1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen 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_X87
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"
12958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/runtime/runtime.h"
13014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/x87/frames-x87.h"
14014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/x87/macro-assembler-x87.h"
15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 {
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal {
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// -------------------------------------------------------------------------
20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// MacroAssembler implementation.
21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochMacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size,
23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                               CodeObjectRequired create_code_object)
24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    : Assembler(arg_isolate, buffer, size),
25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      generating_stub_(false),
26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen 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());
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
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    }
1438389745919cae02139ddc085a63c00d024269cf2Ben Murdoch  }
144109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (fp_mode == kSaveFPRegs) {
145109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // Save FPU state in m108byte.
146109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    sub(esp, Immediate(108));
147109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    fnsave(Operand(esp, 0));
148109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
149109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
150109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
151109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
152109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                    Register exclusion2, Register exclusion3) {
153109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (fp_mode == kSaveFPRegs) {
154109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // Restore FPU state in m108byte.
155109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    frstor(Operand(esp, 0));
156109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    add(esp, Immediate(108));
157109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
158109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
159109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  for (int i = kNumberOfSavedRegs - 1; i >= 0; i--) {
160109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Register reg = saved_regs[i];
161109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    if (!reg.is(exclusion1) && !reg.is(exclusion2) && !reg.is(exclusion3)) {
162109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      pop(reg);
163109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
164109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
165109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
166109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
167109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::InNewSpace(Register object, Register scratch, Condition cc,
168109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                Label* condition_met,
169109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                Label::Distance distance) {
170f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  CheckPageFlag(object, scratch, MemoryChunk::kIsInNewSpaceMask, cc,
171f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                condition_met, distance);
172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::RememberedSetHelper(
176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register object,  // Only used for debug checks.
177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register addr, Register scratch, SaveFPRegsMode save_fp,
178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MacroAssembler::RememberedSetFinalAction and_then) {
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label ok;
182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    JumpIfNotInNewSpace(object, scratch, &ok, Label::kNear);
183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int3();
184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&ok);
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load store buffer top.
187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference store_buffer =
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::store_buffer_top(isolate());
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(scratch, Operand::StaticVariable(store_buffer));
190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Store pointer to buffer.
191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(Operand(scratch, 0), addr);
192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Increment buffer top.
193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  add(scratch, Immediate(kPointerSize));
194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Write back new top of buffer.
195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(Operand::StaticVariable(store_buffer), scratch);
196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Call stub on end of buffer.
197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for end of buffer.
1983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test(scratch, Immediate(StoreBuffer::kStoreBufferMask));
199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (and_then == kReturnAtEnd) {
200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label buffer_overflowed;
2013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    j(equal, &buffer_overflowed, Label::kNear);
202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ret(0);
203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&buffer_overflowed);
204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(and_then == kFallThroughAtEnd);
2063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    j(not_equal, &done, Label::kNear);
207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StoreBufferOverflowStub store_buffer_overflow(isolate(), save_fp);
209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallStub(&store_buffer_overflow);
210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (and_then == kReturnAtEnd) {
211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ret(0);
212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(and_then == kFallThroughAtEnd);
214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&done);
215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::ClampTOSToUint8(Register result_reg) {
220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done, conv_failure;
221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  sub(esp, Immediate(kPointerSize));
222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fnclex();
223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fist_s(Operand(esp, 0));
224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pop(result_reg);
225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87CheckIA();
226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(equal, &conv_failure, Label::kNear);
227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  test(result_reg, Immediate(0xFFFFFF00));
228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(zero, &done, Label::kNear);
229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  setcc(sign, result_reg);
230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  sub(result_reg, Immediate(1));
231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  and_(result_reg, Immediate(255));
232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  jmp(&done, Label::kNear);
233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&conv_failure);
234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fnclex();
235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fldz();
236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fld(1);
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FCmp();
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  setcc(below, result_reg);  // 1 if negative, 0 if positive.
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  dec_b(result_reg);         // 0 if negative, 255 if positive.
240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::ClampUint8(Register reg) {
245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  test(reg, Immediate(0xFFFFFF00));
247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(zero, &done, Label::kNear);
248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  setcc(negative, reg);  // 1 if negative, 0 if positive.
249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  dec_b(reg);  // 0 if negative, 255 if positive.
250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::SlowTruncateToI(Register result_reg,
255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     Register input_reg,
256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     int offset) {
257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleToIStub stub(isolate(), input_reg, result_reg, offset, true);
258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  call(stub.GetCode(), RelocInfo::CODE_TARGET);
259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TruncateX87TOSToI(Register result_reg) {
263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  sub(esp, Immediate(kDoubleSize));
264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fst_d(MemOperand(esp, 0));
265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SlowTruncateToI(result_reg, esp, 0);
266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  add(esp, Immediate(kDoubleSize));
267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::X87TOSToI(Register result_reg,
271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               MinusZeroMode minus_zero_mode,
272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Label* lost_precision, Label* is_nan,
273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Label* minus_zero, Label::Distance dst) {
274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  sub(esp, Immediate(kPointerSize));
276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fld(0);
277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fist_s(MemOperand(esp, 0));
278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fild_s(MemOperand(esp, 0));
279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pop(result_reg);
280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FCmp();
281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(not_equal, lost_precision, dst);
282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(parity_even, is_nan, dst);
283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (minus_zero_mode == FAIL_ON_MINUS_ZERO) {
284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(result_reg, Operand(result_reg));
285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(not_zero, &done, Label::kNear);
286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // To check for minus zero, we load the value again as float, and check
287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // if that is still 0.
288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sub(esp, Immediate(kPointerSize));
289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    fst_s(MemOperand(esp, 0));
290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    pop(result_reg);
291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(result_reg, Operand(result_reg));
292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(not_zero, minus_zero, dst);
293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TruncateHeapNumberToI(Register result_reg,
299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register input_reg) {
300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done, slow_case;
301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SlowTruncateToI(result_reg, input_reg);
303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
307958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::LoadUint32NoSSE2(const Operand& src) {
308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  push(src);
310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fild_s(Operand(esp, 0));
311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(src, Immediate(0));
312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(not_sign, &done, Label::kNear);
313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference uint32_bias =
314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ExternalReference::address_of_uint32_bias();
315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fld_d(Operand::StaticVariable(uint32_bias));
316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  faddp(1);
317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  add(esp, Immediate(kPointerSize));
319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::RecordWriteArray(
323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register object, Register value, Register index, SaveFPRegsMode save_fp,
324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RememberedSetAction remembered_set_action, SmiCheck smi_check,
325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PointersToHereCheck pointers_to_here_check_for_value) {
326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // First, check if a write barrier is even needed. The tests below
327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // catch stores of Smis.
328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Skip barrier if writing a smi.
331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (smi_check == INLINE_SMI_CHECK) {
332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_EQ(0, kSmiTag);
333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(value, Immediate(kSmiTagMask));
334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(zero, &done);
335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Array access: calculate the destination address in the same manner as
338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // KeyedStoreIC::GenerateGeneric.  Multiply a smi by 2 to get an offset
339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // into an array of words.
340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register dst = index;
341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lea(dst, Operand(object, index, times_half_pointer_size,
342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   FixedArray::kHeaderSize - kHeapObjectTag));
343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordWrite(object, dst, value, save_fp, remembered_set_action,
345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              OMIT_SMI_CHECK, pointers_to_here_check_for_value);
346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Clobber clobbered input registers when running with the debug-code flag
350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // turned on to provoke errors.
351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(value, Immediate(bit_cast<int32_t>(kZapValue)));
353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(index, Immediate(bit_cast<int32_t>(kZapValue)));
354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::RecordWriteField(
359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register object, int offset, Register value, Register dst,
360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SaveFPRegsMode save_fp, RememberedSetAction remembered_set_action,
361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiCheck smi_check, PointersToHereCheck pointers_to_here_check_for_value) {
362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // First, check if a write barrier is even needed. The tests below
363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // catch stores of Smis.
364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Skip barrier if writing a smi.
367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (smi_check == INLINE_SMI_CHECK) {
368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    JumpIfSmi(value, &done, Label::kNear);
369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Although the object register is tagged, the offset is relative to the start
372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // of the object, so so offset must be a multiple of kPointerSize.
373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsAligned(offset, kPointerSize));
374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lea(dst, FieldOperand(object, offset));
376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label ok;
3783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    test_b(dst, Immediate((1 << kPointerSizeLog2) - 1));
379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(zero, &ok, Label::kNear);
380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int3();
381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&ok);
382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordWrite(object, dst, value, save_fp, remembered_set_action,
385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              OMIT_SMI_CHECK, pointers_to_here_check_for_value);
386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Clobber clobbered input registers when running with the debug-code flag
390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // turned on to provoke errors.
391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(value, Immediate(bit_cast<int32_t>(kZapValue)));
393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(dst, Immediate(bit_cast<int32_t>(kZapValue)));
394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::RecordWriteForMap(Register object, Handle<Map> map,
399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       Register scratch1, Register scratch2,
400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       SaveFPRegsMode save_fp) {
401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register address = scratch1;
404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register value = scratch2;
405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label ok;
407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    lea(address, FieldOperand(object, HeapObject::kMapOffset));
4083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    test_b(address, Immediate((1 << kPointerSizeLog2) - 1));
409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(zero, &ok, Label::kNear);
410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int3();
411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&ok);
412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!object.is(value));
415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!object.is(address));
416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!value.is(address));
417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertNotSmi(object);
418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!FLAG_incremental_marking) {
420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Compute the address.
424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lea(address, FieldOperand(object, HeapObject::kMapOffset));
425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // A single check of the map's pages interesting flag suffices, since it is
427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // only set during incremental collection, and then it's also guaranteed that
428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the from object's page's interesting flag is also set.  This optimization
429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // relies on the fact that maps can never be in new space.
430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!isolate()->heap()->InNewSpace(*map));
431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckPageFlagForMap(map,
432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      MemoryChunk::kPointersToHereAreInterestingMask,
433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      zero,
434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      &done,
435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      Label::kNear);
436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordWriteStub stub(isolate(), object, value, address, OMIT_REMEMBERED_SET,
438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       save_fp);
439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallStub(&stub);
440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Count number of write barriers in generated code.
444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate()->counters()->write_barriers_static()->Increment();
445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1);
446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Clobber clobbered input registers when running with the debug-code flag
448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // turned on to provoke errors.
449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(value, Immediate(bit_cast<int32_t>(kZapValue)));
451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(scratch1, Immediate(bit_cast<int32_t>(kZapValue)));
452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(scratch2, Immediate(bit_cast<int32_t>(kZapValue)));
453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::RecordWrite(
458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register object, Register address, Register value, SaveFPRegsMode fp_mode,
459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RememberedSetAction remembered_set_action, SmiCheck smi_check,
460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PointersToHereCheck pointers_to_here_check_for_value) {
461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!object.is(value));
462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!object.is(address));
463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!value.is(address));
464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertNotSmi(object);
465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (remembered_set_action == OMIT_REMEMBERED_SET &&
467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      !FLAG_incremental_marking) {
468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label ok;
473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(value, Operand(address, 0));
474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(equal, &ok, Label::kNear);
475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int3();
476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&ok);
477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // First, check if a write barrier is even needed. The tests below
480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // catch stores of Smis and stores into young gen.
481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (smi_check == INLINE_SMI_CHECK) {
484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Skip barrier if writing a smi.
485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    JumpIfSmi(value, &done, Label::kNear);
486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (pointers_to_here_check_for_value != kPointersToHereAreAlwaysInteresting) {
489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CheckPageFlag(value,
490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  value,  // Used as scratch.
491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  MemoryChunk::kPointersToHereAreInterestingMask,
492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  zero,
493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  &done,
494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  Label::kNear);
495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckPageFlag(object,
497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                value,  // Used as scratch.
498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                MemoryChunk::kPointersFromHereAreInterestingMask,
499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                zero,
500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                &done,
501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Label::kNear);
502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordWriteStub stub(isolate(), object, value, address, remembered_set_action,
504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       fp_mode);
505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallStub(&stub);
506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Count number of write barriers in generated code.
510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate()->counters()->write_barriers_static()->Increment();
511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1);
512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Clobber clobbered registers when running with the debug-code flag
514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // turned on to provoke errors.
515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(address, Immediate(bit_cast<int32_t>(kZapValue)));
517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(value, Immediate(bit_cast<int32_t>(kZapValue)));
518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
521109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::RecordWriteCodeEntryField(Register js_function,
522109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                               Register code_entry,
523109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                               Register scratch) {
524109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  const int offset = JSFunction::kCodeEntryOffset;
525109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
526109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Since a code entry (value) is always in old space, we don't need to update
527109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // remembered set. If incremental marking is off, there is nothing for us to
528109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // do.
529109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (!FLAG_incremental_marking) return;
530109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
531109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(!js_function.is(code_entry));
532109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(!js_function.is(scratch));
533109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(!code_entry.is(scratch));
534109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  AssertNotSmi(js_function);
535109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
536109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (emit_debug_code()) {
537109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Label ok;
538109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    lea(scratch, FieldOperand(js_function, offset));
539109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    cmp(code_entry, Operand(scratch, 0));
540109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    j(equal, &ok, Label::kNear);
541109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    int3();
542109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    bind(&ok);
543109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
544109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
545109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // First, check if a write barrier is even needed. The tests below
546109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // catch stores of Smis and stores into young gen.
547109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Label done;
548109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
549109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  CheckPageFlag(code_entry, scratch,
550109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                MemoryChunk::kPointersToHereAreInterestingMask, zero, &done,
551109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                Label::kNear);
552109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  CheckPageFlag(js_function, scratch,
553109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                MemoryChunk::kPointersFromHereAreInterestingMask, zero, &done,
554109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                Label::kNear);
555109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
556109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Save input registers.
557109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  push(js_function);
558109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  push(code_entry);
559109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
560109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  const Register dst = scratch;
561109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  lea(dst, FieldOperand(js_function, offset));
562109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
563109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Save caller-saved registers.
564109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PushCallerSaved(kDontSaveFPRegs, js_function, code_entry);
565109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
566109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  int argument_count = 3;
567109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PrepareCallCFunction(argument_count, code_entry);
568109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  mov(Operand(esp, 0 * kPointerSize), js_function);
569109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  mov(Operand(esp, 1 * kPointerSize), dst);  // Slot.
570109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  mov(Operand(esp, 2 * kPointerSize),
571109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      Immediate(ExternalReference::isolate_address(isolate())));
572109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
573109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  {
574109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    AllowExternalCallThatCantCauseGC scope(this);
575109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    CallCFunction(
576109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        ExternalReference::incremental_marking_record_write_code_entry_function(
577109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch            isolate()),
578109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        argument_count);
579109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
580109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
581109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Restore caller-saved registers.
582109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PopCallerSaved(kDontSaveFPRegs, js_function, code_entry);
583109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
584109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Restore input registers.
585109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  pop(code_entry);
586109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  pop(js_function);
587109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
588109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  bind(&done);
589109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::DebugBreak() {
592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Move(eax, Immediate(0));
593014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(ebx, Immediate(ExternalReference(Runtime::kHandleDebuggerStatement,
594014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                       isolate())));
595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CEntryStub ces(isolate(), 1);
596014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  call(ces.GetCode(), RelocInfo::DEBUGGER_STATEMENT);
597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::ShlPair(Register high, Register low, uint8_t shift) {
6003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (shift >= 32) {
6013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    mov(high, low);
6023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shl(high, shift - 32);
6033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    xor_(low, low);
6043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
6053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shld(high, low, shift);
6063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shl(low, shift);
6073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
6083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
6093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
6103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::ShlPair_cl(Register high, Register low) {
6113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  shld_cl(high, low);
6123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  shl_cl(low);
6133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label done;
6143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test(ecx, Immediate(0x20));
6153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  j(equal, &done, Label::kNear);
6163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(high, low);
6173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  xor_(low, low);
6183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&done);
6193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
6203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
6213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::ShrPair(Register high, Register low, uint8_t shift) {
6223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (shift >= 32) {
6233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    mov(low, high);
6243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shr(low, shift - 32);
6253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    xor_(high, high);
6263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
6273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shrd(high, low, shift);
6283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shr(high, shift);
6293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
6303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
6313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
6323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::ShrPair_cl(Register high, Register low) {
6333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  shrd_cl(low, high);
6343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  shr_cl(high);
6353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label done;
6363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test(ecx, Immediate(0x20));
6373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  j(equal, &done, Label::kNear);
6383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(low, high);
6393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  xor_(high, high);
6403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&done);
6413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
6423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
6433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::SarPair(Register high, Register low, uint8_t shift) {
6443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (shift >= 32) {
6453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    mov(low, high);
6463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    sar(low, shift - 32);
6473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    sar(high, 31);
6483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
6493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shrd(high, low, shift);
6503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    sar(high, shift);
6513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
6523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
6533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
6543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::SarPair_cl(Register high, Register low) {
6553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  shrd_cl(low, high);
6563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  sar_cl(high);
6573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label done;
6583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test(ecx, Immediate(0x20));
6593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  j(equal, &done, Label::kNear);
6603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(low, high);
6613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  sar(high, 31);
6623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&done);
6633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool MacroAssembler::IsUnsafeImmediate(const Immediate& x) {
666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int kMaxImmediateBits = 17;
667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!RelocInfo::IsNone(x.rmode_)) return false;
668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return !is_intn(x.x_, kMaxImmediateBits);
669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::SafeMove(Register dst, const Immediate& x) {
673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsUnsafeImmediate(x) && jit_cookie() != 0) {
674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(dst, Immediate(x.x_ ^ jit_cookie()));
675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    xor_(dst, jit_cookie());
676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(dst, x);
678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::SafePush(const Immediate& x) {
683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsUnsafeImmediate(x) && jit_cookie() != 0) {
684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    push(Immediate(x.x_ ^ jit_cookie()));
685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    xor_(Operand(esp, 0), Immediate(jit_cookie()));
686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    push(x);
688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CmpObjectType(Register heap_object,
693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   InstanceType type,
694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register map) {
695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(map, FieldOperand(heap_object, HeapObject::kMapOffset));
696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CmpInstanceType(map, type);
697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CmpInstanceType(Register map, InstanceType type) {
7013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  cmpb(FieldOperand(map, Map::kInstanceTypeOffset), Immediate(type));
702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CompareMap(Register obj, Handle<Map> map) {
705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(FieldOperand(obj, HeapObject::kMapOffset), map);
706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CheckMap(Register obj,
710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Handle<Map> map,
711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Label* fail,
712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              SmiCheckType smi_check_type) {
713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (smi_check_type == DO_SMI_CHECK) {
714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    JumpIfSmi(obj, fail);
715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompareMap(obj, map);
718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(not_equal, fail);
719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
722958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::DispatchWeakMap(Register obj, Register scratch1,
723958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                     Register scratch2, Handle<WeakCell> cell,
724958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                     Handle<Code> success,
725958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                     SmiCheckType smi_check_type) {
726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label fail;
727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (smi_check_type == DO_SMI_CHECK) {
728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    JumpIfSmi(obj, &fail);
729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
730958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  mov(scratch1, FieldOperand(obj, HeapObject::kMapOffset));
731958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CmpWeakValue(scratch1, cell, scratch2);
732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(equal, success);
733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&fail);
735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochCondition MacroAssembler::IsObjectStringType(Register heap_object,
739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                             Register map,
740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                             Register instance_type) {
741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(map, FieldOperand(heap_object, HeapObject::kMapOffset));
742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(kNotStringTag != 0);
744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  test(instance_type, Immediate(kIsNotStringMask));
745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return zero;
746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochCondition MacroAssembler::IsObjectNameType(Register heap_object,
750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register map,
751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register instance_type) {
752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(map, FieldOperand(heap_object, HeapObject::kMapOffset));
753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
7543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  cmpb(instance_type, Immediate(LAST_NAME_TYPE));
755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return below_equal;
756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::FCmp() {
760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fucompp();
761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  push(eax);
762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fnstsw_ax();
763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  sahf();
764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pop(eax);
765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::FXamMinusZero() {
769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fxam();
770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  push(eax);
771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fnstsw_ax();
772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  and_(eax, Immediate(0x4700));
773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // For minus zero, C3 == 1 && C1 == 1.
774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(eax, Immediate(0x4200));
775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pop(eax);
776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fstp(0);
777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::FXamSign() {
781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fxam();
782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  push(eax);
783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fnstsw_ax();
784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // For negative value (including -0.0), C1 == 1.
785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  and_(eax, Immediate(0x0200));
786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pop(eax);
787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fstp(0);
788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::X87CheckIA() {
792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  push(eax);
793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fnstsw_ax();
794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // For #IA, IE == 1 && SF == 0.
795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  and_(eax, Immediate(0x0041));
796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(eax, Immediate(0x0001));
797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pop(eax);
798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// rc=00B, round to nearest.
802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// rc=01B, round down.
803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// rc=10B, round up.
804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// rc=11B, round toward zero.
805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::X87SetRC(int rc) {
806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  sub(esp, Immediate(kPointerSize));
807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fnstcw(MemOperand(esp, 0));
808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  and_(MemOperand(esp, 0), Immediate(0xF3FF));
809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  or_(MemOperand(esp, 0), Immediate(rc));
810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fldcw(MemOperand(esp, 0));
811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  add(esp, Immediate(kPointerSize));
812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::X87SetFPUCW(int cw) {
816014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  RecordComment("-- X87SetFPUCW start --");
817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  push(Immediate(cw));
818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fldcw(MemOperand(esp, 0));
819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  add(esp, Immediate(kPointerSize));
820014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  RecordComment("-- X87SetFPUCW end--");
821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertNumber(Register object) {
825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label ok;
827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    JumpIfSmi(object, &ok);
828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(FieldOperand(object, HeapObject::kMapOffset),
829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate()->factory()->heap_number_map());
830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, kOperandNotANumber);
831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&ok);
832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::AssertNotNumber(Register object) {
8363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (emit_debug_code()) {
8373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    test(object, Immediate(kSmiTagMask));
8383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Check(not_equal, kOperandIsANumber);
8393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    cmp(FieldOperand(object, HeapObject::kMapOffset),
8403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        isolate()->factory()->heap_number_map());
8413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Check(not_equal, kOperandIsANumber);
8423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
8433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertSmi(Register object) {
846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(object, Immediate(kSmiTagMask));
848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, kOperandIsNotASmi);
849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertString(Register object) {
854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(object, Immediate(kSmiTagMask));
856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kOperandIsASmiAndNotAString);
857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    push(object);
858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(object, FieldOperand(object, HeapObject::kMapOffset));
859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CmpInstanceType(object, FIRST_NONSTRING_TYPE);
860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    pop(object);
861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(below, kOperandIsNotAString);
862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertName(Register object) {
867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(object, Immediate(kSmiTagMask));
869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kOperandIsASmiAndNotAName);
870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    push(object);
871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(object, FieldOperand(object, HeapObject::kMapOffset));
872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CmpInstanceType(object, LAST_NAME_TYPE);
873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    pop(object);
874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(below_equal, kOperandIsNotAName);
875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
879014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::AssertFunction(Register object) {
880014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (emit_debug_code()) {
881014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    test(object, Immediate(kSmiTagMask));
882014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(not_equal, kOperandIsASmiAndNotAFunction);
883014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(object);
884014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CmpObjectType(object, JS_FUNCTION_TYPE, object);
885014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Pop(object);
886014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(equal, kOperandIsNotAFunction);
887014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
888014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
889014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
890014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
891014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::AssertBoundFunction(Register object) {
892014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (emit_debug_code()) {
893014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    test(object, Immediate(kSmiTagMask));
894014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(not_equal, kOperandIsASmiAndNotABoundFunction);
895014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(object);
896014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CmpObjectType(object, JS_BOUND_FUNCTION_TYPE, object);
897014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Pop(object);
898014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(equal, kOperandIsNotABoundFunction);
899014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
900014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
901014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
902bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::AssertGeneratorObject(Register object) {
903bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (emit_debug_code()) {
904bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    test(object, Immediate(kSmiTagMask));
905bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Check(not_equal, kOperandIsASmiAndNotAGeneratorObject);
906bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Push(object);
907bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    CmpObjectType(object, JS_GENERATOR_OBJECT_TYPE, object);
908bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Pop(object);
909bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Check(equal, kOperandIsNotAGeneratorObject);
910bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
911bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
912bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
913109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::AssertReceiver(Register object) {
914109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (emit_debug_code()) {
915109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    test(object, Immediate(kSmiTagMask));
916109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Check(not_equal, kOperandIsASmiAndNotAReceiver);
917109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Push(object);
918109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
919109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    CmpObjectType(object, FIRST_JS_RECEIVER_TYPE, object);
920109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Pop(object);
921109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Check(above_equal, kOperandIsNotAReceiver);
922109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
923109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertUndefinedOrAllocationSite(Register object) {
926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label done_checking;
928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AssertNotSmi(object);
929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(object, isolate()->factory()->undefined_value());
930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(equal, &done_checking);
931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(FieldOperand(object, 0),
932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Immediate(isolate()->factory()->allocation_site_map()));
933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Assert(equal, kExpectedUndefinedOrCell);
934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&done_checking);
935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertNotSmi(Register object) {
940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(object, Immediate(kSmiTagMask));
942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kOperandIsASmi);
943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
9463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::StubPrologue(StackFrame::Type type) {
947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  push(ebp);  // Caller's frame pointer.
948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(ebp, esp);
9493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  push(Immediate(Smi::FromInt(type)));
950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Prologue(bool code_pre_aging) {
954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PredictableCodeSizeScope predictible_code_size_scope(this,
955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kNoCodeAgeSequenceLength);
956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (code_pre_aging) {
957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Pre-age the code.
958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    call(isolate()->builtins()->MarkCodeAsExecutedOnce(),
959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        RelocInfo::CODE_AGE_SEQUENCE);
960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Nop(kNoCodeAgeSequenceLength - Assembler::kCallInstructionLength);
961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    push(ebp);  // Caller's frame pointer.
963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(ebp, esp);
964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    push(esi);  // Callee's context.
965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    push(edi);  // Callee's JS function.
966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
96962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid MacroAssembler::EmitLoadFeedbackVector(Register vector) {
970014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(vector, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
97162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  mov(vector, FieldOperand(vector, JSFunction::kFeedbackVectorOffset));
97262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  mov(vector, FieldOperand(vector, Cell::kValueOffset));
973014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
975014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
976958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::EnterFrame(StackFrame::Type type,
977958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                bool load_constant_pool_pointer_reg) {
978958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Out-of-line constant pool not implemented on x87.
979958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  UNREACHABLE();
980958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
981958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
982958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::EnterFrame(StackFrame::Type type) {
984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  push(ebp);
985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(ebp, esp);
986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  push(Immediate(Smi::FromInt(type)));
9873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (type == StackFrame::INTERNAL) {
9883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    push(Immediate(CodeObject()));
9893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(Operand(esp, 0), Immediate(isolate()->factory()->undefined_value()));
992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kCodeObjectNotProperlyPatched);
993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::LeaveFrame(StackFrame::Type type) {
998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
9993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    cmp(Operand(ebp, CommonFrameConstants::kContextOrFrameTypeOffset),
1000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Immediate(Smi::FromInt(type)));
1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, kStackFrameTypesMustMatch);
1002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  leave();
1004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1006f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MacroAssembler::EnterBuiltinFrame(Register context, Register target,
1007f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                       Register argc) {
1008f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Push(ebp);
1009f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Move(ebp, esp);
1010f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Push(context);
1011f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Push(target);
1012f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Push(argc);
1013f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
1014f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1015f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MacroAssembler::LeaveBuiltinFrame(Register context, Register target,
1016f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                       Register argc) {
1017f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Pop(argc);
1018f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Pop(target);
1019f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Pop(context);
1020f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  leave();
1021f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
1022f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1023f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MacroAssembler::EnterExitFramePrologue(StackFrame::Type frame_type) {
1024f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(frame_type == StackFrame::EXIT ||
1025f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch         frame_type == StackFrame::BUILTIN_EXIT);
1026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Set up the frame structure on the stack.
10283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(+2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement);
10293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(+1 * kPointerSize, ExitFrameConstants::kCallerPCOffset);
10303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset);
1031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  push(ebp);
1032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(ebp, esp);
1033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Reserve room for entry stack pointer and push the code object.
1035f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  push(Immediate(Smi::FromInt(frame_type)));
10363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(-2 * kPointerSize, ExitFrameConstants::kSPOffset);
1037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  push(Immediate(0));  // Saved entry sp, patched before call.
10383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(-3 * kPointerSize, ExitFrameConstants::kCodeOffset);
1039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  push(Immediate(CodeObject()));  // Accessed from ExitFrame::code_slot.
1040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Save the frame pointer and the context in top.
1042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress, isolate());
1043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference context_address(Isolate::kContextAddress, isolate());
1044958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ExternalReference c_function_address(Isolate::kCFunctionAddress, isolate());
1045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(Operand::StaticVariable(c_entry_fp_address), ebp);
1046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(Operand::StaticVariable(context_address), esi);
1047958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  mov(Operand::StaticVariable(c_function_address), ebx);
1048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::EnterExitFrameEpilogue(int argc, bool save_doubles) {
1052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Optionally save FPU state.
1053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (save_doubles) {
1054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Store FPU state to m108byte.
1055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int space = 108 + argc * kPointerSize;
1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sub(esp, Immediate(space));
10573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    const int offset = -ExitFrameConstants::kFixedFrameSizeFromFp;
1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    fnsave(MemOperand(ebp, offset - 108));
1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sub(esp, Immediate(argc * kPointerSize));
1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Get the required frame alignment for the OS.
1064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kFrameAlignment = base::OS::ActivationFrameAlignment();
1065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (kFrameAlignment > 0) {
1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(base::bits::IsPowerOfTwo32(kFrameAlignment));
1067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    and_(esp, -kFrameAlignment);
1068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Patch the saved entry sp.
1071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(Operand(ebp, ExitFrameConstants::kSPOffset), esp);
1072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1074f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MacroAssembler::EnterExitFrame(int argc, bool save_doubles,
1075f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                    StackFrame::Type frame_type) {
1076f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  EnterExitFramePrologue(frame_type);
1077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Set up argc and argv in callee-saved registers.
1079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
1080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(edi, eax);
1081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lea(esi, Operand(ebp, eax, times_4, offset));
1082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Reserve space for argc, argv and isolate.
1084109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  EnterExitFrameEpilogue(argc, save_doubles);
1085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::EnterApiExitFrame(int argc) {
1089f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  EnterExitFramePrologue(StackFrame::EXIT);
1090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EnterExitFrameEpilogue(argc, false);
1091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1094014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LeaveExitFrame(bool save_doubles, bool pop_arguments) {
1095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Optionally restore FPU state.
1096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (save_doubles) {
10973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    const int offset = -ExitFrameConstants::kFixedFrameSizeFromFp;
1098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    frstor(MemOperand(ebp, offset - 108));
1099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (pop_arguments) {
1102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Get the return address from the stack and restore the frame pointer.
1103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mov(ecx, Operand(ebp, 1 * kPointerSize));
1104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mov(ebp, Operand(ebp, 0 * kPointerSize));
1105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Pop the arguments and the receiver from the caller stack.
1107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    lea(esp, Operand(esi, 1 * kPointerSize));
1108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Push the return address to get ready to return.
1110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    push(ecx);
1111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
1112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Otherwise just leave the exit frame.
1113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    leave();
1114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LeaveExitFrameEpilogue(true);
1117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::LeaveExitFrameEpilogue(bool restore_context) {
1121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Restore current context from top and clear it in debug mode.
1122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference context_address(Isolate::kContextAddress, isolate());
1123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (restore_context) {
1124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(esi, Operand::StaticVariable(context_address));
1125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
1127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(Operand::StaticVariable(context_address), Immediate(0));
1128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
1129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Clear the top frame.
1131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress,
1132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       isolate());
1133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(Operand::StaticVariable(c_entry_fp_address), Immediate(0));
1134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::LeaveApiExitFrame(bool restore_context) {
1138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(esp, ebp);
1139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pop(ebp);
1140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LeaveExitFrameEpilogue(restore_context);
1142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::PushStackHandler() {
1146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Adjust this code if not the case.
1147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(StackHandlerConstants::kSize == 1 * kPointerSize);
1148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
1149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Link the current handler as the next handler.
1151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
1152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  push(Operand::StaticVariable(handler_address));
1153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Set this new handler as the current one.
1155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(Operand::StaticVariable(handler_address), esp);
1156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::PopStackHandler() {
1160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
1161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
1162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pop(Operand::StaticVariable(handler_address));
1163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  add(esp, Immediate(StackHandlerConstants::kSize - kPointerSize));
1164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Compute the hash code from the untagged key.  This must be kept in sync with
1168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ComputeIntegerHash in utils.h and KeyedLoadGenericStub in
1169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// code-stub-hydrogen.cc
1170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
1171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Note: r0 will contain hash code
1172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::GetNumberHash(Register r0, Register scratch) {
1173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Xor original key with a seed.
1174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (serializer_enabled()) {
1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ExternalReference roots_array_start =
1176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ExternalReference::roots_array_start(isolate());
1177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(scratch, Immediate(Heap::kHashSeedRootIndex));
1178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(scratch,
1179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Operand::StaticArray(scratch, times_pointer_size, roots_array_start));
1180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiUntag(scratch);
1181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    xor_(r0, scratch);
1182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int32_t seed = isolate()->heap()->HashSeed();
1184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    xor_(r0, Immediate(seed));
1185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // hash = ~hash + (hash << 15);
1188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(scratch, r0);
1189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  not_(r0);
1190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shl(scratch, 15);
1191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  add(r0, scratch);
1192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // hash = hash ^ (hash >> 12);
1193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(scratch, r0);
1194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shr(scratch, 12);
1195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  xor_(r0, scratch);
1196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // hash = hash + (hash << 2);
1197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lea(r0, Operand(r0, r0, times_4, 0));
1198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // hash = hash ^ (hash >> 4);
1199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(scratch, r0);
1200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shr(scratch, 4);
1201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  xor_(r0, scratch);
1202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // hash = hash * 2057;
1203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  imul(r0, r0, 2057);
1204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // hash = hash ^ (hash >> 16);
1205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(scratch, r0);
1206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shr(scratch, 16);
1207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  xor_(r0, scratch);
1208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  and_(r0, 0x3fffffff);
1209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::LoadAllocationTopHelper(Register result,
1212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                             Register scratch,
1213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                             AllocationFlags flags) {
1214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_top =
1215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationTopReference(isolate(), flags);
1216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Just return if allocation top is already known.
1218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if ((flags & RESULT_CONTAINS_TOP) != 0) {
1219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // No use of scratch if allocation top is provided.
1220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(scratch.is(no_reg));
1221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
1222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Assert that result actually contains top on entry.
1223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(result, Operand::StaticVariable(allocation_top));
1224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, kUnexpectedAllocationTop);
1225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
1226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Move address of new object to result. Use scratch register if available.
1230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (scratch.is(no_reg)) {
1231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(result, Operand::StaticVariable(allocation_top));
1232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(scratch, Immediate(allocation_top));
1234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(result, Operand(scratch, 0));
1235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::UpdateAllocationTopHelper(Register result_end,
1240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register scratch,
1241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               AllocationFlags flags) {
1242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
1243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(result_end, Immediate(kObjectAlignmentMask));
1244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(zero, kUnalignedAllocationInNewSpace);
1245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_top =
1248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationTopReference(isolate(), flags);
1249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Update new top. Use scratch if available.
1251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (scratch.is(no_reg)) {
1252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(Operand::StaticVariable(allocation_top), result_end);
1253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(Operand(scratch, 0), result_end);
1255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Allocate(int object_size,
1260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result,
1261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result_end,
1262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register scratch,
1263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Label* gc_required,
1264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              AllocationFlags flags) {
1265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0);
1266f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(object_size <= kMaxRegularHeapObjectSize);
1267bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK((flags & ALLOCATION_FOLDED) == 0);
1268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!FLAG_inline_new) {
1269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (emit_debug_code()) {
1270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Trash the registers to simulate an allocation failure.
1271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mov(result, Immediate(0x7091));
1272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (result_end.is_valid()) {
1273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        mov(result_end, Immediate(0x7191));
1274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (scratch.is_valid()) {
1276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        mov(scratch, Immediate(0x7291));
1277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    jmp(gc_required);
1280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
1281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result.is(result_end));
1283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load address of new object into result.
1285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LoadAllocationTopHelper(result, scratch, flags);
1286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_limit =
1288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationLimitReference(isolate(), flags);
1289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Align the next allocation. Storing the filler map without checking top is
1291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // safe in new-space because the limit of the heap is aligned there.
1292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
1293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
1294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label aligned;
1295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(result, Immediate(kDoubleAlignmentMask));
1296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(zero, &aligned, Label::kNear);
1297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if ((flags & PRETENURE) != 0) {
1298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cmp(result, Operand::StaticVariable(allocation_limit));
1299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      j(above_equal, gc_required);
1300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(Operand(result, 0),
1302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Immediate(isolate()->factory()->one_pointer_filler_map()));
1303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    add(result, Immediate(kDoubleSize / 2));
1304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&aligned);
1305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Calculate new top and bail out if space is exhausted.
1308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register top_reg = result_end.is_valid() ? result_end : result;
1309bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!top_reg.is(result)) {
1311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(top_reg, result);
1312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  add(top_reg, Immediate(object_size));
1314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(top_reg, Operand::StaticVariable(allocation_limit));
1315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(above, gc_required);
1316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1317bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
1318bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // The top pointer is not updated for allocation folding dominators.
1319bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    UpdateAllocationTopHelper(top_reg, scratch, flags);
1320bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (top_reg.is(result)) {
1323bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    sub(result, Immediate(object_size - kHeapObjectTag));
1324bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  } else {
1325bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // Tag the result.
1326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kHeapObjectTag == 1);
1327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    inc(result);
1328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Allocate(int header_size,
1333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              ScaleFactor element_size,
1334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register element_count,
1335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              RegisterValueType element_count_type,
1336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result,
1337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result_end,
1338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register scratch,
1339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Label* gc_required,
1340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              AllocationFlags flags) {
1341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((flags & SIZE_IN_WORDS) == 0);
1342bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK((flags & ALLOCATION_FOLDING_DOMINATOR) == 0);
1343bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK((flags & ALLOCATION_FOLDED) == 0);
1344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!FLAG_inline_new) {
1345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (emit_debug_code()) {
1346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Trash the registers to simulate an allocation failure.
1347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mov(result, Immediate(0x7091));
1348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mov(result_end, Immediate(0x7191));
1349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (scratch.is_valid()) {
1350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        mov(scratch, Immediate(0x7291));
1351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Register element_count is not modified by the function.
1353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    jmp(gc_required);
1355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
1356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result.is(result_end));
1358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load address of new object into result.
1360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LoadAllocationTopHelper(result, scratch, flags);
1361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_limit =
1363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationLimitReference(isolate(), flags);
1364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Align the next allocation. Storing the filler map without checking top is
1366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // safe in new-space because the limit of the heap is aligned there.
1367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
1368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
1369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label aligned;
1370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(result, Immediate(kDoubleAlignmentMask));
1371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(zero, &aligned, Label::kNear);
1372014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if ((flags & PRETENURE) != 0) {
1373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cmp(result, Operand::StaticVariable(allocation_limit));
1374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      j(above_equal, gc_required);
1375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(Operand(result, 0),
1377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Immediate(isolate()->factory()->one_pointer_filler_map()));
1378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    add(result, Immediate(kDoubleSize / 2));
1379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&aligned);
1380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Calculate new top and bail out if space is exhausted.
1383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We assume that element_count*element_size + header_size does not
1384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // overflow.
1385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (element_count_type == REGISTER_VALUE_IS_SMI) {
1386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(static_cast<ScaleFactor>(times_2 - 1) == times_1);
1387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(static_cast<ScaleFactor>(times_4 - 1) == times_2);
1388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(static_cast<ScaleFactor>(times_8 - 1) == times_4);
1389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(element_size >= times_2);
1390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kSmiTagSize == 1);
1391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    element_size = static_cast<ScaleFactor>(element_size - 1);
1392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(element_count_type == REGISTER_VALUE_IS_INT32);
1394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lea(result_end, Operand(element_count, element_size, header_size));
1396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  add(result_end, result);
1397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(carry, gc_required);
1398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(result_end, Operand::StaticVariable(allocation_limit));
1399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(above, gc_required);
1400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1401bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Tag result.
1402bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(kHeapObjectTag == 1);
1403bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  inc(result);
1404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Update allocation top.
1406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UpdateAllocationTopHelper(result_end, scratch, flags);
1407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Allocate(Register object_size,
1410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result,
1411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result_end,
1412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register scratch,
1413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Label* gc_required,
1414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              AllocationFlags flags) {
1415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0);
1416bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK((flags & ALLOCATION_FOLDED) == 0);
1417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!FLAG_inline_new) {
1418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (emit_debug_code()) {
1419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Trash the registers to simulate an allocation failure.
1420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mov(result, Immediate(0x7091));
1421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mov(result_end, Immediate(0x7191));
1422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (scratch.is_valid()) {
1423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        mov(scratch, Immediate(0x7291));
1424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // object_size is left unchanged by this function.
1426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    jmp(gc_required);
1428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
1429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result.is(result_end));
1431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load address of new object into result.
1433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LoadAllocationTopHelper(result, scratch, flags);
1434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_limit =
1436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationLimitReference(isolate(), flags);
1437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Align the next allocation. Storing the filler map without checking top is
1439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // safe in new-space because the limit of the heap is aligned there.
1440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
1441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
1442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label aligned;
1443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(result, Immediate(kDoubleAlignmentMask));
1444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(zero, &aligned, Label::kNear);
1445014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if ((flags & PRETENURE) != 0) {
1446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cmp(result, Operand::StaticVariable(allocation_limit));
1447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      j(above_equal, gc_required);
1448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(Operand(result, 0),
1450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Immediate(isolate()->factory()->one_pointer_filler_map()));
1451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    add(result, Immediate(kDoubleSize / 2));
1452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&aligned);
1453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Calculate new top and bail out if space is exhausted.
1456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!object_size.is(result_end)) {
1457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(result_end, object_size);
1458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  add(result_end, result);
1460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(result_end, Operand::StaticVariable(allocation_limit));
1461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(above, gc_required);
1462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1463bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Tag result.
1464bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(kHeapObjectTag == 1);
1465bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  inc(result);
1466bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1467bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
1468bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // The top pointer is not updated for allocation folding dominators.
1469bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    UpdateAllocationTopHelper(result_end, scratch, flags);
1470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1471bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1473bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::FastAllocate(int object_size, Register result,
1474bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                  Register result_end, AllocationFlags flags) {
1475bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!result.is(result_end));
1476bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Load address of new object into result.
1477bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  LoadAllocationTopHelper(result, no_reg, flags);
1478bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1479bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
1480bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
1481bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Label aligned;
1482bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    test(result, Immediate(kDoubleAlignmentMask));
1483bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    j(zero, &aligned, Label::kNear);
1484bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    mov(Operand(result, 0),
1485bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        Immediate(isolate()->factory()->one_pointer_filler_map()));
1486bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    add(result, Immediate(kDoubleSize / 2));
1487bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    bind(&aligned);
1488bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1489bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1490bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  lea(result_end, Operand(result, object_size));
1491bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  UpdateAllocationTopHelper(result_end, no_reg, flags);
1492bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1493bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(kHeapObjectTag == 1);
1494bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  inc(result);
1495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1497bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::FastAllocate(Register object_size, Register result,
1498bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                  Register result_end, AllocationFlags flags) {
1499bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!result.is(result_end));
1500bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Load address of new object into result.
1501bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  LoadAllocationTopHelper(result, no_reg, flags);
1502bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1503bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
1504bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
1505bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Label aligned;
1506bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    test(result, Immediate(kDoubleAlignmentMask));
1507bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    j(zero, &aligned, Label::kNear);
1508bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    mov(Operand(result, 0),
1509bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        Immediate(isolate()->factory()->one_pointer_filler_map()));
1510bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    add(result, Immediate(kDoubleSize / 2));
1511bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    bind(&aligned);
1512bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1513bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1514bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  lea(result_end, Operand(result, object_size, times_1, 0));
1515bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  UpdateAllocationTopHelper(result_end, no_reg, flags);
1516bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1517bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(kHeapObjectTag == 1);
1518bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  inc(result);
1519bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AllocateHeapNumber(Register result,
1522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        Register scratch1,
1523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        Register scratch2,
1524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        Label* gc_required,
1525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        MutableMode mode) {
1526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Allocate heap number in new space.
1527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(HeapNumber::kSize, result, scratch1, scratch2, gc_required,
1528bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
1529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Map> map = mode == MUTABLE
1531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ? isolate()->factory()->mutable_heap_number_map()
1532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : isolate()->factory()->heap_number_map();
1533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Set the map.
1535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(FieldOperand(result, HeapObject::kMapOffset), Immediate(map));
1536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1538014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::AllocateJSValue(Register result, Register constructor,
1539014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                     Register value, Register scratch,
1540014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                     Label* gc_required) {
1541014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!result.is(constructor));
1542014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!result.is(scratch));
1543014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!result.is(value));
1544014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1545014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Allocate JSValue in new space.
1546bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Allocate(JSValue::kSize, result, scratch, no_reg, gc_required,
1547bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
1548014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1549014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Initialize the JSValue.
1550014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LoadGlobalFunctionInitialMap(constructor, scratch);
1551014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(FieldOperand(result, HeapObject::kMapOffset), scratch);
1552014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LoadRoot(scratch, Heap::kEmptyFixedArrayRootIndex);
1553014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(FieldOperand(result, JSObject::kPropertiesOffset), scratch);
1554014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(FieldOperand(result, JSObject::kElementsOffset), scratch);
1555014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(FieldOperand(result, JSValue::kValueOffset), value);
1556014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
1557014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1558014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1559014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::InitializeFieldsWithFiller(Register current_address,
1560014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                Register end_address,
1561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                Register filler) {
1562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label loop, entry;
1563109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  jmp(&entry, Label::kNear);
1564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&loop);
1565014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(Operand(current_address, 0), filler);
1566014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  add(current_address, Immediate(kPointerSize));
1567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&entry);
1568014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  cmp(current_address, end_address);
1569109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  j(below, &loop, Label::kNear);
1570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::BooleanBitTest(Register object,
1574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    int field_offset,
1575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    int bit_index) {
1576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bit_index += kSmiTagSize + kSmiShiftSize;
1577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(base::bits::IsPowerOfTwo32(kBitsPerByte));
1578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int byte_index = bit_index / kBitsPerByte;
1579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int byte_bit_index = bit_index & (kBitsPerByte - 1);
1580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  test_b(FieldOperand(object, field_offset + byte_index),
15813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch         Immediate(1 << byte_bit_index));
1582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::NegativeZeroTest(Register result,
1587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      Register op,
1588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      Label* then_label) {
1589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label ok;
1590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  test(result, result);
1591109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  j(not_zero, &ok, Label::kNear);
1592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  test(op, op);
1593109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  j(sign, then_label, Label::kNear);
1594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&ok);
1595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::NegativeZeroTest(Register result,
1599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      Register op1,
1600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      Register op2,
1601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      Register scratch,
1602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      Label* then_label) {
1603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label ok;
1604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  test(result, result);
1605109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  j(not_zero, &ok, Label::kNear);
1606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(scratch, op1);
1607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  or_(scratch, op2);
1608109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  j(sign, then_label, Label::kNear);
1609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&ok);
1610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1613014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::GetMapConstructor(Register result, Register map,
1614014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                       Register temp) {
1615014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label done, loop;
1616014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(result, FieldOperand(map, Map::kConstructorOrBackPointerOffset));
1617014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&loop);
1618014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  JumpIfSmi(result, &done, Label::kNear);
1619014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CmpObjectType(result, MAP_TYPE, temp);
1620014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_equal, &done, Label::kNear);
1621014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(result, FieldOperand(result, Map::kConstructorOrBackPointerOffset));
1622014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  jmp(&loop);
1623014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&done);
1624014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CallStub(CodeStub* stub, TypeFeedbackId ast_id) {
1627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(AllowThisStubCall(stub));  // Calls are not allowed in some stubs.
1628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id);
1629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TailCallStub(CodeStub* stub) {
1633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  jmp(stub->GetCode(), RelocInfo::CODE_TARGET);
1634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::StubReturn(int argc) {
1638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(argc >= 1 && generating_stub());
1639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ret((argc - 1) * kPointerSize);
1640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
1644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return has_frame_ || !stub->SometimesSetsUpAFrame();
1645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CallRuntime(const Runtime::Function* f, int num_arguments,
1648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 SaveFPRegsMode save_doubles) {
1649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If the expected number of arguments of the runtime function is
1650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // constant, we check that the actual number of arguments match the
1651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // expectation.
1652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(f->nargs < 0 || f->nargs == num_arguments);
1653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(1236192): Most runtime routines don't need the number of
1655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // arguments passed in because it is constant. At some point we
1656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // should remove this need and make the runtime routine entry code
1657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // smarter.
1658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Move(eax, Immediate(num_arguments));
1659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(ebx, Immediate(ExternalReference(f, isolate())));
1660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CEntryStub ces(isolate(), 1, save_doubles);
1661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallStub(&ces);
1662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CallExternalReference(ExternalReference ref,
1666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           int num_arguments) {
1667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(eax, Immediate(num_arguments));
1668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(ebx, Immediate(ref));
1669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CEntryStub stub(isolate(), 1);
1671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallStub(&stub);
1672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1675014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::TailCallRuntime(Runtime::FunctionId fid) {
1676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // ----------- S t a t e -------------
1677014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  -- esp[0]                 : return address
1678014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  -- esp[8]                 : argument num_arguments - 1
1679014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  ...
1680014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  -- esp[8 * num_arguments] : argument 0 (receiver)
1681014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //
1682014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  For runtime functions with variable arguments:
1683014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  -- eax                    : number of  arguments
1684014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // -----------------------------------
1685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1686014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const Runtime::Function* function = Runtime::FunctionForId(fid);
1687014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(1, function->result_size);
1688014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (function->nargs >= 0) {
1689014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // TODO(1236192): Most runtime routines don't need the number of
1690014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // arguments passed in because it is constant. At some point we
1691014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // should remove this need and make the runtime routine entry code
1692014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // smarter.
1693014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mov(eax, Immediate(function->nargs));
1694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1695014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  JumpToExternalReference(ExternalReference(fid, isolate()));
1696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1698f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MacroAssembler::JumpToExternalReference(const ExternalReference& ext,
1699f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                             bool builtin_exit_frame) {
1700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Set the entry point and jump to the C entry runtime stub.
1701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(ebx, Immediate(ext));
1702f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  CEntryStub ces(isolate(), 1, kDontSaveFPRegs, kArgvOnStack,
1703f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                 builtin_exit_frame);
1704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  jmp(ces.GetCode(), RelocInfo::CODE_TARGET);
1705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::PrepareForTailCall(
17083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    const ParameterCount& callee_args_count, Register caller_args_count_reg,
17093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Register scratch0, Register scratch1, ReturnAddressState ra_state,
17103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    int number_of_temp_values_after_return_address) {
17113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#if DEBUG
17123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (callee_args_count.is_reg()) {
17133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(!AreAliased(callee_args_count.reg(), caller_args_count_reg, scratch0,
17143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                       scratch1));
17153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
17163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(!AreAliased(caller_args_count_reg, scratch0, scratch1));
17173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
17183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK(ra_state != ReturnAddressState::kNotOnStack ||
17193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch         number_of_temp_values_after_return_address == 0);
17203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#endif
17213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
17223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Calculate the destination address where we will put the return address
17233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // after we drop current frame.
17243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Register new_sp_reg = scratch0;
17253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (callee_args_count.is_reg()) {
17263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    sub(caller_args_count_reg, callee_args_count.reg());
17273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    lea(new_sp_reg,
17283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Operand(ebp, caller_args_count_reg, times_pointer_size,
17293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                StandardFrameConstants::kCallerPCOffset -
17303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                    number_of_temp_values_after_return_address * kPointerSize));
17313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
17323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    lea(new_sp_reg, Operand(ebp, caller_args_count_reg, times_pointer_size,
17333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                            StandardFrameConstants::kCallerPCOffset -
17343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                (callee_args_count.immediate() +
17353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                 number_of_temp_values_after_return_address) *
17363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                    kPointerSize));
17373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
17383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
17393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (FLAG_debug_code) {
17403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    cmp(esp, new_sp_reg);
17413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Check(below, kStackAccessBelowStackPointer);
17423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
17433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
17443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Copy return address from caller's frame to current frame's return address
17453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // to avoid its trashing and let the following loop copy it to the right
17463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // place.
17473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Register tmp_reg = scratch1;
17483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (ra_state == ReturnAddressState::kOnStack) {
17493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    mov(tmp_reg, Operand(ebp, StandardFrameConstants::kCallerPCOffset));
17503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    mov(Operand(esp, number_of_temp_values_after_return_address * kPointerSize),
17513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        tmp_reg);
17523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
17533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(ReturnAddressState::kNotOnStack == ra_state);
17543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK_EQ(0, number_of_temp_values_after_return_address);
17553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Push(Operand(ebp, StandardFrameConstants::kCallerPCOffset));
17563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
17573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
17583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Restore caller's frame pointer now as it could be overwritten by
17593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // the copying loop.
17603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(ebp, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
17613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
17623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // +2 here is to copy both receiver and return address.
17633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Register count_reg = caller_args_count_reg;
17643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (callee_args_count.is_reg()) {
17653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    lea(count_reg, Operand(callee_args_count.reg(),
17663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                           2 + number_of_temp_values_after_return_address));
17673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
17683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    mov(count_reg, Immediate(callee_args_count.immediate() + 2 +
17693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                             number_of_temp_values_after_return_address));
17703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // TODO(ishell): Unroll copying loop for small immediate values.
17713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
17723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
17733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Now copy callee arguments to the caller frame going backwards to avoid
17743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // callee arguments corruption (source and destination areas could overlap).
17753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label loop, entry;
17763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  jmp(&entry, Label::kNear);
17773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&loop);
17783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  dec(count_reg);
17793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(tmp_reg, Operand(esp, count_reg, times_pointer_size, 0));
17803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(Operand(new_sp_reg, count_reg, times_pointer_size, 0), tmp_reg);
17813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&entry);
17823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  cmp(count_reg, Immediate(0));
17833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  j(not_equal, &loop, Label::kNear);
17843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
17853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Leave current frame.
17863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(esp, new_sp_reg);
17873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
1788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::InvokePrologue(const ParameterCount& expected,
1790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const ParameterCount& actual,
1791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    Label* done,
1792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    bool* definitely_mismatches,
1793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    InvokeFlag flag,
1794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    Label::Distance done_near,
1795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const CallWrapper& call_wrapper) {
1796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool definitely_matches = false;
1797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  *definitely_mismatches = false;
1798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label invoke;
1799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (expected.is_immediate()) {
1800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(actual.is_immediate());
1801014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mov(eax, actual.immediate());
1802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (expected.immediate() == actual.immediate()) {
1803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      definitely_matches = true;
1804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel;
1806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (expected.immediate() == sentinel) {
1807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Don't worry about adapting arguments for builtins that
1808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // don't want that done. Skip adaption code by making it look
1809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // like we have a match between expected and actual number of
1810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // arguments.
1811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        definitely_matches = true;
1812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
1813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        *definitely_mismatches = true;
1814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        mov(ebx, expected.immediate());
1815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (actual.is_immediate()) {
1819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Expected is in register, actual is immediate. This is the
1820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // case when we invoke function values without going through the
1821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // IC mechanism.
1822014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      mov(eax, actual.immediate());
1823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cmp(expected.reg(), actual.immediate());
1824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      j(equal, &invoke);
1825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(expected.reg().is(ebx));
1826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (!expected.reg().is(actual.reg())) {
1827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Both expected and actual are in (different) registers. This
1828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // is the case when we invoke functions using call and apply.
1829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cmp(expected.reg(), actual.reg());
1830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      j(equal, &invoke);
1831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(actual.reg().is(eax));
1832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(expected.reg().is(ebx));
1833014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
1834014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Move(eax, actual.reg());
1835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!definitely_matches) {
1839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Code> adaptor =
1840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate()->builtins()->ArgumentsAdaptorTrampoline();
1841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (flag == CALL_FUNCTION) {
1842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      call_wrapper.BeforeCall(CallSize(adaptor, RelocInfo::CODE_TARGET));
1843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      call(adaptor, RelocInfo::CODE_TARGET);
1844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      call_wrapper.AfterCall();
1845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (!*definitely_mismatches) {
1846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        jmp(done, done_near);
1847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      jmp(adaptor, RelocInfo::CODE_TARGET);
1850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&invoke);
1852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
185562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid MacroAssembler::CheckDebugHook(Register fun, Register new_target,
185662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                    const ParameterCount& expected,
185762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                    const ParameterCount& actual) {
185862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Label skip_hook;
185962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ExternalReference debug_hook_active =
186062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      ExternalReference::debug_hook_on_function_call_address(isolate());
186162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  cmpb(Operand::StaticVariable(debug_hook_active), Immediate(0));
186262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  j(equal, &skip_hook);
1863014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  {
1864014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    FrameScope frame(this,
1865014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     has_frame() ? StackFrame::NONE : StackFrame::INTERNAL);
1866014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (expected.is_reg()) {
1867014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SmiTag(expected.reg());
1868014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Push(expected.reg());
1869014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1870014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (actual.is_reg()) {
1871014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SmiTag(actual.reg());
1872014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Push(actual.reg());
1873014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1874014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (new_target.is_valid()) {
1875014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Push(new_target);
1876014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1877014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(fun);
1878014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(fun);
187962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    CallRuntime(Runtime::kDebugOnFunctionCall);
1880014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Pop(fun);
1881014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (new_target.is_valid()) {
1882014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pop(new_target);
1883014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1884014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (actual.is_reg()) {
1885014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pop(actual.reg());
1886014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SmiUntag(actual.reg());
1887014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1888014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (expected.is_reg()) {
1889014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pop(expected.reg());
1890014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SmiUntag(expected.reg());
1891014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1892014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
189362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  bind(&skip_hook);
1894014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1895014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1896014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1897014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::InvokeFunctionCode(Register function, Register new_target,
1898014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        const ParameterCount& expected,
1899014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        const ParameterCount& actual,
1900014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        InvokeFlag flag,
1901014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        const CallWrapper& call_wrapper) {
1902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // You can't call a function without a valid frame.
1903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(flag == JUMP_FUNCTION || has_frame());
1904014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(function.is(edi));
1905014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_IMPLIES(new_target.is_valid(), new_target.is(edx));
1906014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
190762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (call_wrapper.NeedsDebugHookCheck()) {
190862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    CheckDebugHook(function, new_target, expected, actual);
1909014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1910014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1911014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Clear the new.target register if not given.
1912014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!new_target.is_valid()) {
1913014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mov(edx, isolate()->factory()->undefined_value());
1914014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
1917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool definitely_mismatches = false;
1918014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InvokePrologue(expected, actual, &done, &definitely_mismatches, flag,
1919014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 Label::kNear, call_wrapper);
1920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!definitely_mismatches) {
1921014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // We call indirectly through the code field in the function to
1922014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // allow recompilation to take effect without changing any of the
1923014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // call sites.
1924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Operand code = FieldOperand(function, JSFunction::kCodeEntryOffset);
1925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (flag == CALL_FUNCTION) {
1926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      call_wrapper.BeforeCall(CallSize(code));
1927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      call(code);
1928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      call_wrapper.AfterCall();
1929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(flag == JUMP_FUNCTION);
1931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      jmp(code);
1932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&done);
1934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1938014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::InvokeFunction(Register fun, Register new_target,
1939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const ParameterCount& actual,
1940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    InvokeFlag flag,
1941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const CallWrapper& call_wrapper) {
1942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // You can't call a function without a valid frame.
1943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(flag == JUMP_FUNCTION || has_frame());
1944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(fun.is(edi));
1946014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
1947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
1948014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kFormalParameterCountOffset));
1949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiUntag(ebx);
1950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ParameterCount expected(ebx);
1952014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InvokeFunctionCode(edi, new_target, expected, actual, flag, call_wrapper);
1953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::InvokeFunction(Register fun,
1957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const ParameterCount& expected,
1958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const ParameterCount& actual,
1959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    InvokeFlag flag,
1960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const CallWrapper& call_wrapper) {
1961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // You can't call a function without a valid frame.
1962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(flag == JUMP_FUNCTION || has_frame());
1963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(fun.is(edi));
1965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
1966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1967014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InvokeFunctionCode(edi, no_reg, expected, actual, flag, call_wrapper);
1968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::InvokeFunction(Handle<JSFunction> function,
1972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const ParameterCount& expected,
1973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const ParameterCount& actual,
1974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    InvokeFlag flag,
1975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const CallWrapper& call_wrapper) {
1976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LoadHeapObject(edi, function);
1977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InvokeFunction(edi, expected, actual, flag, call_wrapper);
1978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::LoadContext(Register dst, int context_chain_length) {
1982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (context_chain_length > 0) {
1983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Move up the chain of contexts to the context containing the slot.
1984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(dst, Operand(esi, Context::SlotOffset(Context::PREVIOUS_INDEX)));
1985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 1; i < context_chain_length; i++) {
1986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mov(dst, Operand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX)));
1987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Slot is in the current function context.  Move it into the
1990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // destination register in case we store into it (the write barrier
1991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // cannot be allowed to destroy the context in esi).
1992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(dst, esi);
1993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We should not have found a with context by walking the context chain
1996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (i.e., the static scope chain and runtime context chain do not agree).
1997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // A variable occurring in such a scope should have slot type LOOKUP and
1998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // not CONTEXT.
1999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
2000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(FieldOperand(dst, HeapObject::kMapOffset),
2001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate()->factory()->with_context_map());
2002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kVariableResolvedToWithContext);
2003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2007014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LoadGlobalProxy(Register dst) {
2008014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(dst, NativeContextOperand());
2009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(dst, ContextOperand(dst, Context::GLOBAL_PROXY_INDEX));
2010014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2011014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::LoadGlobalFunction(int index, Register function) {
2013014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Load the native context from the current context.
2014014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(function, NativeContextOperand());
2015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the function from the native context.
2016014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(function, ContextOperand(function, index));
2017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
2021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                  Register map) {
2022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the initial map.  The global functions all have initial maps.
2023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
2024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
2025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label ok, fail;
2026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CheckMap(map, isolate()->factory()->meta_map(), &fail, DO_SMI_CHECK);
2027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    jmp(&ok);
2028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&fail);
2029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Abort(kGlobalFunctionsMustHaveInitialMap);
2030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&ok);
2031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Store the value in register src in the safepoint register stack
2036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// slot for register dst.
2037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Register src) {
2038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(SafepointRegisterSlot(dst), src);
2039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Immediate src) {
2043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(SafepointRegisterSlot(dst), src);
2044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) {
2048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(dst, SafepointRegisterSlot(src));
2049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochOperand MacroAssembler::SafepointRegisterSlot(Register reg) {
2053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return Operand(esp, SafepointRegisterStackIndex(reg.code()) * kPointerSize);
2054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint MacroAssembler::SafepointRegisterStackIndex(int reg_code) {
2058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The registers are pushed starting with the lowest encoding,
2059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // which means that lowest encodings are furthest away from
2060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the stack pointer.
2061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(reg_code >= 0 && reg_code < kNumSafepointRegisters);
2062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return kNumSafepointRegisters - reg_code - 1;
2063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::LoadHeapObject(Register result,
2067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    Handle<HeapObject> object) {
2068f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  mov(result, object);
2069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CmpHeapObject(Register reg, Handle<HeapObject> object) {
2073f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  cmp(reg, object);
2074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2076f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MacroAssembler::PushHeapObject(Handle<HeapObject> object) { Push(object); }
2077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2078958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::CmpWeakValue(Register value, Handle<WeakCell> cell,
2079958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                  Register scratch) {
2080958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  mov(scratch, cell);
2081958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  cmp(value, FieldOperand(scratch, WeakCell::kValueOffset));
2082958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2083958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2084958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2085014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::GetWeakValue(Register value, Handle<WeakCell> cell) {
2086958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  mov(value, cell);
2087958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  mov(value, FieldOperand(value, WeakCell::kValueOffset));
2088014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2089014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2090014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2091014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LoadWeakValue(Register value, Handle<WeakCell> cell,
2092014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                   Label* miss) {
2093014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GetWeakValue(value, cell);
2094958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  JumpIfSmi(value, miss);
2095958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2096958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2097958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Ret() {
2099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ret(0);
2100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Ret(int bytes_dropped, Register scratch) {
2104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (is_uint16(bytes_dropped)) {
2105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ret(bytes_dropped);
2106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    pop(scratch);
2108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    add(esp, Immediate(bytes_dropped));
2109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    push(scratch);
2110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ret(0);
2111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::VerifyX87StackDepth(uint32_t depth) {
2116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Turn off the stack depth check when serializer is enabled to reduce the
2117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // code size.
2118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (serializer_enabled()) return;
2119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Make sure the floating point stack is either empty or has depth items.
2120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(depth <= 7);
2121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // This is very expensive.
2122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(FLAG_debug_code && FLAG_enable_slow_asserts);
2123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The top-of-stack (tos) is 7 if there is one item pushed.
2125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int tos = (8 - depth) % 8;
2126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kTopMask = 0x3800;
2127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  push(eax);
2128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fwait();
2129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fnstsw_ax();
2130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  and_(eax, kTopMask);
2131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shr(eax, 11);
2132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(eax, Immediate(tos));
2133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(equal, kUnexpectedFPUStackDepthAfterInstruction);
2134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fnclex();
2135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pop(eax);
2136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Drop(int stack_elements) {
2140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (stack_elements > 0) {
2141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    add(esp, Immediate(stack_elements * kPointerSize));
2142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Move(Register dst, Register src) {
2147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!dst.is(src)) {
2148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(dst, src);
2149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Move(Register dst, const Immediate& x) {
215413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (x.is_zero() && RelocInfo::IsNone(x.rmode_)) {
2155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    xor_(dst, dst);  // Shorter than mov of 32-bit immediate 0.
2156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(dst, x);
2158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Move(const Operand& dst, const Immediate& x) {
2163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(dst, x);
2164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Lzcnt(Register dst, const Operand& src) {
2168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // TODO(intel): Add support for LZCNT (with ABM/BMI1).
2169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label not_zero_src;
2170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bsr(dst, src);
2171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_zero, &not_zero_src, Label::kNear);
2172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Move(dst, Immediate(63));  // 63^31 == 32
2173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&not_zero_src);
2174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  xor_(dst, Immediate(31));  // for x in [0..31], 31^x == 31-x.
2175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Tzcnt(Register dst, const Operand& src) {
2179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // TODO(intel): Add support for TZCNT (with ABM/BMI1).
2180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label not_zero_src;
2181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bsf(dst, src);
2182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_zero, &not_zero_src, Label::kNear);
2183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Move(dst, Immediate(32));  // The result of tzcnt is 32 if src = 0.
2184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&not_zero_src);
2185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Popcnt(Register dst, const Operand& src) {
2189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // TODO(intel): Add support for POPCNT (with POPCNT)
2190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // if (CpuFeatures::IsSupported(POPCNT)) {
2191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //   CpuFeatureScope scope(this, POPCNT);
2192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //   popcnt(dst, src);
2193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //   return;
2194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // }
2195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  UNREACHABLE();
2196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::SetCounter(StatsCounter* counter, int value) {
2200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_native_code_counters && counter->Enabled()) {
2201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(Operand::StaticVariable(ExternalReference(counter)), Immediate(value));
2202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::IncrementCounter(StatsCounter* counter, int value) {
2207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(value > 0);
2208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_native_code_counters && counter->Enabled()) {
2209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Operand operand = Operand::StaticVariable(ExternalReference(counter));
2210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (value == 1) {
2211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      inc(operand);
2212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
2213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      add(operand, Immediate(value));
2214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::DecrementCounter(StatsCounter* counter, int value) {
2220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(value > 0);
2221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_native_code_counters && counter->Enabled()) {
2222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Operand operand = Operand::StaticVariable(ExternalReference(counter));
2223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (value == 1) {
2224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      dec(operand);
2225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
2226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      sub(operand, Immediate(value));
2227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::IncrementCounter(Condition cc,
2233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      StatsCounter* counter,
2234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      int value) {
2235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(value > 0);
2236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_native_code_counters && counter->Enabled()) {
2237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label skip;
2238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(NegateCondition(cc), &skip);
2239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    pushfd();
2240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    IncrementCounter(counter, value);
2241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    popfd();
2242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&skip);
2243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::DecrementCounter(Condition cc,
2248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      StatsCounter* counter,
2249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      int value) {
2250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(value > 0);
2251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_native_code_counters && counter->Enabled()) {
2252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label skip;
2253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(NegateCondition(cc), &skip);
2254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    pushfd();
2255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DecrementCounter(counter, value);
2256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    popfd();
2257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&skip);
2258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Assert(Condition cc, BailoutReason reason) {
2263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) Check(cc, reason);
2264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertFastElements(Register elements) {
2268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
2269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Factory* factory = isolate()->factory();
2270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label ok;
2271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(FieldOperand(elements, HeapObject::kMapOffset),
2272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Immediate(factory->fixed_array_map()));
2273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(equal, &ok);
2274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(FieldOperand(elements, HeapObject::kMapOffset),
2275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Immediate(factory->fixed_double_array_map()));
2276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(equal, &ok);
2277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(FieldOperand(elements, HeapObject::kMapOffset),
2278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Immediate(factory->fixed_cow_array_map()));
2279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(equal, &ok);
2280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Abort(kJSObjectWithFastElementsMapHasSlowElements);
2281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&ok);
2282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Check(Condition cc, BailoutReason reason) {
2287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label L;
2288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(cc, &L);
2289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Abort(reason);
2290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // will not return here
2291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&L);
2292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CheckStackAlignment() {
2296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int frame_alignment = base::OS::ActivationFrameAlignment();
2297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int frame_alignment_mask = frame_alignment - 1;
2298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (frame_alignment > kPointerSize) {
2299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
2300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label alignment_as_expected;
2301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(esp, Immediate(frame_alignment_mask));
2302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(zero, &alignment_as_expected);
2303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Abort if stack is not aligned.
2304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int3();
2305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&alignment_as_expected);
2306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Abort(BailoutReason reason) {
2311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
2312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* msg = GetBailoutReason(reason);
2313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (msg != NULL) {
2314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RecordComment("Abort message: ");
2315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RecordComment(msg);
2316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_trap_on_abort) {
2319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int3();
2320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
2321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
2323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2324f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Check if Abort() has already been initialized.
2325f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(isolate()->builtins()->Abort()->IsHeapObject());
2326f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2327f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Move(edx, Smi::FromInt(static_cast<int>(reason)));
2328f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Disable stub call restrictions to always allow calls to abort.
2330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!has_frame_) {
2331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // We don't actually want to generate a pile of code for this, so just
2332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // claim there is a stack frame, without generating one.
2333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FrameScope scope(this, StackFrame::NONE);
2334f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Call(isolate()->builtins()->Abort(), RelocInfo::CODE_TARGET);
2335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2336f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Call(isolate()->builtins()->Abort(), RelocInfo::CODE_TARGET);
2337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // will not return here
2339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int3();
2340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::LoadInstanceDescriptors(Register map,
2344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                             Register descriptors) {
2345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(descriptors, FieldOperand(map, Map::kDescriptorsOffset));
2346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) {
2350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(dst, FieldOperand(map, Map::kBitField3Offset));
2351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DecodeField<Map::NumberOfOwnDescriptorsBits>(dst);
2352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2355014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LoadAccessor(Register dst, Register holder,
2356014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  int accessor_index,
2357014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  AccessorComponent accessor) {
2358014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(dst, FieldOperand(holder, HeapObject::kMapOffset));
2359014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LoadInstanceDescriptors(dst, dst);
2360014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(dst, FieldOperand(dst, DescriptorArray::GetValueOffset(accessor_index)));
2361014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int offset = accessor == ACCESSOR_GETTER ? AccessorPair::kGetterOffset
2362014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                           : AccessorPair::kSetterOffset;
2363014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(dst, FieldOperand(dst, offset));
2364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfNotBothSequentialOneByteStrings(Register object1,
2367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                           Register object2,
2368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                           Register scratch1,
2369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                           Register scratch2,
2370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                           Label* failure) {
2371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that both objects are not smis.
2372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
2373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(scratch1, object1);
2374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  and_(scratch1, object2);
2375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JumpIfSmi(scratch1, failure);
2376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load instance type for both strings.
2378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(scratch1, FieldOperand(object1, HeapObject::kMapOffset));
2379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(scratch2, FieldOperand(object2, HeapObject::kMapOffset));
2380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movzx_b(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset));
2381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movzx_b(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset));
2382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that both are flat one-byte strings.
2384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kFlatOneByteStringMask =
2385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
2386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kFlatOneByteStringTag =
2387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kStringTag | kOneByteStringTag | kSeqStringTag;
2388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Interleave bits from both instance types and compare them in one check.
238962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  const int kShift = 8;
239062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(0, kFlatOneByteStringMask & (kFlatOneByteStringMask << kShift));
2391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  and_(scratch1, kFlatOneByteStringMask);
2392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  and_(scratch2, kFlatOneByteStringMask);
239362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  shl(scratch2, kShift);
239462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  or_(scratch1, scratch2);
239562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  cmp(scratch1, kFlatOneByteStringTag | (kFlatOneByteStringTag << kShift));
2396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(not_equal, failure);
2397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfNotUniqueNameInstanceType(Operand operand,
2401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                     Label* not_unique_name,
2402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                     Label::Distance distance) {
2403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
2404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label succeed;
2405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  test(operand, Immediate(kIsNotStringMask | kIsNotInternalizedMask));
2406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(zero, &succeed);
24073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  cmpb(operand, Immediate(SYMBOL_TYPE));
2408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(not_equal, not_unique_name, distance);
2409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&succeed);
2411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::EmitSeqStringSetCharCheck(Register string,
2415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register index,
2416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register value,
2417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               uint32_t encoding_mask) {
2418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label is_object;
2419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JumpIfNotSmi(string, &is_object, Label::kNear);
2420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Abort(kNonObject);
2421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&is_object);
2422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  push(value);
2424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(value, FieldOperand(string, HeapObject::kMapOffset));
2425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movzx_b(value, FieldOperand(value, Map::kInstanceTypeOffset));
2426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  and_(value, Immediate(kStringRepresentationMask | kStringEncodingMask));
2428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(value, Immediate(encoding_mask));
2429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pop(value);
2430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(equal, kUnexpectedStringType);
2431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The index is assumed to be untagged coming in, tag it to compare with the
2433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // string length without using a temp register, it is restored at the end of
2434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // this function.
2435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiTag(index);
2436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(no_overflow, kIndexIsTooLarge);
2437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(index, FieldOperand(string, String::kLengthOffset));
2439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(less, kIndexIsTooLarge);
2440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2441c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  cmp(index, Immediate(Smi::kZero));
2442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(greater_equal, kIndexIsNegative);
2443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Restore the index
2445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiUntag(index);
2446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::PrepareCallCFunction(int num_arguments, Register scratch) {
2450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int frame_alignment = base::OS::ActivationFrameAlignment();
2451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (frame_alignment != 0) {
2452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Make stack end at alignment and make room for num_arguments words
2453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // and the original value of esp.
2454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(scratch, esp);
2455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sub(esp, Immediate((num_arguments + 1) * kPointerSize));
2456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
2457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    and_(esp, -frame_alignment);
2458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(Operand(esp, num_arguments * kPointerSize), scratch);
2459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sub(esp, Immediate(num_arguments * kPointerSize));
2461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CallCFunction(ExternalReference function,
2466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   int num_arguments) {
2467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Trashing eax is ok as it will be the return value.
2468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(eax, Immediate(function));
2469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallCFunction(eax, num_arguments);
2470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CallCFunction(Register function,
2474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   int num_arguments) {
2475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(has_frame());
2476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check stack alignment.
2477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
2478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CheckStackAlignment();
2479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  call(function);
2482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (base::OS::ActivationFrameAlignment() != 0) {
2483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(esp, Operand(esp, num_arguments * kPointerSize));
2484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    add(esp, Immediate(num_arguments * kPointerSize));
2486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
2491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool AreAliased(Register reg1,
2492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg2,
2493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg3,
2494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg4,
2495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg5,
2496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg6,
2497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg7,
2498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg8) {
2499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int n_of_valid_regs = reg1.is_valid() + reg2.is_valid() +
2500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reg3.is_valid() + reg4.is_valid() + reg5.is_valid() + reg6.is_valid() +
2501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reg7.is_valid() + reg8.is_valid();
2502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RegList regs = 0;
2504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg1.is_valid()) regs |= reg1.bit();
2505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg2.is_valid()) regs |= reg2.bit();
2506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg3.is_valid()) regs |= reg3.bit();
2507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg4.is_valid()) regs |= reg4.bit();
2508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg5.is_valid()) regs |= reg5.bit();
2509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg6.is_valid()) regs |= reg6.bit();
2510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg7.is_valid()) regs |= reg7.bit();
2511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg8.is_valid()) regs |= reg8.bit();
2512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int n_of_non_aliasing_regs = NumRegs(regs);
2513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return n_of_valid_regs != n_of_non_aliasing_regs;
2515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
2517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2519014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochCodePatcher::CodePatcher(Isolate* isolate, byte* address, int size)
2520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    : address_(address),
2521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      size_(size),
2522014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      masm_(isolate, address, size + Assembler::kGap, CodeObjectRequired::kNo) {
2523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Create a new macro assembler pointing to the address of the code to patch.
2524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The size is adjusted with kGap on order for the assembler to generate size
2525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // bytes of instructions without failing with buffer size constraints.
2526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
2527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochCodePatcher::~CodePatcher() {
2531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Indicate that code has changed.
2532014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Assembler::FlushICache(masm_.isolate(), address_, size_);
2533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that the code was patched as expected.
2535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(masm_.pc_ == address_ + size_);
2536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
2537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CheckPageFlag(
2541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register object,
2542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch,
2543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int mask,
2544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Condition cc,
2545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label* condition_met,
2546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label::Distance condition_met_distance) {
2547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(cc == zero || cc == not_zero);
2548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (scratch.is(object)) {
2549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    and_(scratch, Immediate(~Page::kPageAlignmentMask));
2550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(scratch, Immediate(~Page::kPageAlignmentMask));
2552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    and_(scratch, object);
2553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (mask < (1 << kBitsPerByte)) {
25553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    test_b(Operand(scratch, MemoryChunk::kFlagsOffset), Immediate(mask));
2556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(Operand(scratch, MemoryChunk::kFlagsOffset), Immediate(mask));
2558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(cc, condition_met, condition_met_distance);
2560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CheckPageFlagForMap(
2564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Map> map,
2565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int mask,
2566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Condition cc,
2567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label* condition_met,
2568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label::Distance condition_met_distance) {
2569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(cc == zero || cc == not_zero);
2570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Page* page = Page::FromAddress(map->address());
2571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!serializer_enabled());  // Serializer cannot match page_flags.
2572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference reference(ExternalReference::page_flags(page));
2573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The inlined static address check of the page's flags relies
2574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // on maps never being compacted.
2575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!isolate()->heap()->mark_compact_collector()->
2576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         IsOnEvacuationCandidate(*map));
2577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (mask < (1 << kBitsPerByte)) {
25783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    test_b(Operand::StaticVariable(reference), Immediate(mask));
2579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(Operand::StaticVariable(reference), Immediate(mask));
2581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(cc, condition_met, condition_met_distance);
2583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfBlack(Register object,
2587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Register scratch0,
2588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Register scratch1,
2589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Label* on_black,
2590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Label::Distance on_black_near) {
2591014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  HasColor(object, scratch0, scratch1, on_black, on_black_near, 1,
2592014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch           1);  // kBlackBitPattern.
2593014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0);
2594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::HasColor(Register object,
2598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register bitmap_scratch,
2599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register mask_scratch,
2600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Label* has_color,
2601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Label::Distance has_color_distance,
2602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              int first_bit,
2603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              int second_bit) {
2604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(object, bitmap_scratch, mask_scratch, ecx));
2605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GetMarkBits(object, bitmap_scratch, mask_scratch);
2607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label other_color, word_boundary;
2609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
2610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(first_bit == 1 ? zero : not_zero, &other_color, Label::kNear);
2611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  add(mask_scratch, mask_scratch);  // Shift left 1 by adding.
2612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(zero, &word_boundary, Label::kNear);
2613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
2614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(second_bit == 1 ? not_zero : zero, has_color, has_color_distance);
2615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  jmp(&other_color, Label::kNear);
2616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&word_boundary);
26183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test_b(Operand(bitmap_scratch, MemoryChunk::kHeaderSize + kPointerSize),
26193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch         Immediate(1));
2620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(second_bit == 1 ? not_zero : zero, has_color, has_color_distance);
2622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&other_color);
2623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::GetMarkBits(Register addr_reg,
2627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Register bitmap_reg,
2628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Register mask_reg) {
2629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(addr_reg, mask_reg, bitmap_reg, ecx));
2630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(bitmap_reg, Immediate(~Page::kPageAlignmentMask));
2631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  and_(bitmap_reg, addr_reg);
2632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(ecx, addr_reg);
2633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int shift =
2634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Bitmap::kBitsPerCellLog2 + kPointerSizeLog2 - Bitmap::kBytesPerCellLog2;
2635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shr(ecx, shift);
2636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  and_(ecx,
2637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       (Page::kPageAlignmentMask >> shift) & ~(Bitmap::kBytesPerCell - 1));
2638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  add(bitmap_reg, ecx);
2640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(ecx, addr_reg);
2641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shr(ecx, kPointerSizeLog2);
2642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  and_(ecx, (1 << Bitmap::kBitsPerCellLog2) - 1);
2643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(mask_reg, Immediate(1));
2644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shl_cl(mask_reg);
2645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2648014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::JumpIfWhite(Register value, Register bitmap_scratch,
2649014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 Register mask_scratch, Label* value_is_white,
2650014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 Label::Distance distance) {
2651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(value, bitmap_scratch, mask_scratch, ecx));
2652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GetMarkBits(value, bitmap_scratch, mask_scratch);
2653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If the value is black or grey we don't need to do anything.
2655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0);
2656014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0);
2657014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(strcmp(Marking::kGreyBitPattern, "10") == 0);
2658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0);
2659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Since both black and grey have a 1 in the first position and white does
2661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // not have a 1 there we only need to check one bit.
2662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
2663014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(zero, value_is_white, Label::kNear);
2664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::EnumLength(Register dst, Register map) {
2668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(Map::EnumLengthBits::kShift == 0);
2669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(dst, FieldOperand(map, Map::kBitField3Offset));
2670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  and_(dst, Immediate(Map::EnumLengthBits::kMask));
2671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiTag(dst);
2672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CheckEnumCache(Label* call_runtime) {
2676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label next, start;
2677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(ecx, eax);
2678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check if the enum length field is properly initialized, indicating that
2680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // there is an enum cache.
2681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset));
2682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EnumLength(edx, ebx);
2684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(edx, Immediate(Smi::FromInt(kInvalidEnumCacheSentinel)));
2685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(equal, call_runtime);
2686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  jmp(&start);
2688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&next);
2690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset));
2691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // For all objects but the receiver, check that the cache is empty.
2693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EnumLength(edx, ebx);
2694c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  cmp(edx, Immediate(Smi::kZero));
2695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(not_equal, call_runtime);
2696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&start);
2698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that there are no elements. Register rcx contains the current JS
2700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // object we've reached through the prototype chain.
2701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label no_elements;
2702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset));
2703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(ecx, isolate()->factory()->empty_fixed_array());
2704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(equal, &no_elements);
2705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Second chance, the object may be using the empty slow element dictionary.
2707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(ecx, isolate()->factory()->empty_slow_element_dictionary());
2708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(not_equal, call_runtime);
2709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&no_elements);
2711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset));
2712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(ecx, isolate()->factory()->null_value());
2713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(not_equal, &next);
2714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TestJSArrayForAllocationMemento(
2718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register receiver_reg,
2719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch_reg,
2720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label* no_memento_found) {
27213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label map_check;
27223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label top_check;
2723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference new_space_allocation_top =
2724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::new_space_allocation_top_address(isolate());
27253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  const int kMementoMapOffset = JSArray::kSize - kHeapObjectTag;
2726c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  const int kMementoLastWordOffset =
2727c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      kMementoMapOffset + AllocationMemento::kSize - kPointerSize;
27283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
27293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Bail out if the object is not in new space.
27303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  JumpIfNotInNewSpace(receiver_reg, scratch_reg, no_memento_found);
27313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // If the object is in new space, we need to check whether it is on the same
27323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // page as the current top.
2733c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  lea(scratch_reg, Operand(receiver_reg, kMementoLastWordOffset));
27343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  xor_(scratch_reg, Operand::StaticVariable(new_space_allocation_top));
27353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test(scratch_reg, Immediate(~Page::kPageAlignmentMask));
27363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  j(zero, &top_check);
27373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // The object is on a different page than allocation top. Bail out if the
27383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // object sits on the page boundary as no memento can follow and we cannot
27393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // touch the memory following it.
2740c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  lea(scratch_reg, Operand(receiver_reg, kMementoLastWordOffset));
27413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  xor_(scratch_reg, receiver_reg);
27423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test(scratch_reg, Immediate(~Page::kPageAlignmentMask));
27433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  j(not_zero, no_memento_found);
27443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Continue with the actual map check.
27453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  jmp(&map_check);
27463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // If top is on the same page as the current object, we need to check whether
27473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // we are below top.
27483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&top_check);
2749c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  lea(scratch_reg, Operand(receiver_reg, kMementoLastWordOffset));
2750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(scratch_reg, Operand::StaticVariable(new_space_allocation_top));
2751c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  j(greater_equal, no_memento_found);
27523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Memento map check.
27533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&map_check);
27543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(scratch_reg, Operand(receiver_reg, kMementoMapOffset));
27553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  cmp(scratch_reg, Immediate(isolate()->factory()->allocation_memento_map()));
2756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TruncatingDiv(Register dividend, int32_t divisor) {
2759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dividend.is(eax));
2760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dividend.is(edx));
2761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::MagicNumbersForDivision<uint32_t> mag =
2762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      base::SignedDivisionByConstant(static_cast<uint32_t>(divisor));
2763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(eax, Immediate(mag.multiplier));
2764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  imul(dividend);
2765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool neg = (mag.multiplier & (static_cast<uint32_t>(1) << 31)) != 0;
2766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor > 0 && neg) add(edx, dividend);
2767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor < 0 && !neg && mag.multiplier > 0) sub(edx, dividend);
2768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (mag.shift > 0) sar(edx, mag.shift);
2769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(eax, dividend);
2770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shr(eax, 31);
2771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  add(edx, eax);
2772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2775014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
2776014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
2777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // V8_TARGET_ARCH_X87
2779