macro-assembler-ia32.cc revision 3b9bc31999c9787eb726ecdbfd5796bfdec32a18
13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_IA32
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/bits.h"
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/division-by-constant.h"
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/bootstrapper.h"
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h"
11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/debug/debug.h"
12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/ia32/frames-ia32.h"
13014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/ia32/macro-assembler-ia32.h"
14958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/runtime/runtime.h"
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -------------------------------------------------------------------------
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// MacroAssembler implementation.
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochMacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size,
23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                               CodeObjectRequired create_code_object)
248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    : Assembler(arg_isolate, buffer, size),
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      generating_stub_(false),
263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      has_frame_(false) {
27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (create_code_object == CodeObjectRequired::kYes) {
28014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    code_object_ =
29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Handle<Object>::New(isolate()->heap()->undefined_value(), isolate());
308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Load(Register dst, const Operand& src, Representation r) {
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!r.IsDouble());
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (r.IsInteger8()) {
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movsx_b(dst, src);
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsUInteger8()) {
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movzx_b(dst, src);
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsInteger16()) {
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movsx_w(dst, src);
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsUInteger16()) {
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movzx_w(dst, src);
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(dst, src);
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Store(Register src, const Operand& dst, Representation r) {
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!r.IsDouble());
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (r.IsInteger8() || r.IsUInteger8()) {
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov_b(dst, src);
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsInteger16() || r.IsUInteger16()) {
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov_w(dst, src);
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (r.IsHeapObject()) {
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AssertNotSmi(src);
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (r.IsSmi()) {
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AssertSmi(src);
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(dst, src);
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index) {
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (isolate()->heap()->RootCanBeTreatedAsConstant(index)) {
69014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mov(destination, isolate()->heap()->root_handle(index));
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference roots_array_start =
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::roots_array_start(isolate());
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(destination, Immediate(index));
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(destination, Operand::StaticArray(destination,
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        times_pointer_size,
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        roots_array_start));
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::StoreRoot(Register source,
82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Register scratch,
83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Heap::RootListIndex index) {
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(Heap::RootCanBeWrittenAfterInitialization(index));
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference roots_array_start =
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::roots_array_start(isolate());
87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(scratch, Immediate(index));
88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(Operand::StaticArray(scratch, times_pointer_size, roots_array_start),
89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      source);
90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CompareRoot(Register with,
94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Register scratch,
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Heap::RootListIndex index) {
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference roots_array_start =
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::roots_array_start(isolate());
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(scratch, Immediate(index));
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(with, Operand::StaticArray(scratch,
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                times_pointer_size,
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                roots_array_start));
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) {
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(isolate()->heap()->RootCanBeTreatedAsConstant(index));
107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  cmp(with, isolate()->heap()->root_handle(index));
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CompareRoot(const Operand& with,
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Heap::RootListIndex index) {
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(isolate()->heap()->RootCanBeTreatedAsConstant(index));
114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  cmp(with, isolate()->heap()->root_handle(index));
115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::PushRoot(Heap::RootListIndex index) {
119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(isolate()->heap()->RootCanBeTreatedAsConstant(index));
120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Push(isolate()->heap()->root_handle(index));
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
123109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#define REG(Name) \
124109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  { Register::kCode_##Name }
125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
126109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochstatic const Register saved_regs[] = {REG(eax), REG(ecx), REG(edx)};
127109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
128109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#undef REG
129109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
130109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochstatic const int kNumberOfSavedRegs = sizeof(saved_regs) / sizeof(Register);
131109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
132109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::PushCallerSaved(SaveFPRegsMode fp_mode,
133109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                     Register exclusion1, Register exclusion2,
134109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                     Register exclusion3) {
135109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // We don't allow a GC during a store buffer overflow so there is no need to
136109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // store the registers in any particular way, but we do have to store and
137109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // restore them.
138109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  for (int i = 0; i < kNumberOfSavedRegs; i++) {
139109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Register reg = saved_regs[i];
140109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    if (!reg.is(exclusion1) && !reg.is(exclusion2) && !reg.is(exclusion3)) {
141109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      push(reg);
142109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
143109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
144109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (fp_mode == kSaveFPRegs) {
145109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    sub(esp, Immediate(kDoubleSize * (XMMRegister::kMaxNumRegisters - 1)));
146109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // Save all XMM registers except XMM0.
147109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    for (int i = XMMRegister::kMaxNumRegisters - 1; i > 0; i--) {
148109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      XMMRegister reg = XMMRegister::from_code(i);
149109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      movsd(Operand(esp, (i - 1) * kDoubleSize), reg);
150109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
151109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
152109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
153109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
154109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
155109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                    Register exclusion2, Register exclusion3) {
156109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (fp_mode == kSaveFPRegs) {
157109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // Restore all XMM registers except XMM0.
158109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    for (int i = XMMRegister::kMaxNumRegisters - 1; i > 0; i--) {
159109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      XMMRegister reg = XMMRegister::from_code(i);
160109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      movsd(reg, Operand(esp, (i - 1) * kDoubleSize));
161109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
162109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    add(esp, Immediate(kDoubleSize * (XMMRegister::kMaxNumRegisters - 1)));
163109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
164109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
165109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  for (int i = kNumberOfSavedRegs - 1; i >= 0; i--) {
166109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Register reg = saved_regs[i];
167109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    if (!reg.is(exclusion1) && !reg.is(exclusion2) && !reg.is(exclusion3)) {
168109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      pop(reg);
169109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
1706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
171109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
172109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
173109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::InNewSpace(Register object, Register scratch, Condition cc,
174109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                Label* condition_met,
175109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                Label::Distance distance) {
176109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  const int mask =
177109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      (1 << MemoryChunk::IN_FROM_SPACE) | (1 << MemoryChunk::IN_TO_SPACE);
178109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  CheckPageFlag(object, scratch, mask, cc, condition_met, distance);
1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::RememberedSetHelper(
1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register object,  // Only used for debug checks.
1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register addr,
1853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch,
1863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SaveFPRegsMode save_fp,
1873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MacroAssembler::RememberedSetFinalAction and_then) {
1883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
1903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label ok;
1913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JumpIfNotInNewSpace(object, scratch, &ok, Label::kNear);
1923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int3();
1933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&ok);
1943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load store buffer top.
1963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExternalReference store_buffer =
1973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ExternalReference::store_buffer_top(isolate());
1983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(scratch, Operand::StaticVariable(store_buffer));
1993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Store pointer to buffer.
2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(Operand(scratch, 0), addr);
2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Increment buffer top.
2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(scratch, Immediate(kPointerSize));
2033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Write back new top of buffer.
2043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(Operand::StaticVariable(store_buffer), scratch);
2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Call stub on end of buffer.
2063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for end of buffer.
2073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test(scratch, Immediate(StoreBuffer::kStoreBufferMask));
2083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (and_then == kReturnAtEnd) {
2093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label buffer_overflowed;
2103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    j(equal, &buffer_overflowed, Label::kNear);
2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ret(0);
2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&buffer_overflowed);
2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(and_then == kFallThroughAtEnd);
2153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    j(not_equal, &done, Label::kNear);
2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StoreBufferOverflowStub store_buffer_overflow(isolate(), save_fp);
2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallStub(&store_buffer_overflow);
2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (and_then == kReturnAtEnd) {
2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ret(0);
2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(and_then == kFallThroughAtEnd);
2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&done);
2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::ClampDoubleToUint8(XMMRegister input_reg,
229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                        XMMRegister scratch_reg,
230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                        Register result_reg) {
231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label conv_failure;
233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  xorps(scratch_reg, scratch_reg);
234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cvtsd2si(result_reg, input_reg);
235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  test(result_reg, Immediate(0xFFFFFF00));
236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(zero, &done, Label::kNear);
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(result_reg, Immediate(0x1));
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(overflow, &conv_failure, Label::kNear);
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(result_reg, Immediate(0));
240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  setcc(sign, result_reg);
241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  sub(result_reg, Immediate(1));
242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  and_(result_reg, Immediate(255));
243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  jmp(&done, Label::kNear);
244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&conv_failure);
245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Move(result_reg, Immediate(0));
246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ucomisd(input_reg, scratch_reg);
247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(below, &done, Label::kNear);
248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Move(result_reg, Immediate(255));
249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&done);
250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::ClampUint8(Register reg) {
254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  test(reg, Immediate(0xFFFFFF00));
256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(zero, &done, Label::kNear);
257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  setcc(negative, reg);  // 1 if negative, 0 if positive.
258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  dec_b(reg);  // 0 if negative, 255 if positive.
259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&done);
260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::SlowTruncateToI(Register result_reg,
264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     Register input_reg,
265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     int offset) {
266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleToIStub stub(isolate(), input_reg, result_reg, offset, true);
267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  call(stub.GetCode(), RelocInfo::CODE_TARGET);
268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TruncateDoubleToI(Register result_reg,
272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       XMMRegister input_reg) {
273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cvttsd2si(result_reg, Operand(input_reg));
275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(result_reg, 0x1);
276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(no_overflow, &done, Label::kNear);
277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  sub(esp, Immediate(kDoubleSize));
279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movsd(MemOperand(esp, 0), input_reg);
280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SlowTruncateToI(result_reg, esp, 0);
281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  add(esp, Immediate(kDoubleSize));
282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::DoubleToI(Register result_reg, XMMRegister input_reg,
287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               XMMRegister scratch,
288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               MinusZeroMode minus_zero_mode,
289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Label* lost_precision, Label* is_nan,
290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Label* minus_zero, Label::Distance dst) {
291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!input_reg.is(scratch));
292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cvttsd2si(result_reg, Operand(input_reg));
293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Cvtsi2sd(scratch, Operand(result_reg));
294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ucomisd(scratch, input_reg);
295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(not_equal, lost_precision, dst);
296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(parity_even, is_nan, dst);
297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (minus_zero_mode == FAIL_ON_MINUS_ZERO) {
298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label done;
299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // The integer converted back is equal to the original. We
300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // only have to test if we got -0 as an input.
301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(result_reg, Operand(result_reg));
302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(not_zero, &done, Label::kNear);
303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movmskpd(result_reg, input_reg);
304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Bit 0 contains the sign of the double in input_reg.
305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If input was positive, we are ok and return 0, otherwise
306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // jump to minus_zero.
307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    and_(result_reg, 1);
308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(not_zero, minus_zero, dst);
309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&done);
310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TruncateHeapNumberToI(Register result_reg,
315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register input_reg) {
316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done, slow_case;
317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (CpuFeatures::IsSupported(SSE3)) {
319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CpuFeatureScope scope(this, SSE3);
320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label convert;
321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Use more powerful conversion when sse3 is available.
322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Load x87 register with heap number.
323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Get exponent alone and check for too-big exponent.
325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(result_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset));
326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    and_(result_reg, HeapNumber::kExponentMask);
327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const uint32_t kTooBigExponent =
328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift;
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(Operand(result_reg), Immediate(kTooBigExponent));
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(greater_equal, &slow_case, Label::kNear);
331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Reserve space for 64 bit answer.
333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sub(Operand(esp), Immediate(kDoubleSize));
334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Do conversion, which cannot fail because we checked the exponent.
335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    fisttp_d(Operand(esp, 0));
336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(result_reg, Operand(esp, 0));  // Low word of answer is the result.
337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    add(Operand(esp), Immediate(kDoubleSize));
338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    jmp(&done, Label::kNear);
339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Slow case.
341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&slow_case);
342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (input_reg.is(result_reg)) {
343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Input is clobbered. Restore number from fpu stack
344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      sub(Operand(esp), Immediate(kDoubleSize));
345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      fstp_d(Operand(esp, 0));
346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SlowTruncateToI(result_reg, esp, 0);
347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      add(esp, Immediate(kDoubleSize));
348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      fstp(0);
350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SlowTruncateToI(result_reg, input_reg);
351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cvttsd2si(result_reg, Operand(xmm0));
355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(result_reg, 0x1);
356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(no_overflow, &done, Label::kNear);
357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Check if the input was 0x8000000 (kMinInt).
358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If no, then we got an overflow and we deoptimize.
359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ExternalReference min_int = ExternalReference::address_of_min_int();
360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ucomisd(xmm0, Operand::StaticVariable(min_int));
361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(not_equal, &slow_case, Label::kNear);
362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(parity_even, &slow_case, Label::kNear);  // NaN.
363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    jmp(&done, Label::kNear);
364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Slow case.
366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&slow_case);
367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (input_reg.is(result_reg)) {
368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Input is clobbered. Restore number from double scratch.
369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      sub(esp, Immediate(kDoubleSize));
370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movsd(MemOperand(esp, 0), xmm0);
371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SlowTruncateToI(result_reg, esp, 0);
372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      add(esp, Immediate(kDoubleSize));
373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SlowTruncateToI(result_reg, input_reg);
375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
381958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::LoadUint32(XMMRegister dst, const Operand& src) {
382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(src, Immediate(0));
384958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ExternalReference uint32_bias = ExternalReference::address_of_uint32_bias();
385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Cvtsi2sd(dst, src);
386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(not_sign, &done, Label::kNear);
387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  addsd(dst, Operand::StaticVariable(uint32_bias));
388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::RecordWriteArray(
393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register object,
394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register value,
395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register index,
396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SaveFPRegsMode save_fp,
397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RememberedSetAction remembered_set_action,
398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiCheck smi_check,
399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PointersToHereCheck pointers_to_here_check_for_value) {
4003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // First, check if a write barrier is even needed. The tests below
4013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // catch stores of Smis.
4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Skip barrier if writing a smi.
4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (smi_check == INLINE_SMI_CHECK) {
406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_EQ(0, kSmiTag);
4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    test(value, Immediate(kSmiTagMask));
4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(zero, &done);
4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Array access: calculate the destination address in the same manner as
4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // KeyedStoreIC::GenerateGeneric.  Multiply a smi by 2 to get an offset
4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // into an array of words.
4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register dst = index;
4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lea(dst, Operand(object, index, times_half_pointer_size,
4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   FixedArray::kHeaderSize - kHeapObjectTag));
4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordWrite(object, dst, value, save_fp, remembered_set_action,
419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              OMIT_SMI_CHECK, pointers_to_here_check_for_value);
4203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&done);
4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Clobber clobbered input registers when running with the debug-code flag
4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // turned on to provoke errors.
4253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (emit_debug_code()) {
426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(value, Immediate(bit_cast<int32_t>(kZapValue)));
427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(index, Immediate(bit_cast<int32_t>(kZapValue)));
428257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::RecordWriteField(
4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register object,
4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int offset,
4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register value,
4363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register dst,
4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SaveFPRegsMode save_fp,
4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RememberedSetAction remembered_set_action,
439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiCheck smi_check,
440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PointersToHereCheck pointers_to_here_check_for_value) {
4417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // First, check if a write barrier is even needed. The tests below
4423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // catch stores of Smis.
443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Skip barrier if writing a smi.
4463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (smi_check == INLINE_SMI_CHECK) {
4473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JumpIfSmi(value, &done, Label::kNear);
4483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Although the object register is tagged, the offset is relative to the start
4513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // of the object, so so offset must be a multiple of kPointerSize.
452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsAligned(offset, kPointerSize));
453592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
4543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lea(dst, FieldOperand(object, offset));
4553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (emit_debug_code()) {
4563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label ok;
4573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    test_b(dst, Immediate((1 << kPointerSizeLog2) - 1));
4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(zero, &ok, Label::kNear);
4593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int3();
4603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&ok);
46185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  }
4623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordWrite(object, dst, value, save_fp, remembered_set_action,
464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              OMIT_SMI_CHECK, pointers_to_here_check_for_value);
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&done);
4674515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
4683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Clobber clobbered input registers when running with the debug-code flag
4694515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // turned on to provoke errors.
47044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(value, Immediate(bit_cast<int32_t>(kZapValue)));
472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(dst, Immediate(bit_cast<int32_t>(kZapValue)));
4734515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::RecordWriteForMap(
478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register object,
479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Map> map,
480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch1,
481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch2,
482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SaveFPRegsMode save_fp) {
483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register address = scratch1;
486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register value = scratch2;
4873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (emit_debug_code()) {
488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label ok;
489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    lea(address, FieldOperand(object, HeapObject::kMapOffset));
4903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    test_b(address, Immediate((1 << kPointerSizeLog2) - 1));
491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(zero, &ok, Label::kNear);
492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int3();
493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&ok);
494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!object.is(value));
497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!object.is(address));
498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!value.is(address));
499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertNotSmi(object);
500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!FLAG_incremental_marking) {
502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Compute the address.
506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lea(address, FieldOperand(object, HeapObject::kMapOffset));
507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // A single check of the map's pages interesting flag suffices, since it is
509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // only set during incremental collection, and then it's also guaranteed that
510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the from object's page's interesting flag is also set.  This optimization
511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // relies on the fact that maps can never be in new space.
512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!isolate()->heap()->InNewSpace(*map));
513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckPageFlagForMap(map,
514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      MemoryChunk::kPointersToHereAreInterestingMask,
515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      zero,
516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      &done,
517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      Label::kNear);
518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordWriteStub stub(isolate(), object, value, address, OMIT_REMEMBERED_SET,
520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       save_fp);
521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallStub(&stub);
522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Count number of write barriers in generated code.
526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate()->counters()->write_barriers_static()->Increment();
527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1);
528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Clobber clobbered input registers when running with the debug-code flag
530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // turned on to provoke errors.
531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(value, Immediate(bit_cast<int32_t>(kZapValue)));
533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(scratch1, Immediate(bit_cast<int32_t>(kZapValue)));
534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(scratch2, Immediate(bit_cast<int32_t>(kZapValue)));
535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::RecordWrite(
540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register object,
541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register address,
542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register value,
543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SaveFPRegsMode fp_mode,
544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RememberedSetAction remembered_set_action,
545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiCheck smi_check,
546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PointersToHereCheck pointers_to_here_check_for_value) {
547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!object.is(value));
548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!object.is(address));
549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!value.is(address));
550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertNotSmi(object);
551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (remembered_set_action == OMIT_REMEMBERED_SET &&
5533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      !FLAG_incremental_marking) {
5543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return;
5553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
5583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label ok;
5593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    cmp(value, Operand(address, 0));
5603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(equal, &ok, Label::kNear);
5613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int3();
5623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&ok);
5633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5658defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // First, check if a write barrier is even needed. The tests below
5668defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // catch stores of Smis and stores into young gen.
5678defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Label done;
5688defd9ff6930b4e24729971a61cf7469daf119beSteve Block
5693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (smi_check == INLINE_SMI_CHECK) {
5703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Skip barrier if writing a smi.
5713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JumpIfSmi(value, &done, Label::kNear);
5723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (pointers_to_here_check_for_value != kPointersToHereAreAlwaysInteresting) {
575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CheckPageFlag(value,
576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  value,  // Used as scratch.
577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  MemoryChunk::kPointersToHereAreInterestingMask,
578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  zero,
579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  &done,
580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  Label::kNear);
581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPageFlag(object,
5833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                value,  // Used as scratch.
5843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                MemoryChunk::kPointersFromHereAreInterestingMask,
5853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                zero,
5863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                &done,
5873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                Label::kNear);
5883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordWriteStub stub(isolate(), object, value, address, remembered_set_action,
590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       fp_mode);
5913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallStub(&stub);
5928defd9ff6930b4e24729971a61cf7469daf119beSteve Block
5938defd9ff6930b4e24729971a61cf7469daf119beSteve Block  bind(&done);
5948defd9ff6930b4e24729971a61cf7469daf119beSteve Block
595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Count number of write barriers in generated code.
596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate()->counters()->write_barriers_static()->Increment();
597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1);
598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Clobber clobbered registers when running with the debug-code flag
6008defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // turned on to provoke errors.
60144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(address, Immediate(bit_cast<int32_t>(kZapValue)));
603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(value, Immediate(bit_cast<int32_t>(kZapValue)));
6048defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
6058defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
6068defd9ff6930b4e24729971a61cf7469daf119beSteve Block
607109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::RecordWriteCodeEntryField(Register js_function,
608109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                               Register code_entry,
609109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                               Register scratch) {
610109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  const int offset = JSFunction::kCodeEntryOffset;
611109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
612109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Since a code entry (value) is always in old space, we don't need to update
613109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // remembered set. If incremental marking is off, there is nothing for us to
614109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // do.
615109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (!FLAG_incremental_marking) return;
616109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
617109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(!js_function.is(code_entry));
618109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(!js_function.is(scratch));
619109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(!code_entry.is(scratch));
620109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  AssertNotSmi(js_function);
621109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
622109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (emit_debug_code()) {
623109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Label ok;
624109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    lea(scratch, FieldOperand(js_function, offset));
625109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    cmp(code_entry, Operand(scratch, 0));
626109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    j(equal, &ok, Label::kNear);
627109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    int3();
628109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    bind(&ok);
629109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
630109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
631109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // First, check if a write barrier is even needed. The tests below
632109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // catch stores of Smis and stores into young gen.
633109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Label done;
634109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
635109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  CheckPageFlag(code_entry, scratch,
636109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                MemoryChunk::kPointersToHereAreInterestingMask, zero, &done,
637109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                Label::kNear);
638109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  CheckPageFlag(js_function, scratch,
639109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                MemoryChunk::kPointersFromHereAreInterestingMask, zero, &done,
640109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                Label::kNear);
641109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
642109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Save input registers.
643109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  push(js_function);
644109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  push(code_entry);
645109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
646109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  const Register dst = scratch;
647109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  lea(dst, FieldOperand(js_function, offset));
648109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
649109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Save caller-saved registers.
650109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PushCallerSaved(kDontSaveFPRegs, js_function, code_entry);
651109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
652109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  int argument_count = 3;
653109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PrepareCallCFunction(argument_count, code_entry);
654109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  mov(Operand(esp, 0 * kPointerSize), js_function);
655109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  mov(Operand(esp, 1 * kPointerSize), dst);  // Slot.
656109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  mov(Operand(esp, 2 * kPointerSize),
657109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      Immediate(ExternalReference::isolate_address(isolate())));
658109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
659109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  {
660109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    AllowExternalCallThatCantCauseGC scope(this);
661109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    CallCFunction(
662109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        ExternalReference::incremental_marking_record_write_code_entry_function(
663109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch            isolate()),
664109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        argument_count);
665109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
666109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
667109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Restore caller-saved registers.
668109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PopCallerSaved(kDontSaveFPRegs, js_function, code_entry);
669109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
670109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Restore input registers.
671109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  pop(code_entry);
672109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  pop(js_function);
673109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
674109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  bind(&done);
675109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
6768defd9ff6930b4e24729971a61cf7469daf119beSteve Block
677402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::DebugBreak() {
678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Move(eax, Immediate(0));
679014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(ebx, Immediate(ExternalReference(Runtime::kHandleDebuggerStatement,
680014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                       isolate())));
681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CEntryStub ces(isolate(), 1);
682014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  call(ces.GetCode(), RelocInfo::DEBUGGER_STATEMENT);
683402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Cvtsi2sd(XMMRegister dst, const Operand& src) {
686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  xorps(dst, dst);
687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cvtsi2sd(dst, src);
688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
691109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::Cvtui2ss(XMMRegister dst, Register src, Register tmp) {
692109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Label msb_set_src;
693109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Label jmp_return;
694109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  test(src, src);
695109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  j(sign, &msb_set_src, Label::kNear);
696109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  cvtsi2ss(dst, src);
697109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  jmp(&jmp_return, Label::kNear);
698109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  bind(&msb_set_src);
699109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  mov(tmp, src);
700109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  shr(src, 1);
701109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Recover the least significant bit to avoid rounding errors.
702109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  and_(tmp, Immediate(1));
703109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  or_(src, tmp);
704109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  cvtsi2ss(dst, src);
705109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  addss(dst, dst);
706109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  bind(&jmp_return);
707109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
708109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
7093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::ShlPair(Register high, Register low, uint8_t shift) {
7103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (shift >= 32) {
7113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    mov(high, low);
7123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shl(high, shift - 32);
7133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    xor_(low, low);
7143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
7153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shld(high, low, shift);
7163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shl(low, shift);
7173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
7183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
7193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
7203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::ShlPair_cl(Register high, Register low) {
7213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  shld_cl(high, low);
7223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  shl_cl(low);
7233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label done;
7243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test(ecx, Immediate(0x20));
7253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  j(equal, &done, Label::kNear);
7263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(high, low);
7273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  xor_(low, low);
7283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&done);
7293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
7303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
7313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::ShrPair(Register high, Register low, uint8_t shift) {
7323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (shift >= 32) {
7333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    mov(low, high);
7343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shr(low, shift - 32);
7353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    xor_(high, high);
7363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
7373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shrd(high, low, shift);
7383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shr(high, shift);
7393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
7403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
7413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
7423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::ShrPair_cl(Register high, Register low) {
7433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  shrd_cl(low, high);
7443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  shr_cl(high);
7453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label done;
7463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test(ecx, Immediate(0x20));
7473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  j(equal, &done, Label::kNear);
7483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(low, high);
7493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  xor_(high, high);
7503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&done);
7513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
7523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
7533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::SarPair(Register high, Register low, uint8_t shift) {
7543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (shift >= 32) {
7553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    mov(low, high);
7563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    sar(low, shift - 32);
7573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    sar(high, 31);
7583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
7593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shrd(high, low, shift);
7603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    sar(high, shift);
7613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
7623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
7633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
7643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::SarPair_cl(Register high, Register low) {
7653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  shrd_cl(low, high);
7663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  sar_cl(high);
7673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label done;
7683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test(ecx, Immediate(0x20));
7693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  j(equal, &done, Label::kNear);
7703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(low, high);
7713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  sar(high, 31);
7723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&done);
7733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
774109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
775053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Blockbool MacroAssembler::IsUnsafeImmediate(const Immediate& x) {
776053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  static const int kMaxImmediateBits = 17;
777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!RelocInfo::IsNone(x.rmode_)) return false;
778053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  return !is_intn(x.x_, kMaxImmediateBits);
779053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block}
780053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
781053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::SafeMove(Register dst, const Immediate& x) {
783053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  if (IsUnsafeImmediate(x) && jit_cookie() != 0) {
784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(dst, Immediate(x.x_ ^ jit_cookie()));
785053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block    xor_(dst, jit_cookie());
786053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  } else {
787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(dst, x);
788053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  }
789053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block}
790053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
791053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
792053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Blockvoid MacroAssembler::SafePush(const Immediate& x) {
793053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  if (IsUnsafeImmediate(x) && jit_cookie() != 0) {
794053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block    push(Immediate(x.x_ ^ jit_cookie()));
795053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block    xor_(Operand(esp, 0), Immediate(jit_cookie()));
796053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  } else {
797053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block    push(x);
798053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  }
799053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block}
800053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
801053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpObjectType(Register heap_object,
803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   InstanceType type,
804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   Register map) {
805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(map, FieldOperand(heap_object, HeapObject::kMapOffset));
806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CmpInstanceType(map, type);
807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpInstanceType(Register map, InstanceType type) {
8113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  cmpb(FieldOperand(map, Map::kInstanceTypeOffset), Immediate(type));
812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::CheckFastElements(Register map,
8163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                       Label* fail,
8173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                       Label::Distance distance) {
818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_ELEMENTS == 2);
821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
8223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmpb(FieldOperand(map, Map::kBitField2Offset),
8233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch       Immediate(Map::kMaximumBitField2FastHoleyElementValue));
8243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(above, fail, distance);
8253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
8263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckFastObjectElements(Register map,
8293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Label* fail,
8303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Label::Distance distance) {
831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_ELEMENTS == 2);
834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
8353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmpb(FieldOperand(map, Map::kBitField2Offset),
8363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch       Immediate(Map::kMaximumBitField2FastHoleySmiElementValue));
8373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(below_equal, fail, distance);
8383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  cmpb(FieldOperand(map, Map::kBitField2Offset),
8393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch       Immediate(Map::kMaximumBitField2FastHoleyElementValue));
8403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  j(above, fail, distance);
8413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
8423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
8433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CheckFastSmiElements(Register map,
845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          Label* fail,
846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          Label::Distance distance) {
847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
8493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmpb(FieldOperand(map, Map::kBitField2Offset),
8503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch       Immediate(Map::kMaximumBitField2FastHoleySmiElementValue));
8513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(above, fail, distance);
8523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
8533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::StoreNumberToDoubleElements(
8563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register maybe_number,
8573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register elements,
8583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register key,
8593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch1,
8603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    XMMRegister scratch2,
8613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* fail,
862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int elements_offset) {
863014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label smi_value, done;
8643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpIfSmi(maybe_number, &smi_value, Label::kNear);
8653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckMap(maybe_number,
8673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           isolate()->factory()->heap_number_map(),
8683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           fail,
8693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           DONT_DO_SMI_CHECK);
8703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
871014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Double value, turn potential sNaN into qNaN.
872014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Move(scratch2, 1.0);
873014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mulsd(scratch2, FieldOperand(maybe_number, HeapNumber::kValueOffset));
874014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  jmp(&done, Label::kNear);
8753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&smi_value);
8773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Value is a smi. Convert to a double and store.
8783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Preserve original value.
8793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(scratch1, maybe_number);
8803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SmiUntag(scratch1);
881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Cvtsi2sd(scratch2, scratch1);
882014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&done);
883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movsd(FieldOperand(elements, key, times_4,
884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     FixedDoubleArray::kHeaderSize - elements_offset),
885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        scratch2);
8863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
8873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CompareMap(Register obj, Handle<Map> map) {
8903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmp(FieldOperand(obj, HeapObject::kMapOffset), map);
8913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
8923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::CheckMap(Register obj,
8953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Handle<Map> map,
8963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Label* fail,
897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              SmiCheckType smi_check_type) {
898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (smi_check_type == DO_SMI_CHECK) {
899257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    JumpIfSmi(obj, fail);
9003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
9013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompareMap(obj, map);
9033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  j(not_equal, fail);
9043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
9053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
907958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::DispatchWeakMap(Register obj, Register scratch1,
908958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                     Register scratch2, Handle<WeakCell> cell,
909958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                     Handle<Code> success,
910958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                     SmiCheckType smi_check_type) {
911257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label fail;
912257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (smi_check_type == DO_SMI_CHECK) {
913257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    JumpIfSmi(obj, &fail);
914257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
915958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  mov(scratch1, FieldOperand(obj, HeapObject::kMapOffset));
916958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CmpWeakValue(scratch1, cell, scratch2);
917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(equal, success);
918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&fail);
920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
923e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeCondition MacroAssembler::IsObjectStringType(Register heap_object,
924e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                             Register map,
925e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                             Register instance_type) {
926e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  mov(map, FieldOperand(heap_object, HeapObject::kMapOffset));
927e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
92869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kNotStringTag != 0);
929e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  test(instance_type, Immediate(kIsNotStringMask));
930e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  return zero;
931e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
932e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
933e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochCondition MacroAssembler::IsObjectNameType(Register heap_object,
935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register map,
936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register instance_type) {
937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(map, FieldOperand(heap_object, HeapObject::kMapOffset));
938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
9393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  cmpb(instance_type, Immediate(LAST_NAME_TYPE));
940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return below_equal;
941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::FCmp() {
945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fucomip();
946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fstp(0);
947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertNumber(Register object) {
951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label ok;
953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    JumpIfSmi(object, &ok);
954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(FieldOperand(object, HeapObject::kMapOffset),
955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate()->factory()->heap_number_map());
956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, kOperandNotANumber);
957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&ok);
9583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::AssertNotNumber(Register object) {
9623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (emit_debug_code()) {
9633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    test(object, Immediate(kSmiTagMask));
9643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Check(not_equal, kOperandIsANumber);
9653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    cmp(FieldOperand(object, HeapObject::kMapOffset),
9663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        isolate()->factory()->heap_number_map());
9673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Check(not_equal, kOperandIsANumber);
9683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
9693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertSmi(Register object) {
972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(object, Immediate(kSmiTagMask));
974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, kOperandIsNotASmi);
975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertString(Register object) {
980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(object, Immediate(kSmiTagMask));
982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kOperandIsASmiAndNotAString);
983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    push(object);
984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(object, FieldOperand(object, HeapObject::kMapOffset));
985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CmpInstanceType(object, FIRST_NONSTRING_TYPE);
986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    pop(object);
987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(below, kOperandIsNotAString);
988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertName(Register object) {
993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(object, Immediate(kSmiTagMask));
995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kOperandIsASmiAndNotAName);
996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    push(object);
997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(object, FieldOperand(object, HeapObject::kMapOffset));
998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CmpInstanceType(object, LAST_NAME_TYPE);
999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    pop(object);
1000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(below_equal, kOperandIsNotAName);
1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1005014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::AssertFunction(Register object) {
1006014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (emit_debug_code()) {
1007014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    test(object, Immediate(kSmiTagMask));
1008014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(not_equal, kOperandIsASmiAndNotAFunction);
1009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(object);
1010014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CmpObjectType(object, JS_FUNCTION_TYPE, object);
1011014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Pop(object);
1012014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(equal, kOperandIsNotAFunction);
1013014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1014014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1015014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1016014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1017014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::AssertBoundFunction(Register object) {
1018014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (emit_debug_code()) {
1019014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    test(object, Immediate(kSmiTagMask));
1020014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(not_equal, kOperandIsASmiAndNotABoundFunction);
1021014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(object);
1022014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CmpObjectType(object, JS_BOUND_FUNCTION_TYPE, object);
1023014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Pop(object);
1024014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(equal, kOperandIsNotABoundFunction);
1025014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1026014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1027014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1028014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1029109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::AssertReceiver(Register object) {
1030109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (emit_debug_code()) {
1031109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    test(object, Immediate(kSmiTagMask));
1032109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Check(not_equal, kOperandIsASmiAndNotAReceiver);
1033109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Push(object);
1034109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
1035109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    CmpObjectType(object, FIRST_JS_RECEIVER_TYPE, object);
1036109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Pop(object);
1037109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Check(above_equal, kOperandIsNotAReceiver);
1038109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
1039109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
1040109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1041109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertUndefinedOrAllocationSite(Register object) {
1043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
1044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label done_checking;
1045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AssertNotSmi(object);
1046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(object, isolate()->factory()->undefined_value());
1047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(equal, &done_checking);
1048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(FieldOperand(object, 0),
1049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Immediate(isolate()->factory()->allocation_site_map()));
1050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Assert(equal, kExpectedUndefinedOrCell);
1051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&done_checking);
1052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1053402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
1054402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1055402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertNotSmi(Register object) {
1057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(object, Immediate(kSmiTagMask));
1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kOperandIsASmi);
1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1061756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
1062756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
10633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::StubPrologue(StackFrame::Type type) {
1064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  push(ebp);  // Caller's frame pointer.
1065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(ebp, esp);
10663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  push(Immediate(Smi::FromInt(type)));
106780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
106880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Prologue(bool code_pre_aging) {
1070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PredictableCodeSizeScope predictible_code_size_scope(this,
1071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kNoCodeAgeSequenceLength);
1072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (code_pre_aging) {
1073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Pre-age the code.
1074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    call(isolate()->builtins()->MarkCodeAsExecutedOnce(),
1075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        RelocInfo::CODE_AGE_SEQUENCE);
1076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Nop(kNoCodeAgeSequenceLength - Assembler::kCallInstructionLength);
1077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    push(ebp);  // Caller's frame pointer.
1079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(ebp, esp);
1080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    push(esi);  // Callee's context.
1081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    push(edi);  // Callee's JS function.
1082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
10836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
10846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1086014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::EmitLoadTypeFeedbackVector(Register vector) {
1087014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(vector, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1088014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(vector, FieldOperand(vector, JSFunction::kSharedFunctionInfoOffset));
1089014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(vector, FieldOperand(vector, SharedFunctionInfo::kFeedbackVectorOffset));
1090014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1091014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1092014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1093958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::EnterFrame(StackFrame::Type type,
1094958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                bool load_constant_pool_pointer_reg) {
1095958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Out-of-line constant pool not implemented on ia32.
1096958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  UNREACHABLE();
1097958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1098958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1099958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::EnterFrame(StackFrame::Type type) {
1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(ebp);
11023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(ebp, esp);
1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(Immediate(Smi::FromInt(type)));
11043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (type == StackFrame::INTERNAL) {
11053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    push(Immediate(CodeObject()));
11063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
110744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
110844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    cmp(Operand(esp, 0), Immediate(isolate()->factory()->undefined_value()));
1109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kCodeObjectNotProperlyPatched);
1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LeaveFrame(StackFrame::Type type) {
111544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
11163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    cmp(Operand(ebp, CommonFrameConstants::kContextOrFrameTypeOffset),
1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Immediate(Smi::FromInt(type)));
1118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, kStackFrameTypesMustMatch);
1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  leave();
1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
112380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
112480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::EnterExitFramePrologue() {
11253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up the frame structure on the stack.
11263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(+2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement);
11273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(+1 * kPointerSize, ExitFrameConstants::kCallerPCOffset);
11283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset);
1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(ebp);
11303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(ebp, esp);
1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
113280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Reserve room for entry stack pointer and push the code object.
11333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  push(Immediate(Smi::FromInt(StackFrame::EXIT)));
11343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(-2 * kPointerSize, ExitFrameConstants::kSPOffset);
1135402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  push(Immediate(0));  // Saved entry sp, patched before call.
11363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(-3 * kPointerSize, ExitFrameConstants::kCodeOffset);
1137402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  push(Immediate(CodeObject()));  // Accessed from ExitFrame::code_slot.
1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Save the frame pointer and the context in top.
1140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress, isolate());
1141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference context_address(Isolate::kContextAddress, isolate());
1142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ExternalReference c_function_address(Isolate::kCFunctionAddress, isolate());
1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(Operand::StaticVariable(c_entry_fp_address), ebp);
1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(Operand::StaticVariable(context_address), esi);
1145958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  mov(Operand::StaticVariable(c_function_address), ebx);
1146d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid MacroAssembler::EnterExitFrameEpilogue(int argc, bool save_doubles) {
1150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Optionally save all XMM registers.
1151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (save_doubles) {
1152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int space = XMMRegister::kMaxNumRegisters * kDoubleSize +
1153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                argc * kPointerSize;
11543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sub(esp, Immediate(space));
11553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    const int offset = -ExitFrameConstants::kFixedFrameSizeFromFp;
1156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
1157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      XMMRegister reg = XMMRegister::from_code(i);
1158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movsd(Operand(ebp, offset - ((i + 1) * kDoubleSize)), reg);
1159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
11613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sub(esp, Immediate(argc * kPointerSize));
1162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the required frame alignment for the OS.
1165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kFrameAlignment = base::OS::ActivationFrameAlignment();
1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (kFrameAlignment > 0) {
1167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(base::bits::IsPowerOfTwo32(kFrameAlignment));
1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    and_(esp, -kFrameAlignment);
1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the saved entry sp.
1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(Operand(ebp, ExitFrameConstants::kSPOffset), esp);
1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1176109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::EnterExitFrame(int argc, bool save_doubles) {
117780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  EnterExitFramePrologue();
1178d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
11793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up argc and argv in callee-saved registers.
1180d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
11813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(edi, eax);
1182d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  lea(esi, Operand(ebp, eax, times_4, offset));
1183d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
118444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Reserve space for argc, argv and isolate.
1185109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  EnterExitFrameEpilogue(argc, save_doubles);
1186d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1188d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
11898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid MacroAssembler::EnterApiExitFrame(int argc) {
119080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  EnterExitFramePrologue();
1191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  EnterExitFrameEpilogue(argc, false);
1192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1193d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1194d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LeaveExitFrame(bool save_doubles, bool pop_arguments) {
1196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Optionally restore all XMM registers.
1197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (save_doubles) {
11983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    const int offset = -ExitFrameConstants::kFixedFrameSizeFromFp;
1199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
1200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      XMMRegister reg = XMMRegister::from_code(i);
1201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movsd(reg, Operand(ebp, offset - ((i + 1) * kDoubleSize)));
1202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (pop_arguments) {
1206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Get the return address from the stack and restore the frame pointer.
1207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mov(ecx, Operand(ebp, 1 * kPointerSize));
1208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mov(ebp, Operand(ebp, 0 * kPointerSize));
1209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Pop the arguments and the receiver from the caller stack.
1211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    lea(esp, Operand(esi, 1 * kPointerSize));
1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Push the return address to get ready to return.
1214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    push(ecx);
1215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
1216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Otherwise just leave the exit frame.
1217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    leave();
1218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
12198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LeaveExitFrameEpilogue(true);
12218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
12228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::LeaveExitFrameEpilogue(bool restore_context) {
1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Restore current context from top and clear it in debug mode.
1226589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ExternalReference context_address(Isolate::kContextAddress, isolate());
1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (restore_context) {
1228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(esi, Operand::StaticVariable(context_address));
1229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(Operand::StaticVariable(context_address), Immediate(0));
1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clear the top frame.
1235589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress,
123644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       isolate());
1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(Operand::StaticVariable(c_entry_fp_address), Immediate(0));
1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::LeaveApiExitFrame(bool restore_context) {
12423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(esp, ebp);
12438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  pop(ebp);
12448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LeaveExitFrameEpilogue(restore_context);
12468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
12478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
12488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::PushStackHandler() {
1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Adjust this code if not the case.
1251014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(StackHandlerConstants::kSize == 1 * kPointerSize);
125269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
12533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Link the current handler as the next handler.
12553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
12563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  push(Operand::StaticVariable(handler_address));
1257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
12583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set this new handler as the current one.
12593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(Operand::StaticVariable(handler_address), esp);
1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::PopStackHandler() {
126469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
12653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
12663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  pop(Operand::StaticVariable(handler_address));
12673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(esp, Immediate(StackHandlerConstants::kSize - kPointerSize));
12683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
12693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
1272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                            Register scratch1,
1273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                            Register scratch2,
1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            Label* miss) {
1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label same_contexts;
1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!holder_reg.is(scratch1));
1278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!holder_reg.is(scratch2));
1279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!scratch1.is(scratch2));
1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Load current lexical context from the active StandardFrame, which
12823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // may require crawling past STUB frames.
12833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label load_context;
12843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label has_context;
12853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(scratch2, ebp);
12863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&load_context);
12873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(scratch1,
12883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      MemOperand(scratch2, CommonFrameConstants::kContextOrFrameTypeOffset));
12893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  JumpIfNotSmi(scratch1, &has_context);
12903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(scratch2, MemOperand(scratch2, CommonFrameConstants::kCallerFPOffset));
12913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  jmp(&load_context);
12923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&has_context);
1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // When generating debug code, make sure the lexical context is set.
129544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
1296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(scratch1, Immediate(0));
1297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kWeShouldNotHaveAnEmptyLexicalContext);
1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the native context of the current context.
1300014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(scratch1, ContextOperand(scratch1, Context::NATIVE_CONTEXT_INDEX));
1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check the context is a native context.
130344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
1304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Read the first word and compare to native_context_map.
1305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(FieldOperand(scratch1, HeapObject::kMapOffset),
1306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate()->factory()->native_context_map());
1307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext);
1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if both contexts are the same.
1311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(scratch1, FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
1312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(equal, &same_contexts);
1313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compare security tokens, save holder_reg on the stack so we can use it
1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // as a temporary register.
1316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
1317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the security token in the calling global object is
1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // compatible with the security token in the receiving global
1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object.
1320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(scratch2,
1321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check the context is a native context.
132444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
1325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(scratch2, isolate()->factory()->null_value());
1326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kJSGlobalProxyContextShouldNotBeNull);
1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Read the first word and compare to native_context_map(),
1329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(FieldOperand(scratch2, HeapObject::kMapOffset),
1330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate()->factory()->native_context_map());
1331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext);
1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int token_offset = Context::kHeaderSize +
1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     Context::SECURITY_TOKEN_INDEX * kPointerSize;
1336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(scratch1, FieldOperand(scratch1, token_offset));
1337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(scratch1, FieldOperand(scratch2, token_offset));
1338257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_equal, miss);
1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&same_contexts);
1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Compute the hash code from the untagged key.  This must be kept in sync with
1345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ComputeIntegerHash in utils.h and KeyedLoadGenericStub in
1346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// code-stub-hydrogen.cc
1347c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch//
1348c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch// Note: r0 will contain hash code
1349c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdochvoid MacroAssembler::GetNumberHash(Register r0, Register scratch) {
1350c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // Xor original key with a seed.
1351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (serializer_enabled()) {
13523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ExternalReference roots_array_start =
13533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ExternalReference::roots_array_start(isolate());
1354c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    mov(scratch, Immediate(Heap::kHashSeedRootIndex));
13553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(scratch,
13563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Operand::StaticArray(scratch, times_pointer_size, roots_array_start));
1357c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    SmiUntag(scratch);
13583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    xor_(r0, scratch);
1359c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  } else {
1360c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    int32_t seed = isolate()->heap()->HashSeed();
13613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    xor_(r0, Immediate(seed));
1362c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  }
1363c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
1364c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = ~hash + (hash << 15);
1365c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  mov(scratch, r0);
1366c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  not_(r0);
1367c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  shl(scratch, 15);
13683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(r0, scratch);
1369c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash ^ (hash >> 12);
1370c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  mov(scratch, r0);
1371c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  shr(scratch, 12);
13723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  xor_(r0, scratch);
1373c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash + (hash << 2);
1374c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  lea(r0, Operand(r0, r0, times_4, 0));
1375c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash ^ (hash >> 4);
1376c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  mov(scratch, r0);
1377c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  shr(scratch, 4);
13783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  xor_(r0, scratch);
1379c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash * 2057;
1380c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  imul(r0, r0, 2057);
1381c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash ^ (hash >> 16);
1382c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  mov(scratch, r0);
1383c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  shr(scratch, 16);
13843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  xor_(r0, scratch);
1385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  and_(r0, 0x3fffffff);
1386c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch}
1387c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
1388c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
1389c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
13903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::LoadFromNumberDictionary(Label* miss,
13913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register elements,
13923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register key,
13933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register r0,
13943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register r1,
13953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register r2,
13963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register result) {
13973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Register use:
13983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
13993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // elements - holds the slow-case elements of the receiver and is unchanged.
14003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
14013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // key      - holds the smi key on entry and is unchanged.
14023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
14033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Scratch registers:
14043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
14053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // r0 - holds the untagged key on entry and holds the hash once computed.
14063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
14073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // r1 - used to hold the capacity mask of the dictionary
14083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
14093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // r2 - used for the index into the dictionary.
14103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
14113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // result - holds the result on exit if the load succeeds and we fall through.
14123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
14133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label done;
14143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1415c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  GetNumberHash(r0, r1);
14163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
14173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Compute capacity mask.
1418c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  mov(r1, FieldOperand(elements, SeededNumberDictionary::kCapacityOffset));
14193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  shr(r1, kSmiTagSize);  // convert smi to int
14203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  dec(r1);
14213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
14223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Generate an unrolled loop that performs a few probes before giving up.
1423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < kNumberDictionaryProbes; i++) {
14243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Use r2 for index calculations and keep the hash intact in r0.
14253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    mov(r2, r0);
14263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Compute the masked index: (hash + i + i * i) & mask.
14273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (i > 0) {
14283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      add(r2, Immediate(SeededNumberDictionary::GetProbeOffset(i)));
14293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
14303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    and_(r2, r1);
14313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
14323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Scale the index by multiplying by the entry size.
1433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SeededNumberDictionary::kEntrySize == 3);
14343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    lea(r2, Operand(r2, r2, times_2, 0));  // r2 = r2 * 3
14353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
14363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Check if the key matches.
14373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    cmp(key, FieldOperand(elements,
14383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          r2,
14393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          times_pointer_size,
1440c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                          SeededNumberDictionary::kElementsStartOffset));
1441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (i != (kNumberDictionaryProbes - 1)) {
14423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      j(equal, &done);
14433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
14443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      j(not_equal, miss);
14453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
14463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
14473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
14483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bind(&done);
1449958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check that the value is a field property.
14503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const int kDetailsOffset =
1451c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize;
1452014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(DATA, 0);
14533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset),
1454589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch       Immediate(PropertyDetails::TypeField::kMask << kSmiTagSize));
14553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  j(not_zero, miss);
14563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
14573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Get the value at the masked, scaled index.
14583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const int kValueOffset =
1459c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      SeededNumberDictionary::kElementsStartOffset + kPointerSize;
14603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  mov(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset));
14613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
14623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
14633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LoadAllocationTopHelper(Register result,
1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register scratch,
1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             AllocationFlags flags) {
1467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_top =
1468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationTopReference(isolate(), flags);
1469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Just return if allocation top is already known.
1471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((flags & RESULT_CONTAINS_TOP) != 0) {
1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // No use of scratch if allocation top is provided.
1473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(scratch.is(no_reg));
1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Assert that result actually contains top on entry.
1476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(result, Operand::StaticVariable(allocation_top));
1477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, kUnexpectedAllocationTop);
1478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Move address of new object to result. Use scratch register if available.
1483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (scratch.is(no_reg)) {
1484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(result, Operand::StaticVariable(allocation_top));
1485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(scratch, Immediate(allocation_top));
1487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(result, Operand(scratch, 0));
1488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::UpdateAllocationTopHelper(Register result_end,
1493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register scratch,
1494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               AllocationFlags flags) {
149544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
1496d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    test(result_end, Immediate(kObjectAlignmentMask));
1497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(zero, kUnalignedAllocationInNewSpace);
1498d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1499d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_top =
1501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationTopReference(isolate(), flags);
1502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update new top. Use scratch if available.
1504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (scratch.is(no_reg)) {
1505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(Operand::StaticVariable(allocation_top), result_end);
1506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(Operand(scratch, 0), result_end);
1508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Allocate(int object_size,
1513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result,
1514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result_end,
1515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register scratch,
1516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Label* gc_required,
1517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              AllocationFlags flags) {
1518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0);
1519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(object_size <= Page::kMaxRegularHeapObjectSize);
15205913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  if (!FLAG_inline_new) {
152144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (emit_debug_code()) {
15225913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // Trash the registers to simulate an allocation failure.
15235913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      mov(result, Immediate(0x7091));
15245913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (result_end.is_valid()) {
15255913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        mov(result_end, Immediate(0x7191));
15265913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
15275913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (scratch.is_valid()) {
15285913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        mov(scratch, Immediate(0x7291));
15295913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
15305913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    }
15315913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    jmp(gc_required);
15325913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    return;
15335913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
1534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result.is(result_end));
1535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load address of new object into result.
15378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LoadAllocationTopHelper(result, scratch, flags);
1538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_limit =
1540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationLimitReference(isolate(), flags);
1541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Align the next allocation. Storing the filler map without checking top is
1543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // safe in new-space because the limit of the heap is aligned there.
1544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
1545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
1546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label aligned;
1547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(result, Immediate(kDoubleAlignmentMask));
1548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(zero, &aligned, Label::kNear);
1549014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if ((flags & PRETENURE) != 0) {
1550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cmp(result, Operand::StaticVariable(allocation_limit));
1551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      j(above_equal, gc_required);
1552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(Operand(result, 0),
1554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Immediate(isolate()->factory()->one_pointer_filler_map()));
1555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    add(result, Immediate(kDoubleSize / 2));
1556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&aligned);
1557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Calculate new top and bail out if space is exhausted.
1560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register top_reg = result_end.is_valid() ? result_end : result;
15611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (!top_reg.is(result)) {
15621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    mov(top_reg, result);
1563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
15643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(top_reg, Immediate(object_size));
1565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(carry, gc_required);
1566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(top_reg, Operand::StaticVariable(allocation_limit));
1567257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(above, gc_required);
1568e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1569e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Update allocation top.
1570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UpdateAllocationTopHelper(top_reg, scratch, flags);
1571bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1572bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Tag result if requested.
1573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool tag_result = (flags & TAG_OBJECT) != 0;
1574bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (top_reg.is(result)) {
1575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (tag_result) {
15763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      sub(result, Immediate(object_size - kHeapObjectTag));
1577bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    } else {
15783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      sub(result, Immediate(object_size));
1579bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    }
1580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (tag_result) {
1581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kHeapObjectTag == 1);
1582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    inc(result);
1583bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
1584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Allocate(int header_size,
1588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              ScaleFactor element_size,
1589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register element_count,
1590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              RegisterValueType element_count_type,
1591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result,
1592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result_end,
1593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register scratch,
1594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Label* gc_required,
1595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              AllocationFlags flags) {
1596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((flags & SIZE_IN_WORDS) == 0);
15975913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  if (!FLAG_inline_new) {
159844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (emit_debug_code()) {
15995913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // Trash the registers to simulate an allocation failure.
16005913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      mov(result, Immediate(0x7091));
16015913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      mov(result_end, Immediate(0x7191));
16025913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (scratch.is_valid()) {
16035913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        mov(scratch, Immediate(0x7291));
16045913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
16055913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // Register element_count is not modified by the function.
16065913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    }
16075913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    jmp(gc_required);
16085913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    return;
16095913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
1610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result.is(result_end));
1611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load address of new object into result.
16138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LoadAllocationTopHelper(result, scratch, flags);
1614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_limit =
1616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationLimitReference(isolate(), flags);
1617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Align the next allocation. Storing the filler map without checking top is
1619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // safe in new-space because the limit of the heap is aligned there.
1620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
1621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
1622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label aligned;
1623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(result, Immediate(kDoubleAlignmentMask));
1624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(zero, &aligned, Label::kNear);
1625014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if ((flags & PRETENURE) != 0) {
1626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cmp(result, Operand::StaticVariable(allocation_limit));
1627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      j(above_equal, gc_required);
1628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(Operand(result, 0),
1630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Immediate(isolate()->factory()->one_pointer_filler_map()));
1631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    add(result, Immediate(kDoubleSize / 2));
1632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&aligned);
1633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
16341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Calculate new top and bail out if space is exhausted.
16361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // We assume that element_count*element_size + header_size does not
16371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // overflow.
1638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (element_count_type == REGISTER_VALUE_IS_SMI) {
1639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(static_cast<ScaleFactor>(times_2 - 1) == times_1);
1640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(static_cast<ScaleFactor>(times_4 - 1) == times_2);
1641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(static_cast<ScaleFactor>(times_8 - 1) == times_4);
1642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(element_size >= times_2);
1643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kSmiTagSize == 1);
1644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    element_size = static_cast<ScaleFactor>(element_size - 1);
1645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(element_count_type == REGISTER_VALUE_IS_INT32);
1647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
16481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  lea(result_end, Operand(element_count, element_size, header_size));
16493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(result_end, result);
16501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  j(carry, gc_required);
1651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(result_end, Operand::StaticVariable(allocation_limit));
1652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(above, gc_required);
1653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((flags & TAG_OBJECT) != 0) {
1655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kHeapObjectTag == 1);
1656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    inc(result);
1657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1658e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1659e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Update allocation top.
1660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UpdateAllocationTopHelper(result_end, scratch, flags);
1661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Allocate(Register object_size,
1665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result,
1666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result_end,
1667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register scratch,
1668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Label* gc_required,
1669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              AllocationFlags flags) {
1670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0);
16715913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  if (!FLAG_inline_new) {
167244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (emit_debug_code()) {
16735913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // Trash the registers to simulate an allocation failure.
16745913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      mov(result, Immediate(0x7091));
16755913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      mov(result_end, Immediate(0x7191));
16765913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (scratch.is_valid()) {
16775913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        mov(scratch, Immediate(0x7291));
16785913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
16795913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // object_size is left unchanged by this function.
16805913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    }
16815913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    jmp(gc_required);
16825913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    return;
16835913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
1684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result.is(result_end));
1685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load address of new object into result.
16878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LoadAllocationTopHelper(result, scratch, flags);
1688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_limit =
1690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationLimitReference(isolate(), flags);
1691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Align the next allocation. Storing the filler map without checking top is
1693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // safe in new-space because the limit of the heap is aligned there.
1694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
1695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
1696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label aligned;
1697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(result, Immediate(kDoubleAlignmentMask));
1698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(zero, &aligned, Label::kNear);
1699014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if ((flags & PRETENURE) != 0) {
1700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cmp(result, Operand::StaticVariable(allocation_limit));
1701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      j(above_equal, gc_required);
1702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(Operand(result, 0),
1704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Immediate(isolate()->factory()->one_pointer_filler_map()));
1705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    add(result, Immediate(kDoubleSize / 2));
1706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&aligned);
1707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Calculate new top and bail out if space is exhausted.
1710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!object_size.is(result_end)) {
1711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(result_end, object_size);
1712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
17133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(result_end, result);
1714257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(carry, gc_required);
1715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(result_end, Operand::StaticVariable(allocation_limit));
1716257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(above, gc_required);
1717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Tag result if requested.
1719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((flags & TAG_OBJECT) != 0) {
1720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kHeapObjectTag == 1);
1721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    inc(result);
1722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1723e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1724e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Update allocation top.
1725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UpdateAllocationTopHelper(result_end, scratch, flags);
1726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::AllocateHeapNumber(Register result,
17303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                        Register scratch1,
17313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                        Register scratch2,
1732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        Label* gc_required,
1733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        MutableMode mode) {
17343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Allocate heap number in new space.
1735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(HeapNumber::kSize, result, scratch1, scratch2, gc_required,
1736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           TAG_OBJECT);
1737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Map> map = mode == MUTABLE
1739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ? isolate()->factory()->mutable_heap_number_map()
1740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : isolate()->factory()->heap_number_map();
17413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
17423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Set the map.
1743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(FieldOperand(result, HeapObject::kMapOffset), Immediate(map));
17443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
17453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
17463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1747d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::AllocateTwoByteString(Register result,
1748d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                           Register length,
1749d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                           Register scratch1,
1750d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                           Register scratch2,
1751d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                           Register scratch3,
1752d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                           Label* gc_required) {
1753d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Calculate the number of bytes needed for the characters in the string while
1754d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // observing object alignment.
1755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
1756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(kShortSize == 2);
1757e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // scratch1 = length * 2 + kObjectAlignmentMask.
1758e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  lea(scratch1, Operand(length, length, times_1, kObjectAlignmentMask));
17593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(scratch1, Immediate(~kObjectAlignmentMask));
1760d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1761d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Allocate two byte string in new space.
1762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(SeqTwoByteString::kHeaderSize,
1763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           times_1,
1764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           scratch1,
1765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           REGISTER_VALUE_IS_INT32,
1766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           result,
1767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           scratch2,
1768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           scratch3,
1769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           gc_required,
1770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           TAG_OBJECT);
1771d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1772d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Set the map, length and hash field.
1773d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  mov(FieldOperand(result, HeapObject::kMapOffset),
177444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Immediate(isolate()->factory()->string_map()));
17756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  mov(scratch1, length);
17766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  SmiTag(scratch1);
17776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  mov(FieldOperand(result, String::kLengthOffset), scratch1);
1778d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  mov(FieldOperand(result, String::kHashFieldOffset),
1779d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Immediate(String::kEmptyHashField));
1780d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1781d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1782d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AllocateOneByteString(Register result, Register length,
1784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register scratch1, Register scratch2,
1785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register scratch3,
1786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Label* gc_required) {
1787d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Calculate the number of bytes needed for the characters in the string while
1788d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // observing object alignment.
1789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0);
1790d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  mov(scratch1, length);
1791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(kCharSize == 1);
17923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(scratch1, Immediate(kObjectAlignmentMask));
17933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(scratch1, Immediate(~kObjectAlignmentMask));
1794d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Allocate one-byte string in new space.
1796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(SeqOneByteString::kHeaderSize,
1797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           times_1,
1798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           scratch1,
1799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           REGISTER_VALUE_IS_INT32,
1800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           result,
1801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           scratch2,
1802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           scratch3,
1803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           gc_required,
1804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           TAG_OBJECT);
1805d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1806d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Set the map, length and hash field.
1807d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  mov(FieldOperand(result, HeapObject::kMapOffset),
1808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Immediate(isolate()->factory()->one_byte_string_map()));
18096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  mov(scratch1, length);
18106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  SmiTag(scratch1);
18116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  mov(FieldOperand(result, String::kLengthOffset), scratch1);
1812d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  mov(FieldOperand(result, String::kHashFieldOffset),
1813d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Immediate(String::kEmptyHashField));
1814d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1815d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1816d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AllocateOneByteString(Register result, int length,
1818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register scratch1, Register scratch2,
1819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Label* gc_required) {
1820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(length > 0);
18219ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick
1822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Allocate one-byte string in new space.
1823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(SeqOneByteString::SizeFor(length), result, scratch1, scratch2,
1824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           gc_required, TAG_OBJECT);
18259ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick
18269ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  // Set the map, length and hash field.
18279ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  mov(FieldOperand(result, HeapObject::kMapOffset),
1828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Immediate(isolate()->factory()->one_byte_string_map()));
18299ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  mov(FieldOperand(result, String::kLengthOffset),
18309ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick      Immediate(Smi::FromInt(length)));
18319ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  mov(FieldOperand(result, String::kHashFieldOffset),
18329ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick      Immediate(String::kEmptyHashField));
18339ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick}
18349ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick
18359ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick
1836589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid MacroAssembler::AllocateTwoByteConsString(Register result,
1837d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                        Register scratch1,
1838d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                        Register scratch2,
1839d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                        Label* gc_required) {
1840d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Allocate heap number in new space.
1841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
1842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           TAG_OBJECT);
1843d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1844d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Set the map. The other fields are left uninitialized.
1845d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  mov(FieldOperand(result, HeapObject::kMapOffset),
184644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Immediate(isolate()->factory()->cons_string_map()));
1847d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1848d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1849d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AllocateOneByteConsString(Register result,
1851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register scratch1,
1852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register scratch2,
1853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Label* gc_required) {
1854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(ConsString::kSize,
1855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           result,
1856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           scratch1,
1857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           scratch2,
1858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           gc_required,
1859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           TAG_OBJECT);
1860d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1861d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Set the map. The other fields are left uninitialized.
1862d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  mov(FieldOperand(result, HeapObject::kMapOffset),
1863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Immediate(isolate()->factory()->cons_one_byte_string_map()));
1864d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1865d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1866b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1867589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid MacroAssembler::AllocateTwoByteSlicedString(Register result,
186869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                          Register scratch1,
186969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                          Register scratch2,
187069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                          Label* gc_required) {
187169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Allocate heap number in new space.
1872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
1873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           TAG_OBJECT);
187469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
187569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Set the map. The other fields are left uninitialized.
187669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  mov(FieldOperand(result, HeapObject::kMapOffset),
187769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      Immediate(isolate()->factory()->sliced_string_map()));
187869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
187969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
188069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
1881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AllocateOneByteSlicedString(Register result,
1882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                 Register scratch1,
1883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                 Register scratch2,
1884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                 Label* gc_required) {
188569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Allocate heap number in new space.
1886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
1887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           TAG_OBJECT);
188869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
188969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Set the map. The other fields are left uninitialized.
189069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  mov(FieldOperand(result, HeapObject::kMapOffset),
1891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Immediate(isolate()->factory()->sliced_one_byte_string_map()));
189269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
189369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
189469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
1895014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::AllocateJSValue(Register result, Register constructor,
1896014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                     Register value, Register scratch,
1897014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                     Label* gc_required) {
1898014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!result.is(constructor));
1899014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!result.is(scratch));
1900014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!result.is(value));
1901014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1902014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Allocate JSValue in new space.
1903014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Allocate(JSValue::kSize, result, scratch, no_reg, gc_required, TAG_OBJECT);
1904014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1905014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Initialize the JSValue.
1906014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LoadGlobalFunctionInitialMap(constructor, scratch);
1907014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(FieldOperand(result, HeapObject::kMapOffset), scratch);
1908014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LoadRoot(scratch, Heap::kEmptyFixedArrayRootIndex);
1909014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(FieldOperand(result, JSObject::kPropertiesOffset), scratch);
1910014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(FieldOperand(result, JSObject::kElementsOffset), scratch);
1911014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(FieldOperand(result, JSValue::kValueOffset), value);
1912014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
1913014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1914014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1915014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1916b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// Copy memory, byte-by-byte, from source to destination.  Not optimized for
1917b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// long or aligned copies.  The contents of scratch and length are destroyed.
1918b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// Source and destination are incremented by length.
1919b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// Many variants of movsb, loop unrolling, word moves, and indexed operands
1920b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// have been tried here already, and this is fastest.
1921b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// A simpler loop is faster on small copies, but 30% slower on large ones.
1922b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// The cld() instruction must have been emitted, to set the direction flag(),
1923b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// before calling this function.
1924b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid MacroAssembler::CopyBytes(Register source,
1925b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                               Register destination,
1926b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                               Register length,
1927b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                               Register scratch) {
1928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label short_loop, len4, len8, len12, done, short_string;
1929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(source.is(esi));
1930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(destination.is(edi));
1931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(length.is(ecx));
1932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(length, Immediate(4));
1933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(below, &short_string, Label::kNear);
1934b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1935b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Because source is 4-byte aligned in our uses of this function,
1936b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // we keep source aligned for the rep_movs call by copying the odd bytes
1937b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // at the end of the ranges.
1938b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  mov(scratch, Operand(source, length, times_1, -4));
1939b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  mov(Operand(destination, length, times_1, -4), scratch);
1940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(length, Immediate(8));
1942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(below_equal, &len4, Label::kNear);
1943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(length, Immediate(12));
1944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(below_equal, &len8, Label::kNear);
1945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(length, Immediate(16));
1946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(below_equal, &len12, Label::kNear);
1947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1948b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  mov(scratch, ecx);
1949b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  shr(ecx, 2);
1950b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  rep_movs();
19513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(scratch, Immediate(0x3));
19523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(destination, scratch);
1953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  jmp(&done, Label::kNear);
1954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&len12);
1956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(scratch, Operand(source, 8));
1957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(Operand(destination, 8), scratch);
1958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&len8);
1959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(scratch, Operand(source, 4));
1960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(Operand(destination, 4), scratch);
1961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&len4);
1962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(scratch, Operand(source, 0));
1963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(Operand(destination, 0), scratch);
1964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  add(destination, length);
1965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  jmp(&done, Label::kNear);
1966b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1967b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  bind(&short_string);
19683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(length, length);
1969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(zero, &done, Label::kNear);
1970b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1971b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  bind(&short_loop);
1972b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  mov_b(scratch, Operand(source, 0));
1973b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  mov_b(Operand(destination, 0), scratch);
1974b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  inc(source);
1975b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  inc(destination);
1976b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  dec(length);
1977b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  j(not_zero, &short_loop);
1978b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1979b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  bind(&done);
19808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
19818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1982d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1983014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::InitializeFieldsWithFiller(Register current_address,
1984014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                Register end_address,
19853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Register filler) {
19863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label loop, entry;
1987109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  jmp(&entry, Label::kNear);
19883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&loop);
1989014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(Operand(current_address, 0), filler);
1990014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  add(current_address, Immediate(kPointerSize));
19913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&entry);
1992014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  cmp(current_address, end_address);
1993109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  j(below, &loop, Label::kNear);
19943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
19953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
19963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
19973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::BooleanBitTest(Register object,
19983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    int field_offset,
19993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    int bit_index) {
20003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bit_index += kSmiTagSize + kSmiShiftSize;
2001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(base::bits::IsPowerOfTwo32(kBitsPerByte));
20023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int byte_index = bit_index / kBitsPerByte;
20033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int byte_bit_index = bit_index & (kBitsPerByte - 1);
20043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test_b(FieldOperand(object, field_offset + byte_index),
20053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch         Immediate(1 << byte_bit_index));
20063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
20073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::NegativeZeroTest(Register result,
2011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register op,
2012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Label* then_label) {
2013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label ok;
20143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(result, result);
2015109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  j(not_zero, &ok, Label::kNear);
20163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(op, op);
2017109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  j(sign, then_label, Label::kNear);
2018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&ok);
2019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::NegativeZeroTest(Register result,
2023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register op1,
2024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register op2,
2025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register scratch,
2026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Label* then_label) {
2027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label ok;
20283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(result, result);
2029109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  j(not_zero, &ok, Label::kNear);
20303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(scratch, op1);
20313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  or_(scratch, op2);
2032109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  j(sign, then_label, Label::kNear);
2033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&ok);
2034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2037014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::GetMapConstructor(Register result, Register map,
2038014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                       Register temp) {
2039014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label done, loop;
2040014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(result, FieldOperand(map, Map::kConstructorOrBackPointerOffset));
2041014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&loop);
2042014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  JumpIfSmi(result, &done, Label::kNear);
2043014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CmpObjectType(result, MAP_TYPE, temp);
2044014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_equal, &done, Label::kNear);
2045014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(result, FieldOperand(result, Map::kConstructorOrBackPointerOffset));
2046014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  jmp(&loop);
2047014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&done);
2048014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
20493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2051014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::TryGetFunctionPrototype(Register function, Register result,
2052014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                             Register scratch, Label* miss) {
2053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the prototype or initial map from the function.
2054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(result,
2055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
2056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the prototype or initial map is the hole, don't return it and
2058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // simply miss the cache instead. This will allow us to allocate a
2059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // prototype object on-demand in the runtime system.
20603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmp(result, Immediate(isolate()->factory()->the_hole_value()));
2061257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(equal, miss);
2062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the function does not have an initial map, we're done.
2064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label done;
2065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CmpObjectType(result, MAP_TYPE, scratch);
2066014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_equal, &done, Label::kNear);
2067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the prototype from the initial map.
2069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(result, FieldOperand(result, Map::kPrototypeOffset));
2070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // All done.
2072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&done);
2073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CallStub(CodeStub* stub, TypeFeedbackId ast_id) {
2077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(AllowThisStubCall(stub));  // Calls are not allowed in some stubs.
2078257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id);
2079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2082d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::TailCallStub(CodeStub* stub) {
2083d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  jmp(stub->GetCode(), RelocInfo::CODE_TARGET);
2084d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2085d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2086d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
208785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochvoid MacroAssembler::StubReturn(int argc) {
2088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(argc >= 1 && generating_stub());
208985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  ret((argc - 1) * kPointerSize);
2090592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch}
2091592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
2092592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
20933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
2094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return has_frame_ || !stub->SometimesSetsUpAFrame();
2095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
209880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::IndexFromHash(Register hash, Register index) {
209980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // The assert checks that the constants for the maximum number of digits
210080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // for an array index cached in the hash field and the number of bits
210180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // reserved for it does not conflict.
2102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(TenToThe(String::kMaxCachedArrayIndexLength) <
210380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen         (1 << String::kArrayIndexValueBits));
210480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (!index.is(hash)) {
210580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    mov(index, hash);
210680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
2107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DecodeFieldToSmi<String::ArrayIndexValueBits>(index);
2108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
211144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CallRuntime(const Runtime::Function* f,
2112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 int num_arguments,
2113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 SaveFPRegsMode save_doubles) {
2114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the expected number of arguments of the runtime function is
2115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // constant, we check that the actual number of arguments match the
2116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // expectation.
2117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(f->nargs < 0 || f->nargs == num_arguments);
2118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21194515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // TODO(1236192): Most runtime routines don't need the number of
21204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // arguments passed in because it is constant. At some point we
21214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // should remove this need and make the runtime routine entry code
21224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // smarter.
2123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Move(eax, Immediate(num_arguments));
212444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  mov(ebx, Immediate(ExternalReference(f, isolate())));
2125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CEntryStub ces(isolate(), 1, save_doubles);
21264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  CallStub(&ces);
2127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2130bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid MacroAssembler::CallExternalReference(ExternalReference ref,
2131bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                           int num_arguments) {
2132bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  mov(eax, Immediate(num_arguments));
2133bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  mov(ebx, Immediate(ref));
2134bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CEntryStub stub(isolate(), 1);
2136bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  CallStub(&stub);
2137bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
2138bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2139bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::TailCallRuntime(Runtime::FunctionId fid) {
2141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // ----------- S t a t e -------------
2142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  -- esp[0]                 : return address
2143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  -- esp[8]                 : argument num_arguments - 1
2144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  ...
2145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  -- esp[8 * num_arguments] : argument 0 (receiver)
2146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //
2147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  For runtime functions with variable arguments:
2148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  -- eax                    : number of  arguments
2149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // -----------------------------------
21503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const Runtime::Function* function = Runtime::FunctionForId(fid);
2152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(1, function->result_size);
2153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (function->nargs >= 0) {
2154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // TODO(1236192): Most runtime routines don't need the number of
2155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // arguments passed in because it is constant. At some point we
2156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // should remove this need and make the runtime routine entry code
2157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // smarter.
2158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mov(eax, Immediate(function->nargs));
2159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  JumpToExternalReference(ExternalReference(fid, isolate()));
2161d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2162d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2163d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
21646ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::JumpToExternalReference(const ExternalReference& ext) {
2165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set the entry point and jump to the C entry runtime stub.
2166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(ebx, Immediate(ext));
2167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CEntryStub ces(isolate(), 1);
2168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  jmp(ces.GetCode(), RelocInfo::CODE_TARGET);
2169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::PrepareForTailCall(
21723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    const ParameterCount& callee_args_count, Register caller_args_count_reg,
21733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Register scratch0, Register scratch1, ReturnAddressState ra_state,
21743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    int number_of_temp_values_after_return_address) {
21753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#if DEBUG
21763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (callee_args_count.is_reg()) {
21773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(!AreAliased(callee_args_count.reg(), caller_args_count_reg, scratch0,
21783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                       scratch1));
21793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
21803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(!AreAliased(caller_args_count_reg, scratch0, scratch1));
21813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
21823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK(ra_state != ReturnAddressState::kNotOnStack ||
21833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch         number_of_temp_values_after_return_address == 0);
21843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#endif
21853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
21863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Calculate the destination address where we will put the return address
21873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // after we drop current frame.
21883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Register new_sp_reg = scratch0;
21893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (callee_args_count.is_reg()) {
21903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    sub(caller_args_count_reg, callee_args_count.reg());
21913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    lea(new_sp_reg,
21923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Operand(ebp, caller_args_count_reg, times_pointer_size,
21933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                StandardFrameConstants::kCallerPCOffset -
21943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                    number_of_temp_values_after_return_address * kPointerSize));
21953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
21963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    lea(new_sp_reg, Operand(ebp, caller_args_count_reg, times_pointer_size,
21973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                            StandardFrameConstants::kCallerPCOffset -
21983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                (callee_args_count.immediate() +
21993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                 number_of_temp_values_after_return_address) *
22003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                    kPointerSize));
22013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
22023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
22033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (FLAG_debug_code) {
22043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    cmp(esp, new_sp_reg);
22053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Check(below, kStackAccessBelowStackPointer);
22063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
22073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
22083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Copy return address from caller's frame to current frame's return address
22093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // to avoid its trashing and let the following loop copy it to the right
22103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // place.
22113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Register tmp_reg = scratch1;
22123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (ra_state == ReturnAddressState::kOnStack) {
22133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    mov(tmp_reg, Operand(ebp, StandardFrameConstants::kCallerPCOffset));
22143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    mov(Operand(esp, number_of_temp_values_after_return_address * kPointerSize),
22153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        tmp_reg);
22163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
22173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(ReturnAddressState::kNotOnStack == ra_state);
22183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK_EQ(0, number_of_temp_values_after_return_address);
22193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Push(Operand(ebp, StandardFrameConstants::kCallerPCOffset));
22203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
22213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
22223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Restore caller's frame pointer now as it could be overwritten by
22233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // the copying loop.
22243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(ebp, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
22253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
22263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // +2 here is to copy both receiver and return address.
22273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Register count_reg = caller_args_count_reg;
22283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (callee_args_count.is_reg()) {
22293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    lea(count_reg, Operand(callee_args_count.reg(),
22303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                           2 + number_of_temp_values_after_return_address));
22313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
22323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    mov(count_reg, Immediate(callee_args_count.immediate() + 2 +
22333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                             number_of_temp_values_after_return_address));
22343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // TODO(ishell): Unroll copying loop for small immediate values.
22353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
22363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
22373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Now copy callee arguments to the caller frame going backwards to avoid
22383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // callee arguments corruption (source and destination areas could overlap).
22393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label loop, entry;
22403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  jmp(&entry, Label::kNear);
22413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&loop);
22423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  dec(count_reg);
22433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(tmp_reg, Operand(esp, count_reg, times_pointer_size, 0));
22443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(Operand(new_sp_reg, count_reg, times_pointer_size, 0), tmp_reg);
22453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&entry);
22463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  cmp(count_reg, Immediate(0));
22473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  j(not_equal, &loop, Label::kNear);
22483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
22493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Leave current frame.
22503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(esp, new_sp_reg);
22513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
2252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokePrologue(const ParameterCount& expected,
2254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    const ParameterCount& actual,
2255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Label* done,
22563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    bool* definitely_mismatches,
2257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                    InvokeFlag flag,
2258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Label::Distance done_near,
2259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const CallWrapper& call_wrapper) {
2260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool definitely_matches = false;
22613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  *definitely_mismatches = false;
2262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label invoke;
2263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (expected.is_immediate()) {
2264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(actual.is_immediate());
2265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mov(eax, actual.immediate());
2266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (expected.immediate() == actual.immediate()) {
2267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      definitely_matches = true;
2268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
2269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel;
2270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (expected.immediate() == sentinel) {
2271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Don't worry about adapting arguments for builtins that
2272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // don't want that done. Skip adaption code by making it look
2273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // like we have a match between expected and actual number of
2274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // arguments.
2275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        definitely_matches = true;
2276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
22773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        *definitely_mismatches = true;
2278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mov(ebx, expected.immediate());
2279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
2280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (actual.is_immediate()) {
2283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Expected is in register, actual is immediate. This is the
2284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // case when we invoke function values without going through the
2285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // IC mechanism.
2286014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      mov(eax, actual.immediate());
2287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      cmp(expected.reg(), actual.immediate());
2288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      j(equal, &invoke);
2289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(expected.reg().is(ebx));
2290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else if (!expected.reg().is(actual.reg())) {
2291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Both expected and actual are in (different) registers. This
2292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // is the case when we invoke functions using call and apply.
22933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      cmp(expected.reg(), actual.reg());
2294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      j(equal, &invoke);
2295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(actual.reg().is(eax));
2296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(expected.reg().is(ebx));
2297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
2298014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Move(eax, actual.reg());
2299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!definitely_matches) {
2303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Handle<Code> adaptor =
230444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        isolate()->builtins()->ArgumentsAdaptorTrampoline();
2305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (flag == CALL_FUNCTION) {
2306257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      call_wrapper.BeforeCall(CallSize(adaptor, RelocInfo::CODE_TARGET));
2307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      call(adaptor, RelocInfo::CODE_TARGET);
2308257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      call_wrapper.AfterCall();
23093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (!*definitely_mismatches) {
23103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        jmp(done, done_near);
23113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
2312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
2313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      jmp(adaptor, RelocInfo::CODE_TARGET);
2314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bind(&invoke);
2316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::FloodFunctionIfStepping(Register fun, Register new_target,
2321014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                             const ParameterCount& expected,
2322014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                             const ParameterCount& actual) {
2323014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label skip_flooding;
2324014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ExternalReference step_in_enabled =
2325014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ExternalReference::debug_step_in_enabled_address(isolate());
23263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  cmpb(Operand::StaticVariable(step_in_enabled), Immediate(0));
2327014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(equal, &skip_flooding);
2328014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  {
2329014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    FrameScope frame(this,
2330014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     has_frame() ? StackFrame::NONE : StackFrame::INTERNAL);
2331014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (expected.is_reg()) {
2332014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SmiTag(expected.reg());
2333014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Push(expected.reg());
2334014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
2335014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (actual.is_reg()) {
2336014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SmiTag(actual.reg());
2337014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Push(actual.reg());
2338014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
2339014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (new_target.is_valid()) {
2340014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Push(new_target);
2341014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
2342014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(fun);
2343014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(fun);
2344109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    CallRuntime(Runtime::kDebugPrepareStepInIfStepping);
2345014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Pop(fun);
2346014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (new_target.is_valid()) {
2347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pop(new_target);
2348014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
2349014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (actual.is_reg()) {
2350014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pop(actual.reg());
2351014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SmiUntag(actual.reg());
2352014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
2353014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (expected.is_reg()) {
2354014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pop(expected.reg());
2355014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SmiUntag(expected.reg());
2356014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
2357014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2358014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&skip_flooding);
2359014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2360014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2361014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2362014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::InvokeFunctionCode(Register function, Register new_target,
2363014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        const ParameterCount& expected,
2364014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        const ParameterCount& actual,
2365014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        InvokeFlag flag,
2366014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        const CallWrapper& call_wrapper) {
23673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a function without a valid frame.
2368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(flag == JUMP_FUNCTION || has_frame());
2369014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(function.is(edi));
2370014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_IMPLIES(new_target.is_valid(), new_target.is(edx));
2371014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2372014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (call_wrapper.NeedsDebugStepCheck()) {
2373014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    FloodFunctionIfStepping(function, new_target, expected, actual);
2374014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2376014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Clear the new.target register if not given.
2377014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!new_target.is_valid()) {
2378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mov(edx, isolate()->factory()->undefined_value());
2379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
23803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2381257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
23823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool definitely_mismatches = false;
2383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InvokePrologue(expected, actual, &done, &definitely_mismatches, flag,
2384014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 Label::kNear, call_wrapper);
23853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!definitely_mismatches) {
2386014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // We call indirectly through the code field in the function to
2387014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // allow recompilation to take effect without changing any of the
2388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // call sites.
2389014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Operand code = FieldOperand(function, JSFunction::kCodeEntryOffset);
23903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (flag == CALL_FUNCTION) {
23913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call_wrapper.BeforeCall(CallSize(code));
23923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call(code);
23933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call_wrapper.AfterCall();
23943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
2395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(flag == JUMP_FUNCTION);
23963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      jmp(code);
23973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
23983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&done);
2399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeFunction(Register fun,
2404014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    Register new_target,
2405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    const ParameterCount& actual,
2406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                    InvokeFlag flag,
2407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const CallWrapper& call_wrapper) {
24083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a function without a valid frame.
2409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(flag == JUMP_FUNCTION || has_frame());
24103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(fun.is(edi));
2412014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
2413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
2414014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kFormalParameterCountOffset));
24157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  SmiUntag(ebx);
2416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ParameterCount expected(ebx);
2418014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InvokeFunctionCode(edi, new_target, expected, actual, flag, call_wrapper);
2419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::InvokeFunction(Register fun,
2423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const ParameterCount& expected,
2424402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                    const ParameterCount& actual,
2425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                    InvokeFlag flag,
2426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const CallWrapper& call_wrapper) {
24273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a function without a valid frame.
2428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(flag == JUMP_FUNCTION || has_frame());
24293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(fun.is(edi));
2431402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
2432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2433014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InvokeFunctionCode(edi, no_reg, expected, actual, flag, call_wrapper);
2434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::InvokeFunction(Handle<JSFunction> function,
2438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const ParameterCount& expected,
2439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const ParameterCount& actual,
2440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    InvokeFlag flag,
2441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const CallWrapper& call_wrapper) {
2442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LoadHeapObject(edi, function);
2443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InvokeFunction(edi, expected, actual, flag, call_wrapper);
2444402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
2445402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2447d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::LoadContext(Register dst, int context_chain_length) {
2448d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (context_chain_length > 0) {
2449d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Move up the chain of contexts to the context containing the slot.
24503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    mov(dst, Operand(esi, Context::SlotOffset(Context::PREVIOUS_INDEX)));
2451d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    for (int i = 1; i < context_chain_length; i++) {
24523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      mov(dst, Operand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX)));
2453d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
24541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
24551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Slot is in the current function context.  Move it into the
24561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // destination register in case we store into it (the write barrier
24571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // cannot be allowed to destroy the context in esi).
24581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    mov(dst, esi);
24591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
24601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
24613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // We should not have found a with context by walking the context chain
24621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // (i.e., the static scope chain and runtime context chain do not agree).
24631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // A variable occurring in such a scope should have slot type LOOKUP and
24641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // not CONTEXT.
246544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
24663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    cmp(FieldOperand(dst, HeapObject::kMapOffset),
24673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        isolate()->factory()->with_context_map());
2468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kVariableResolvedToWithContext);
2469d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2470d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2471d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2472d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2473014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LoadGlobalProxy(Register dst) {
2474014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(dst, NativeContextOperand());
2475014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(dst, ContextOperand(dst, Context::GLOBAL_PROXY_INDEX));
2476014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2477014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2478014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
24793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::LoadTransitionedArrayMapConditional(
24803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ElementsKind expected_kind,
24813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ElementsKind transitioned_kind,
24823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register map_in_out,
24833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch,
24843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* no_map_match) {
2485014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsFastElementsKind(expected_kind));
2486014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsFastElementsKind(transitioned_kind));
24873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check that the function's map is the same as the expected cached map.
2489014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(scratch, NativeContextOperand());
2490014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  cmp(map_in_out,
2491014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ContextOperand(scratch, Context::ArrayMapIndex(expected_kind)));
24923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_equal, no_map_match);
24933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Use the transitioned cached map.
2495014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(map_in_out,
2496014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ContextOperand(scratch, Context::ArrayMapIndex(transitioned_kind)));
24973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
24983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
250080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::LoadGlobalFunction(int index, Register function) {
2501014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Load the native context from the current context.
2502014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(function, NativeContextOperand());
2503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the function from the native context.
2504014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(function, ContextOperand(function, index));
250580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
250680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
250780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
250880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
250980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                                  Register map) {
251080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Load the initial map.  The global functions all have initial maps.
251180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  mov(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
251244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
251380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Label ok, fail;
2514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CheckMap(map, isolate()->factory()->meta_map(), &fail, DO_SMI_CHECK);
251580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    jmp(&ok);
251680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    bind(&fail);
2517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Abort(kGlobalFunctionsMustHaveInitialMap);
251880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    bind(&ok);
251980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
252080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
252180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2522d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2523e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Store the value in register src in the safepoint register stack
2524e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// slot for register dst.
2525e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Register src) {
2526e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  mov(SafepointRegisterSlot(dst), src);
2527e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2528e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2529e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2530e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Immediate src) {
2531e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  mov(SafepointRegisterSlot(dst), src);
2532e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2533e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2534e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2535e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) {
2536e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  mov(dst, SafepointRegisterSlot(src));
2537e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2538e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2539e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2540e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochOperand MacroAssembler::SafepointRegisterSlot(Register reg) {
2541e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return Operand(esp, SafepointRegisterStackIndex(reg.code()) * kPointerSize);
2542e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2543e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2544e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochint MacroAssembler::SafepointRegisterStackIndex(int reg_code) {
2546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The registers are pushed starting with the lowest encoding,
2547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // which means that lowest encodings are furthest away from
2548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // the stack pointer.
2549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(reg_code >= 0 && reg_code < kNumSafepointRegisters);
2550b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return kNumSafepointRegisters - reg_code - 1;
2551b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2552b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
25543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::LoadHeapObject(Register result,
25553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    Handle<HeapObject> object) {
2556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllowDeferredHandleDereference embedding_raw_address;
25573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (isolate()->heap()->InNewSpace(*object)) {
2558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Cell> cell = isolate()->factory()->NewCell(object);
2559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(result, Operand::ForCell(cell));
25603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
25613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(result, object);
25623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
25633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
25643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CmpHeapObject(Register reg, Handle<HeapObject> object) {
2567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllowDeferredHandleDereference using_raw_address;
2568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (isolate()->heap()->InNewSpace(*object)) {
2569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Cell> cell = isolate()->factory()->NewCell(object);
2570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(reg, Operand::ForCell(cell));
2571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(reg, object);
2573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
25773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::PushHeapObject(Handle<HeapObject> object) {
2578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllowDeferredHandleDereference using_raw_address;
25793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (isolate()->heap()->InNewSpace(*object)) {
2580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Cell> cell = isolate()->factory()->NewCell(object);
2581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    push(Operand::ForCell(cell));
25823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
25833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Push(object);
25843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
25853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
25863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2588958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::CmpWeakValue(Register value, Handle<WeakCell> cell,
2589958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                  Register scratch) {
2590958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  mov(scratch, cell);
2591958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  cmp(value, FieldOperand(scratch, WeakCell::kValueOffset));
2592958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2593958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2594958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2595014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::GetWeakValue(Register value, Handle<WeakCell> cell) {
2596958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  mov(value, cell);
2597958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  mov(value, FieldOperand(value, WeakCell::kValueOffset));
2598014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2599014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2600014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2601014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LoadWeakValue(Register value, Handle<WeakCell> cell,
2602014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                   Label* miss) {
2603014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GetWeakValue(value, cell);
2604958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  JumpIfSmi(value, miss);
2605958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2606958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2607958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Ret() {
2609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ret(0);
2610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::Ret(int bytes_dropped, Register scratch) {
26141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (is_uint16(bytes_dropped)) {
26151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ret(bytes_dropped);
26161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
26171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    pop(scratch);
26183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    add(esp, Immediate(bytes_dropped));
26191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    push(scratch);
26201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ret(0);
26211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
26221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
26231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
26241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2625e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::Drop(int stack_elements) {
2626e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (stack_elements > 0) {
26273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    add(esp, Immediate(stack_elements * kPointerSize));
2628e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2629e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
2630e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2631e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
26320d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::Move(Register dst, Register src) {
26330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (!dst.is(src)) {
26340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    mov(dst, src);
26350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
26360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
26370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
26380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
2639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Move(Register dst, const Immediate& x) {
2640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (x.is_zero()) {
2641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    xor_(dst, dst);  // Shorter than mov of 32-bit immediate 0.
2642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(dst, x);
2644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Move(const Operand& dst, const Immediate& x) {
2649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(dst, x);
2650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2653958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::Move(XMMRegister dst, uint32_t src) {
2654958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (src == 0) {
2655958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    pxor(dst, dst);
2656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2657958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    unsigned cnt = base::bits::CountPopulation32(src);
2658958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    unsigned nlz = base::bits::CountLeadingZeros32(src);
2659958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    unsigned ntz = base::bits::CountTrailingZeros32(src);
2660958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (nlz + cnt + ntz == 32) {
2661958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      pcmpeqd(dst, dst);
2662958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (ntz == 0) {
2663958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        psrld(dst, 32 - cnt);
2664958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      } else {
2665958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        pslld(dst, 32 - cnt);
2666958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        if (nlz != 0) psrld(dst, nlz);
2667958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
2668958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
2669958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      push(eax);
2670958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      mov(eax, Immediate(src));
2671958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      movd(dst, Operand(eax));
2672958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      pop(eax);
2673958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
2674958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
2675958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2676958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2677958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2678958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::Move(XMMRegister dst, uint64_t src) {
2679014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (src == 0) {
2680014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    pxor(dst, dst);
2681958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
2682014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    uint32_t lower = static_cast<uint32_t>(src);
2683014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    uint32_t upper = static_cast<uint32_t>(src >> 32);
2684958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    unsigned cnt = base::bits::CountPopulation64(src);
2685958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    unsigned nlz = base::bits::CountLeadingZeros64(src);
2686958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    unsigned ntz = base::bits::CountTrailingZeros64(src);
2687958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (nlz + cnt + ntz == 64) {
2688958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      pcmpeqd(dst, dst);
2689958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (ntz == 0) {
2690958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        psrlq(dst, 64 - cnt);
2691958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      } else {
2692958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        psllq(dst, 64 - cnt);
2693958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        if (nlz != 0) psrlq(dst, nlz);
2694958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
2695958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else if (lower == 0) {
2696958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Move(dst, upper);
2697958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      psllq(dst, 32);
2698958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else if (CpuFeatures::IsSupported(SSE4_1)) {
2699958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      CpuFeatureScope scope(this, SSE4_1);
2700958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      push(eax);
2701958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Move(eax, Immediate(lower));
2702958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      movd(dst, Operand(eax));
2703958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Move(eax, Immediate(upper));
2704958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      pinsrd(dst, Operand(eax), 1);
2705958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      pop(eax);
2706958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
2707958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      push(Immediate(upper));
2708958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      push(Immediate(lower));
2709958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      movsd(dst, Operand(esp, 0));
2710958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      add(esp, Immediate(kDoubleSize));
2711958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
2712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2716014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Pextrd(Register dst, XMMRegister src, int8_t imm8) {
2717014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (imm8 == 0) {
2718014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movd(dst, src);
2719014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
2720014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2721014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(1, imm8);
2722014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(SSE4_1)) {
2723014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope sse_scope(this, SSE4_1);
2724014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    pextrd(dst, src, imm8);
2725014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
2726014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2727014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  pshufd(xmm0, src, 1);
2728014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movd(dst, xmm0);
2729014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2730014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2731014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2732014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Pinsrd(XMMRegister dst, const Operand& src, int8_t imm8) {
2733014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(imm8 == 0 || imm8 == 1);
2734014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(SSE4_1)) {
2735014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope sse_scope(this, SSE4_1);
2736014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    pinsrd(dst, src, imm8);
2737014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
2738014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2739014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movd(xmm0, src);
2740014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (imm8 == 1) {
2741014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    punpckldq(dst, xmm0);
2742014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2743014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK_EQ(0, imm8);
2744014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    psrlq(dst, 32);
2745014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    punpckldq(xmm0, dst);
2746014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movaps(dst, xmm0);
2747014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2748014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2749014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2750014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2751014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Lzcnt(Register dst, const Operand& src) {
2752014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(LZCNT)) {
2753014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, LZCNT);
2754014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    lzcnt(dst, src);
2755014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
2756014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2757014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label not_zero_src;
2758014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bsr(dst, src);
2759014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_zero, &not_zero_src, Label::kNear);
2760014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Move(dst, Immediate(63));  // 63^31 == 32
2761014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&not_zero_src);
2762014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  xor_(dst, Immediate(31));  // for x in [0..31], 31^x == 31-x.
2763014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2764014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2765014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2766014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Tzcnt(Register dst, const Operand& src) {
2767014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(BMI1)) {
2768014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, BMI1);
2769014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    tzcnt(dst, src);
2770014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
2771014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2772014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label not_zero_src;
2773014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bsf(dst, src);
2774014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_zero, &not_zero_src, Label::kNear);
2775014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Move(dst, Immediate(32));  // The result of tzcnt is 32 if src = 0.
2776014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&not_zero_src);
2777014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2778014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2779014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2780014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Popcnt(Register dst, const Operand& src) {
2781014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(POPCNT)) {
2782014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, POPCNT);
2783014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    popcnt(dst, src);
2784014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
2785014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2786014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  UNREACHABLE();
2787014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2788014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2789014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SetCounter(StatsCounter* counter, int value) {
2791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
2792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(Operand::StaticVariable(ExternalReference(counter)), Immediate(value));
2793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::IncrementCounter(StatsCounter* counter, int value) {
2798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(value > 0);
2799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
2800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Operand operand = Operand::StaticVariable(ExternalReference(counter));
2801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (value == 1) {
2802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      inc(operand);
2803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
2804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      add(operand, Immediate(value));
2805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::DecrementCounter(StatsCounter* counter, int value) {
2811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(value > 0);
2812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
2813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Operand operand = Operand::StaticVariable(ExternalReference(counter));
2814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (value == 1) {
2815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      dec(operand);
2816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
2817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      sub(operand, Immediate(value));
2818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2823d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid MacroAssembler::IncrementCounter(Condition cc,
2824d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                      StatsCounter* counter,
2825d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                      int value) {
2826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(value > 0);
2827d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (FLAG_native_code_counters && counter->Enabled()) {
2828d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Label skip;
2829d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    j(NegateCondition(cc), &skip);
2830d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    pushfd();
2831d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    IncrementCounter(counter, value);
2832d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    popfd();
2833d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    bind(&skip);
2834d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
2835d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
2836d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2837d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2838d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid MacroAssembler::DecrementCounter(Condition cc,
2839d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                      StatsCounter* counter,
2840d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                      int value) {
2841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(value > 0);
2842d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (FLAG_native_code_counters && counter->Enabled()) {
2843d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Label skip;
2844d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    j(NegateCondition(cc), &skip);
2845d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    pushfd();
2846d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    DecrementCounter(counter, value);
2847d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    popfd();
2848d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    bind(&skip);
2849d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
2850d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
2851d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2852d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Assert(Condition cc, BailoutReason reason) {
2854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) Check(cc, reason);
2855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2858756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid MacroAssembler::AssertFastElements(Register elements) {
285944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
286044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Factory* factory = isolate()->factory();
2861756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Label ok;
2862756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    cmp(FieldOperand(elements, HeapObject::kMapOffset),
286344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Immediate(factory->fixed_array_map()));
2864756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    j(equal, &ok);
2865756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    cmp(FieldOperand(elements, HeapObject::kMapOffset),
28663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        Immediate(factory->fixed_double_array_map()));
28673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    j(equal, &ok);
28683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    cmp(FieldOperand(elements, HeapObject::kMapOffset),
286944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Immediate(factory->fixed_cow_array_map()));
2870756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    j(equal, &ok);
2871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Abort(kJSObjectWithFastElementsMapHasSlowElements);
2872756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    bind(&ok);
2873756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
2874756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
2875756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2876756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Check(Condition cc, BailoutReason reason) {
2878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label L;
2879257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(cc, &L);
2880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Abort(reason);
2881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // will not return here
2882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&L);
2883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28866ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::CheckStackAlignment() {
2887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int frame_alignment = base::OS::ActivationFrameAlignment();
28886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int frame_alignment_mask = frame_alignment - 1;
28896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (frame_alignment > kPointerSize) {
2890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
28916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Label alignment_as_expected;
28926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    test(esp, Immediate(frame_alignment_mask));
28936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    j(zero, &alignment_as_expected);
28946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Abort if stack is not aligned.
28956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int3();
28966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    bind(&alignment_as_expected);
28976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
28986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
28996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
29006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Abort(BailoutReason reason) {
2902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* msg = GetBailoutReason(reason);
2904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (msg != NULL) {
2905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RecordComment("Abort message: ");
2906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RecordComment(msg);
2907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_trap_on_abort) {
2910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int3();
2911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
2912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2914d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  push(Immediate(reinterpret_cast<intptr_t>(Smi::FromInt(reason))));
29163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Disable stub call restrictions to always allow calls to abort.
29173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!has_frame_) {
29183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // We don't actually want to generate a pile of code for this, so just
29193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // claim there is a stack frame, without generating one.
29203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(this, StackFrame::NONE);
2921109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    CallRuntime(Runtime::kAbort);
29223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
2923109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    CallRuntime(Runtime::kAbort);
29243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // will not return here
2926d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int3();
2927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2930257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::LoadInstanceDescriptors(Register map,
2931257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Register descriptors) {
2932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(descriptors, FieldOperand(map, Map::kDescriptorsOffset));
2933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) {
2937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(dst, FieldOperand(map, Map::kBitField3Offset));
2938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DecodeField<Map::NumberOfOwnDescriptorsBits>(dst);
2939756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
2940756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2941756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2942014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LoadAccessor(Register dst, Register holder,
2943014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  int accessor_index,
2944014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  AccessorComponent accessor) {
2945014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(dst, FieldOperand(holder, HeapObject::kMapOffset));
2946014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LoadInstanceDescriptors(dst, dst);
2947014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(dst, FieldOperand(dst, DescriptorArray::GetValueOffset(accessor_index)));
2948014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int offset = accessor == ACCESSOR_GETTER ? AccessorPair::kGetterOffset
2949014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                           : AccessorPair::kSetterOffset;
2950014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(dst, FieldOperand(dst, offset));
2951014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2952014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2953014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
29540d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::LoadPowerOf2(XMMRegister dst,
29550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                  Register scratch,
29560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                  int power) {
2957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uintn(power + HeapNumber::kExponentBias,
29580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                  HeapNumber::kExponentBits));
29590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  mov(scratch, Immediate(power + HeapNumber::kExponentBias));
29603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movd(dst, scratch);
29610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  psllq(dst, HeapNumber::kMantissaBits);
29620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
29630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
29640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
2965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfInstanceTypeIsNotSequentialOneByte(
2966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register instance_type, Register scratch, Label* failure) {
2967402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (!scratch.is(instance_type)) {
2968402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    mov(scratch, instance_type);
2969402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
2970402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  and_(scratch,
2971402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu       kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask);
2972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(scratch, kStringTag | kSeqStringTag | kOneByteStringTag);
2973402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  j(not_equal, failure);
2974402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
2975402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2976402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfNotBothSequentialOneByteStrings(Register object1,
2978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                           Register object2,
2979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                           Register scratch1,
2980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                           Register scratch2,
2981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                           Label* failure) {
2982d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Check that both objects are not smis.
298369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
29843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(scratch1, object1);
29853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(scratch1, object2);
29863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  JumpIfSmi(scratch1, failure);
2987d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2988d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Load instance type for both strings.
2989d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  mov(scratch1, FieldOperand(object1, HeapObject::kMapOffset));
2990d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  mov(scratch2, FieldOperand(object2, HeapObject::kMapOffset));
2991d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  movzx_b(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset));
2992d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  movzx_b(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset));
2993d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that both are flat one-byte strings.
2995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kFlatOneByteStringMask =
2996d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
2997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kFlatOneByteStringTag =
2998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kStringTag | kOneByteStringTag | kSeqStringTag;
2999d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Interleave bits from both instance types and compare them in one check.
3000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0, kFlatOneByteStringMask & (kFlatOneByteStringMask << 3));
3001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  and_(scratch1, kFlatOneByteStringMask);
3002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  and_(scratch2, kFlatOneByteStringMask);
3003d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  lea(scratch1, Operand(scratch1, scratch2, times_8, 0));
3004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(scratch1, kFlatOneByteStringTag | (kFlatOneByteStringTag << 3));
3005d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  j(not_equal, failure);
3006d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
3007d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
3008d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
3009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfNotUniqueNameInstanceType(Operand operand,
3010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                     Label* not_unique_name,
3011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                     Label::Distance distance) {
3012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
3013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label succeed;
3014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  test(operand, Immediate(kIsNotStringMask | kIsNotInternalizedMask));
3015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(zero, &succeed);
30163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  cmpb(operand, Immediate(SYMBOL_TYPE));
3017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(not_equal, not_unique_name, distance);
3018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&succeed);
3020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::EmitSeqStringSetCharCheck(Register string,
3024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register index,
3025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register value,
3026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               uint32_t encoding_mask) {
3027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label is_object;
3028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JumpIfNotSmi(string, &is_object, Label::kNear);
3029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Abort(kNonObject);
3030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&is_object);
3031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  push(value);
3033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(value, FieldOperand(string, HeapObject::kMapOffset));
3034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movzx_b(value, FieldOperand(value, Map::kInstanceTypeOffset));
3035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  and_(value, Immediate(kStringRepresentationMask | kStringEncodingMask));
3037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(value, Immediate(encoding_mask));
3038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pop(value);
3039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(equal, kUnexpectedStringType);
3040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The index is assumed to be untagged coming in, tag it to compare with the
3042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // string length without using a temp register, it is restored at the end of
3043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // this function.
3044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiTag(index);
3045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(no_overflow, kIndexIsTooLarge);
3046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(index, FieldOperand(string, String::kLengthOffset));
3048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(less, kIndexIsTooLarge);
3049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(index, Immediate(Smi::FromInt(0)));
3051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(greater_equal, kIndexIsNegative);
3052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Restore the index
3054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiUntag(index);
3055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
30586ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::PrepareCallCFunction(int num_arguments, Register scratch) {
3059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int frame_alignment = base::OS::ActivationFrameAlignment();
30608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (frame_alignment != 0) {
30616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Make stack end at alignment and make room for num_arguments words
30626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // and the original value of esp.
30636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    mov(scratch, esp);
30643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sub(esp, Immediate((num_arguments + 1) * kPointerSize));
3065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
30668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    and_(esp, -frame_alignment);
30676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    mov(Operand(esp, num_arguments * kPointerSize), scratch);
30686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
30693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sub(esp, Immediate(num_arguments * kPointerSize));
30706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
30716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
30726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
30736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
30746ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::CallCFunction(ExternalReference function,
30756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                   int num_arguments) {
30766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Trashing eax is ok as it will be the return value.
30773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(eax, Immediate(function));
30786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CallCFunction(eax, num_arguments);
30796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
30806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
30816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
30826ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::CallCFunction(Register function,
30836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                   int num_arguments) {
3084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(has_frame());
30856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check stack alignment.
308644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
30876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CheckStackAlignment();
30886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
30896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
30903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  call(function);
3091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (base::OS::ActivationFrameAlignment() != 0) {
30926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    mov(esp, Operand(esp, num_arguments * kPointerSize));
30936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
30943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    add(esp, Immediate(num_arguments * kPointerSize));
30956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
30966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
30976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
30986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
3100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool AreAliased(Register reg1,
3101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg2,
3102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg3,
3103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg4,
3104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg5,
3105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg6,
3106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg7,
3107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg8) {
3108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int n_of_valid_regs = reg1.is_valid() + reg2.is_valid() +
3109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reg3.is_valid() + reg4.is_valid() + reg5.is_valid() + reg6.is_valid() +
3110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reg7.is_valid() + reg8.is_valid();
3111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RegList regs = 0;
3113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg1.is_valid()) regs |= reg1.bit();
3114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg2.is_valid()) regs |= reg2.bit();
3115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg3.is_valid()) regs |= reg3.bit();
3116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg4.is_valid()) regs |= reg4.bit();
3117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg5.is_valid()) regs |= reg5.bit();
3118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg6.is_valid()) regs |= reg6.bit();
3119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg7.is_valid()) regs |= reg7.bit();
3120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg8.is_valid()) regs |= reg8.bit();
3121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int n_of_non_aliasing_regs = NumRegs(regs);
3122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return n_of_valid_regs != n_of_non_aliasing_regs;
31243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
31263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochCodePatcher::CodePatcher(Isolate* isolate, byte* address, int size)
31298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    : address_(address),
31308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      size_(size),
3131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      masm_(isolate, address, size + Assembler::kGap, CodeObjectRequired::kNo) {
3132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a new macro assembler pointing to the address of the code to patch.
3133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The size is adjusted with kGap on order for the assembler to generate size
3134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // bytes of instructions without failing with buffer size constraints.
3135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
3136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCodePatcher::~CodePatcher() {
3140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Indicate that code has changed.
3141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Assembler::FlushICache(masm_.isolate(), address_, size_);
3142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the code was patched as expected.
3144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(masm_.pc_ == address_ + size_);
3145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
3146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
31493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckPageFlag(
31503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register object,
31513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch,
31523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int mask,
31533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Condition cc,
31543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* condition_met,
31553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label::Distance condition_met_distance) {
3156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(cc == zero || cc == not_zero);
31573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (scratch.is(object)) {
31583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    and_(scratch, Immediate(~Page::kPageAlignmentMask));
31593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
31603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(scratch, Immediate(~Page::kPageAlignmentMask));
31613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    and_(scratch, object);
31623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
31633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (mask < (1 << kBitsPerByte)) {
31643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    test_b(Operand(scratch, MemoryChunk::kFlagsOffset), Immediate(mask));
31653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
31663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    test(Operand(scratch, MemoryChunk::kFlagsOffset), Immediate(mask));
31673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
31683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(cc, condition_met, condition_met_distance);
31693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
31703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CheckPageFlagForMap(
3173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Map> map,
3174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int mask,
3175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Condition cc,
3176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label* condition_met,
3177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label::Distance condition_met_distance) {
3178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(cc == zero || cc == not_zero);
3179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Page* page = Page::FromAddress(map->address());
3180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!serializer_enabled());  // Serializer cannot match page_flags.
3181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference reference(ExternalReference::page_flags(page));
3182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The inlined static address check of the page's flags relies
3183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // on maps never being compacted.
3184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!isolate()->heap()->mark_compact_collector()->
3185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         IsOnEvacuationCandidate(*map));
3186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (mask < (1 << kBitsPerByte)) {
31873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    test_b(Operand::StaticVariable(reference), Immediate(mask));
3188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(Operand::StaticVariable(reference), Immediate(mask));
3190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(cc, condition_met, condition_met_distance);
3192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
31953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::JumpIfBlack(Register object,
31963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register scratch0,
31973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register scratch1,
31983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Label* on_black,
31993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Label::Distance on_black_near) {
3200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  HasColor(object, scratch0, scratch1, on_black, on_black_near, 1,
3201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch           1);  // kBlackBitPattern.
3202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0);
32033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
32043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::HasColor(Register object,
32073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Register bitmap_scratch,
32083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Register mask_scratch,
32093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Label* has_color,
32103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Label::Distance has_color_distance,
32113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              int first_bit,
32123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              int second_bit) {
3213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(object, bitmap_scratch, mask_scratch, ecx));
32143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GetMarkBits(object, bitmap_scratch, mask_scratch);
32163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label other_color, word_boundary;
32183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
32193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(first_bit == 1 ? zero : not_zero, &other_color, Label::kNear);
32203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(mask_scratch, mask_scratch);  // Shift left 1 by adding.
32213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(zero, &word_boundary, Label::kNear);
32223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
32233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(second_bit == 1 ? not_zero : zero, has_color, has_color_distance);
32243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  jmp(&other_color, Label::kNear);
32253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&word_boundary);
32273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test_b(Operand(bitmap_scratch, MemoryChunk::kHeaderSize + kPointerSize),
32283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch         Immediate(1));
32293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(second_bit == 1 ? not_zero : zero, has_color, has_color_distance);
32313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&other_color);
32323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
32333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::GetMarkBits(Register addr_reg,
32363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register bitmap_reg,
32373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register mask_reg) {
3238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(addr_reg, mask_reg, bitmap_reg, ecx));
32393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(bitmap_reg, Immediate(~Page::kPageAlignmentMask));
32403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(bitmap_reg, addr_reg);
32413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(ecx, addr_reg);
32423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int shift =
32433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Bitmap::kBitsPerCellLog2 + kPointerSizeLog2 - Bitmap::kBytesPerCellLog2;
32443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  shr(ecx, shift);
32453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(ecx,
32463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       (Page::kPageAlignmentMask >> shift) & ~(Bitmap::kBytesPerCell - 1));
32473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(bitmap_reg, ecx);
32493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(ecx, addr_reg);
32503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  shr(ecx, kPointerSizeLog2);
32513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(ecx, (1 << Bitmap::kBitsPerCellLog2) - 1);
32523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(mask_reg, Immediate(1));
32533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  shl_cl(mask_reg);
32543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
32553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::JumpIfWhite(Register value, Register bitmap_scratch,
3258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 Register mask_scratch, Label* value_is_white,
3259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 Label::Distance distance) {
3260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(value, bitmap_scratch, mask_scratch, ecx));
32613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GetMarkBits(value, bitmap_scratch, mask_scratch);
32623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If the value is black or grey we don't need to do anything.
3264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0);
3265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0);
3266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(strcmp(Marking::kGreyBitPattern, "10") == 0);
3267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0);
32683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Since both black and grey have a 1 in the first position and white does
32703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // not have a 1 there we only need to check one bit.
32713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
3272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(zero, value_is_white, Label::kNear);
32733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
32743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::EnumLength(Register dst, Register map) {
3277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(Map::EnumLengthBits::kShift == 0);
3278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(dst, FieldOperand(map, Map::kBitField3Offset));
3279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  and_(dst, Immediate(Map::EnumLengthBits::kMask));
3280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiTag(dst);
3281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
32843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckEnumCache(Label* call_runtime) {
3285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label next, start;
32863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(ecx, eax);
3287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check if the enum length field is properly initialized, indicating that
3289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // there is an enum cache.
3290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset));
3291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EnumLength(edx, ebx);
3293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(edx, Immediate(Smi::FromInt(kInvalidEnumCacheSentinel)));
3294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(equal, call_runtime);
3295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  jmp(&start);
3297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
32983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&next);
3299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset));
33003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // For all objects but the receiver, check that the cache is empty.
3302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EnumLength(edx, ebx);
3303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(edx, Immediate(Smi::FromInt(0)));
33043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_equal, call_runtime);
33053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&start);
33073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that there are no elements. Register rcx contains the current JS
3309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // object we've reached through the prototype chain.
3310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label no_elements;
3311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset));
3312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(ecx, isolate()->factory()->empty_fixed_array());
3313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(equal, &no_elements);
33143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Second chance, the object may be using the empty slow element dictionary.
3316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(ecx, isolate()->factory()->empty_slow_element_dictionary());
33173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_equal, call_runtime);
33183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&no_elements);
33203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset));
33213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmp(ecx, isolate()->factory()->null_value());
33223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_equal, &next);
33233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
33243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TestJSArrayForAllocationMemento(
3327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register receiver_reg,
3328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch_reg,
3329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label* no_memento_found) {
33303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label map_check;
33313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label top_check;
3332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference new_space_allocation_top =
3333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::new_space_allocation_top_address(isolate());
33343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  const int kMementoMapOffset = JSArray::kSize - kHeapObjectTag;
33353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  const int kMementoEndOffset = kMementoMapOffset + AllocationMemento::kSize;
33363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
33373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Bail out if the object is not in new space.
33383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  JumpIfNotInNewSpace(receiver_reg, scratch_reg, no_memento_found);
33393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // If the object is in new space, we need to check whether it is on the same
33403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // page as the current top.
33413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  lea(scratch_reg, Operand(receiver_reg, kMementoEndOffset));
33423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  xor_(scratch_reg, Operand::StaticVariable(new_space_allocation_top));
33433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test(scratch_reg, Immediate(~Page::kPageAlignmentMask));
33443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  j(zero, &top_check);
33453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // The object is on a different page than allocation top. Bail out if the
33463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // object sits on the page boundary as no memento can follow and we cannot
33473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // touch the memory following it.
33483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  lea(scratch_reg, Operand(receiver_reg, kMementoEndOffset));
33493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  xor_(scratch_reg, receiver_reg);
33503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test(scratch_reg, Immediate(~Page::kPageAlignmentMask));
33513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  j(not_zero, no_memento_found);
33523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Continue with the actual map check.
33533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  jmp(&map_check);
33543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // If top is on the same page as the current object, we need to check whether
33553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // we are below top.
33563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&top_check);
33573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  lea(scratch_reg, Operand(receiver_reg, kMementoEndOffset));
3358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(scratch_reg, Operand::StaticVariable(new_space_allocation_top));
3359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(greater, no_memento_found);
33603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Memento map check.
33613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&map_check);
33623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(scratch_reg, Operand(receiver_reg, kMementoMapOffset));
33633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  cmp(scratch_reg, Immediate(isolate()->factory()->allocation_memento_map()));
3364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfDictionaryInPrototypeChain(
3368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register object,
3369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch0,
3370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch1,
3371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label* found) {
3372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!scratch1.is(scratch0));
3373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Factory* factory = isolate()->factory();
3374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register current = scratch0;
3375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label loop_again, end;
3376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // scratch contained elements pointer.
3378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(current, object);
3379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(current, FieldOperand(current, HeapObject::kMapOffset));
3380014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(current, FieldOperand(current, Map::kPrototypeOffset));
3381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  cmp(current, Immediate(factory->null_value()));
3382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(equal, &end);
3383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Loop based on the map going up the prototype chain.
3385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&loop_again);
3386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(current, FieldOperand(current, HeapObject::kMapOffset));
3387014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(JS_PROXY_TYPE < JS_OBJECT_TYPE);
3388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(JS_VALUE_TYPE < JS_OBJECT_TYPE);
3389014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CmpInstanceType(current, JS_OBJECT_TYPE);
3390014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(below, found);
3391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(scratch1, FieldOperand(current, Map::kBitField2Offset));
3392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DecodeField<Map::ElementsKindBits>(scratch1);
3393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(scratch1, Immediate(DICTIONARY_ELEMENTS));
3394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(equal, found);
3395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(current, FieldOperand(current, Map::kPrototypeOffset));
3396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(current, Immediate(factory->null_value()));
3397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(not_equal, &loop_again);
3398014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3399014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&end);
3400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TruncatingDiv(Register dividend, int32_t divisor) {
3404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dividend.is(eax));
3405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dividend.is(edx));
3406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::MagicNumbersForDivision<uint32_t> mag =
3407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      base::SignedDivisionByConstant(static_cast<uint32_t>(divisor));
3408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(eax, Immediate(mag.multiplier));
3409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  imul(dividend);
3410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool neg = (mag.multiplier & (static_cast<uint32_t>(1) << 31)) != 0;
3411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor > 0 && neg) add(edx, dividend);
3412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor < 0 && !neg && mag.multiplier > 0) sub(edx, dividend);
3413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (mag.shift > 0) sar(edx, mag.shift);
3414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(eax, dividend);
3415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shr(eax, 31);
3416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  add(edx, eax);
3417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3420014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
3421014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
3422f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3423f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_IA32
3424