13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_IA32
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/bits.h"
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/division-by-constant.h"
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/bootstrapper.h"
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h"
11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/debug/debug.h"
12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/ia32/frames-ia32.h"
13014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/ia32/macro-assembler-ia32.h"
14958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/runtime/runtime.h"
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -------------------------------------------------------------------------
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// MacroAssembler implementation.
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochMacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size,
23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                               CodeObjectRequired create_code_object)
248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    : Assembler(arg_isolate, buffer, size),
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      generating_stub_(false),
263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      has_frame_(false) {
27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (create_code_object == CodeObjectRequired::kYes) {
28014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    code_object_ =
29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Handle<Object>::New(isolate()->heap()->undefined_value(), isolate());
308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Load(Register dst, const Operand& src, Representation r) {
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!r.IsDouble());
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (r.IsInteger8()) {
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movsx_b(dst, src);
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsUInteger8()) {
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movzx_b(dst, src);
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsInteger16()) {
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movsx_w(dst, src);
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsUInteger16()) {
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movzx_w(dst, src);
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(dst, src);
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Store(Register src, const Operand& dst, Representation r) {
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!r.IsDouble());
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (r.IsInteger8() || r.IsUInteger8()) {
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov_b(dst, src);
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsInteger16() || r.IsUInteger16()) {
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov_w(dst, src);
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (r.IsHeapObject()) {
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AssertNotSmi(src);
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (r.IsSmi()) {
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AssertSmi(src);
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(dst, src);
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index) {
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (isolate()->heap()->RootCanBeTreatedAsConstant(index)) {
69014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mov(destination, isolate()->heap()->root_handle(index));
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference roots_array_start =
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::roots_array_start(isolate());
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(destination, Immediate(index));
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(destination, Operand::StaticArray(destination,
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        times_pointer_size,
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        roots_array_start));
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::StoreRoot(Register source,
82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Register scratch,
83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Heap::RootListIndex index) {
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(Heap::RootCanBeWrittenAfterInitialization(index));
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference roots_array_start =
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::roots_array_start(isolate());
87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(scratch, Immediate(index));
88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(Operand::StaticArray(scratch, times_pointer_size, roots_array_start),
89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      source);
90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CompareRoot(Register with,
94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Register scratch,
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Heap::RootListIndex index) {
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference roots_array_start =
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::roots_array_start(isolate());
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(scratch, Immediate(index));
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(with, Operand::StaticArray(scratch,
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                times_pointer_size,
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                roots_array_start));
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) {
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(isolate()->heap()->RootCanBeTreatedAsConstant(index));
107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  cmp(with, isolate()->heap()->root_handle(index));
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CompareRoot(const Operand& with,
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Heap::RootListIndex index) {
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(isolate()->heap()->RootCanBeTreatedAsConstant(index));
114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  cmp(with, isolate()->heap()->root_handle(index));
115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::PushRoot(Heap::RootListIndex index) {
119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(isolate()->heap()->RootCanBeTreatedAsConstant(index));
120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Push(isolate()->heap()->root_handle(index));
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
123109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#define REG(Name) \
124109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  { Register::kCode_##Name }
125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
126109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochstatic const Register saved_regs[] = {REG(eax), REG(ecx), REG(edx)};
127109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
128109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#undef REG
129109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
130109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochstatic const int kNumberOfSavedRegs = sizeof(saved_regs) / sizeof(Register);
131109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
132109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::PushCallerSaved(SaveFPRegsMode fp_mode,
133109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                     Register exclusion1, Register exclusion2,
134109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                     Register exclusion3) {
135109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // We don't allow a GC during a store buffer overflow so there is no need to
136109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // store the registers in any particular way, but we do have to store and
137109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // restore them.
138109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  for (int i = 0; i < kNumberOfSavedRegs; i++) {
139109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Register reg = saved_regs[i];
140109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    if (!reg.is(exclusion1) && !reg.is(exclusion2) && !reg.is(exclusion3)) {
141109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      push(reg);
142109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
143109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
144109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (fp_mode == kSaveFPRegs) {
145109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    sub(esp, Immediate(kDoubleSize * (XMMRegister::kMaxNumRegisters - 1)));
146109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // Save all XMM registers except XMM0.
147109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    for (int i = XMMRegister::kMaxNumRegisters - 1; i > 0; i--) {
148109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      XMMRegister reg = XMMRegister::from_code(i);
149109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      movsd(Operand(esp, (i - 1) * kDoubleSize), reg);
150109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
151109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
152109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
153109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
154109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
155109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                    Register exclusion2, Register exclusion3) {
156109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (fp_mode == kSaveFPRegs) {
157109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // Restore all XMM registers except XMM0.
158109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    for (int i = XMMRegister::kMaxNumRegisters - 1; i > 0; i--) {
159109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      XMMRegister reg = XMMRegister::from_code(i);
160109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      movsd(reg, Operand(esp, (i - 1) * kDoubleSize));
161109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
162109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    add(esp, Immediate(kDoubleSize * (XMMRegister::kMaxNumRegisters - 1)));
163109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
164109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
165109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  for (int i = kNumberOfSavedRegs - 1; i >= 0; i--) {
166109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Register reg = saved_regs[i];
167109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    if (!reg.is(exclusion1) && !reg.is(exclusion2) && !reg.is(exclusion3)) {
168109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      pop(reg);
169109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
1706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
171109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
172109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
173109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::InNewSpace(Register object, Register scratch, Condition cc,
174109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                Label* condition_met,
175109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                Label::Distance distance) {
176f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  CheckPageFlag(object, scratch, MemoryChunk::kIsInNewSpaceMask, cc,
177f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                condition_met, distance);
1783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::RememberedSetHelper(
1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register object,  // Only used for debug checks.
1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register addr,
1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch,
1853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SaveFPRegsMode save_fp,
1863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MacroAssembler::RememberedSetFinalAction and_then) {
1873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
1893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label ok;
1903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JumpIfNotInNewSpace(object, scratch, &ok, Label::kNear);
1913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int3();
1923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&ok);
1933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load store buffer top.
1953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExternalReference store_buffer =
1963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ExternalReference::store_buffer_top(isolate());
1973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(scratch, Operand::StaticVariable(store_buffer));
1983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Store pointer to buffer.
1993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(Operand(scratch, 0), addr);
2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Increment buffer top.
2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(scratch, Immediate(kPointerSize));
2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Write back new top of buffer.
2033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(Operand::StaticVariable(store_buffer), scratch);
2043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Call stub on end of buffer.
2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for end of buffer.
2063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test(scratch, Immediate(StoreBuffer::kStoreBufferMask));
2073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (and_then == kReturnAtEnd) {
2083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label buffer_overflowed;
2093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    j(equal, &buffer_overflowed, Label::kNear);
2103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ret(0);
2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&buffer_overflowed);
2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(and_then == kFallThroughAtEnd);
2143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    j(not_equal, &done, Label::kNear);
2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StoreBufferOverflowStub store_buffer_overflow(isolate(), save_fp);
2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallStub(&store_buffer_overflow);
2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (and_then == kReturnAtEnd) {
2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ret(0);
2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(and_then == kFallThroughAtEnd);
2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&done);
2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::ClampDoubleToUint8(XMMRegister input_reg,
228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                        XMMRegister scratch_reg,
229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                        Register result_reg) {
230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label conv_failure;
232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  xorps(scratch_reg, scratch_reg);
233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cvtsd2si(result_reg, input_reg);
234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  test(result_reg, Immediate(0xFFFFFF00));
235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(zero, &done, Label::kNear);
236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(result_reg, Immediate(0x1));
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(overflow, &conv_failure, Label::kNear);
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(result_reg, Immediate(0));
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  setcc(sign, result_reg);
240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  sub(result_reg, Immediate(1));
241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  and_(result_reg, Immediate(255));
242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  jmp(&done, Label::kNear);
243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&conv_failure);
244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Move(result_reg, Immediate(0));
245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ucomisd(input_reg, scratch_reg);
246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(below, &done, Label::kNear);
247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Move(result_reg, Immediate(255));
248257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&done);
249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::ClampUint8(Register reg) {
253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  test(reg, Immediate(0xFFFFFF00));
255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(zero, &done, Label::kNear);
256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  setcc(negative, reg);  // 1 if negative, 0 if positive.
257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  dec_b(reg);  // 0 if negative, 255 if positive.
258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&done);
259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::SlowTruncateToI(Register result_reg,
263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     Register input_reg,
264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     int offset) {
265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleToIStub stub(isolate(), input_reg, result_reg, offset, true);
266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  call(stub.GetCode(), RelocInfo::CODE_TARGET);
267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TruncateDoubleToI(Register result_reg,
271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       XMMRegister input_reg) {
272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cvttsd2si(result_reg, Operand(input_reg));
274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(result_reg, 0x1);
275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(no_overflow, &done, Label::kNear);
276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  sub(esp, Immediate(kDoubleSize));
278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movsd(MemOperand(esp, 0), input_reg);
279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SlowTruncateToI(result_reg, esp, 0);
280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  add(esp, Immediate(kDoubleSize));
281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::DoubleToI(Register result_reg, XMMRegister input_reg,
286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               XMMRegister scratch,
287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               MinusZeroMode minus_zero_mode,
288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Label* lost_precision, Label* is_nan,
289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Label* minus_zero, Label::Distance dst) {
290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!input_reg.is(scratch));
291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cvttsd2si(result_reg, Operand(input_reg));
292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Cvtsi2sd(scratch, Operand(result_reg));
293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ucomisd(scratch, input_reg);
294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(not_equal, lost_precision, dst);
295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(parity_even, is_nan, dst);
296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (minus_zero_mode == FAIL_ON_MINUS_ZERO) {
297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label done;
298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // The integer converted back is equal to the original. We
299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // only have to test if we got -0 as an input.
300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(result_reg, Operand(result_reg));
301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(not_zero, &done, Label::kNear);
302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movmskpd(result_reg, input_reg);
303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Bit 0 contains the sign of the double in input_reg.
304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If input was positive, we are ok and return 0, otherwise
305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // jump to minus_zero.
306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    and_(result_reg, 1);
307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(not_zero, minus_zero, dst);
308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&done);
309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TruncateHeapNumberToI(Register result_reg,
314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register input_reg) {
315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done, slow_case;
316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (CpuFeatures::IsSupported(SSE3)) {
318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CpuFeatureScope scope(this, SSE3);
319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label convert;
320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Use more powerful conversion when sse3 is available.
321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Load x87 register with heap number.
322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Get exponent alone and check for too-big exponent.
324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(result_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset));
325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    and_(result_reg, HeapNumber::kExponentMask);
326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const uint32_t kTooBigExponent =
327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift;
328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(Operand(result_reg), Immediate(kTooBigExponent));
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(greater_equal, &slow_case, Label::kNear);
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Reserve space for 64 bit answer.
332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sub(Operand(esp), Immediate(kDoubleSize));
333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Do conversion, which cannot fail because we checked the exponent.
334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    fisttp_d(Operand(esp, 0));
335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(result_reg, Operand(esp, 0));  // Low word of answer is the result.
336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    add(Operand(esp), Immediate(kDoubleSize));
337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    jmp(&done, Label::kNear);
338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Slow case.
340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&slow_case);
341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (input_reg.is(result_reg)) {
342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Input is clobbered. Restore number from fpu stack
343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      sub(Operand(esp), Immediate(kDoubleSize));
344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      fstp_d(Operand(esp, 0));
345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SlowTruncateToI(result_reg, esp, 0);
346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      add(esp, Immediate(kDoubleSize));
347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      fstp(0);
349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SlowTruncateToI(result_reg, input_reg);
350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cvttsd2si(result_reg, Operand(xmm0));
354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(result_reg, 0x1);
355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(no_overflow, &done, Label::kNear);
356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Check if the input was 0x8000000 (kMinInt).
357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If no, then we got an overflow and we deoptimize.
358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ExternalReference min_int = ExternalReference::address_of_min_int();
359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ucomisd(xmm0, Operand::StaticVariable(min_int));
360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(not_equal, &slow_case, Label::kNear);
361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(parity_even, &slow_case, Label::kNear);  // NaN.
362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    jmp(&done, Label::kNear);
363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Slow case.
365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&slow_case);
366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (input_reg.is(result_reg)) {
367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Input is clobbered. Restore number from double scratch.
368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      sub(esp, Immediate(kDoubleSize));
369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movsd(MemOperand(esp, 0), xmm0);
370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SlowTruncateToI(result_reg, esp, 0);
371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      add(esp, Immediate(kDoubleSize));
372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SlowTruncateToI(result_reg, input_reg);
374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
380958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::LoadUint32(XMMRegister dst, const Operand& src) {
381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(src, Immediate(0));
383958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ExternalReference uint32_bias = ExternalReference::address_of_uint32_bias();
384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Cvtsi2sd(dst, src);
385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(not_sign, &done, Label::kNear);
386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  addsd(dst, Operand::StaticVariable(uint32_bias));
387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::RecordWriteArray(
392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register object,
393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register value,
394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register index,
395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SaveFPRegsMode save_fp,
396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RememberedSetAction remembered_set_action,
397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiCheck smi_check,
398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PointersToHereCheck pointers_to_here_check_for_value) {
3993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // First, check if a write barrier is even needed. The tests below
4003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // catch stores of Smis.
4013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Skip barrier if writing a smi.
4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (smi_check == INLINE_SMI_CHECK) {
405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_EQ(0, kSmiTag);
4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    test(value, Immediate(kSmiTagMask));
4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(zero, &done);
4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Array access: calculate the destination address in the same manner as
4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // KeyedStoreIC::GenerateGeneric.  Multiply a smi by 2 to get an offset
4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // into an array of words.
4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register dst = index;
4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lea(dst, Operand(object, index, times_half_pointer_size,
4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   FixedArray::kHeaderSize - kHeapObjectTag));
4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordWrite(object, dst, value, save_fp, remembered_set_action,
418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              OMIT_SMI_CHECK, pointers_to_here_check_for_value);
4193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&done);
4213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Clobber clobbered input registers when running with the debug-code flag
4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // turned on to provoke errors.
4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (emit_debug_code()) {
425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(value, Immediate(bit_cast<int32_t>(kZapValue)));
426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(index, Immediate(bit_cast<int32_t>(kZapValue)));
427257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::RecordWriteField(
4323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register object,
4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int offset,
4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register value,
4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register dst,
4363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SaveFPRegsMode save_fp,
4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RememberedSetAction remembered_set_action,
438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiCheck smi_check,
439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PointersToHereCheck pointers_to_here_check_for_value) {
4407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // First, check if a write barrier is even needed. The tests below
4413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // catch stores of Smis.
442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Skip barrier if writing a smi.
4453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (smi_check == INLINE_SMI_CHECK) {
4463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JumpIfSmi(value, &done, Label::kNear);
4473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Although the object register is tagged, the offset is relative to the start
4503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // of the object, so so offset must be a multiple of kPointerSize.
451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsAligned(offset, kPointerSize));
452592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
4533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lea(dst, FieldOperand(object, offset));
4543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (emit_debug_code()) {
4553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label ok;
4563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    test_b(dst, Immediate((1 << kPointerSizeLog2) - 1));
4573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(zero, &ok, Label::kNear);
4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int3();
4593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&ok);
46085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  }
4613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordWrite(object, dst, value, save_fp, remembered_set_action,
463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              OMIT_SMI_CHECK, pointers_to_here_check_for_value);
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&done);
4664515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Clobber clobbered input registers when running with the debug-code flag
4684515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // turned on to provoke errors.
46944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(value, Immediate(bit_cast<int32_t>(kZapValue)));
471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(dst, Immediate(bit_cast<int32_t>(kZapValue)));
4724515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::RecordWriteForMap(
477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register object,
478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Map> map,
479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch1,
480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch2,
481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SaveFPRegsMode save_fp) {
482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register address = scratch1;
485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register value = scratch2;
4863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (emit_debug_code()) {
487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label ok;
488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    lea(address, FieldOperand(object, HeapObject::kMapOffset));
4893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    test_b(address, Immediate((1 << kPointerSizeLog2) - 1));
490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(zero, &ok, Label::kNear);
491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int3();
492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&ok);
493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!object.is(value));
496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!object.is(address));
497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!value.is(address));
498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertNotSmi(object);
499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!FLAG_incremental_marking) {
501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Compute the address.
505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lea(address, FieldOperand(object, HeapObject::kMapOffset));
506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // A single check of the map's pages interesting flag suffices, since it is
508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // only set during incremental collection, and then it's also guaranteed that
509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the from object's page's interesting flag is also set.  This optimization
510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // relies on the fact that maps can never be in new space.
511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!isolate()->heap()->InNewSpace(*map));
512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckPageFlagForMap(map,
513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      MemoryChunk::kPointersToHereAreInterestingMask,
514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      zero,
515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      &done,
516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      Label::kNear);
517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordWriteStub stub(isolate(), object, value, address, OMIT_REMEMBERED_SET,
519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       save_fp);
520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallStub(&stub);
521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Count number of write barriers in generated code.
525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate()->counters()->write_barriers_static()->Increment();
526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1);
527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Clobber clobbered input registers when running with the debug-code flag
529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // turned on to provoke errors.
530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(value, Immediate(bit_cast<int32_t>(kZapValue)));
532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(scratch1, Immediate(bit_cast<int32_t>(kZapValue)));
533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(scratch2, Immediate(bit_cast<int32_t>(kZapValue)));
534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::RecordWrite(
539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register object,
540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register address,
541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register value,
542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SaveFPRegsMode fp_mode,
543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RememberedSetAction remembered_set_action,
544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiCheck smi_check,
545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PointersToHereCheck pointers_to_here_check_for_value) {
546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!object.is(value));
547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!object.is(address));
548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!value.is(address));
549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertNotSmi(object);
550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (remembered_set_action == OMIT_REMEMBERED_SET &&
5523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      !FLAG_incremental_marking) {
5533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return;
5543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
5573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label ok;
5583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    cmp(value, Operand(address, 0));
5593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(equal, &ok, Label::kNear);
5603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int3();
5613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&ok);
5623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5648defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // First, check if a write barrier is even needed. The tests below
5658defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // catch stores of Smis and stores into young gen.
5668defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Label done;
5678defd9ff6930b4e24729971a61cf7469daf119beSteve Block
5683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (smi_check == INLINE_SMI_CHECK) {
5693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Skip barrier if writing a smi.
5703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JumpIfSmi(value, &done, Label::kNear);
5713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (pointers_to_here_check_for_value != kPointersToHereAreAlwaysInteresting) {
574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CheckPageFlag(value,
575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  value,  // Used as scratch.
576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  MemoryChunk::kPointersToHereAreInterestingMask,
577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  zero,
578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  &done,
579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  Label::kNear);
580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPageFlag(object,
5823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                value,  // Used as scratch.
5833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                MemoryChunk::kPointersFromHereAreInterestingMask,
5843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                zero,
5853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                &done,
5863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                Label::kNear);
5873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordWriteStub stub(isolate(), object, value, address, remembered_set_action,
589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       fp_mode);
5903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallStub(&stub);
5918defd9ff6930b4e24729971a61cf7469daf119beSteve Block
5928defd9ff6930b4e24729971a61cf7469daf119beSteve Block  bind(&done);
5938defd9ff6930b4e24729971a61cf7469daf119beSteve Block
594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Count number of write barriers in generated code.
595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate()->counters()->write_barriers_static()->Increment();
596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1);
597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Clobber clobbered registers when running with the debug-code flag
5998defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // turned on to provoke errors.
60044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(address, Immediate(bit_cast<int32_t>(kZapValue)));
602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(value, Immediate(bit_cast<int32_t>(kZapValue)));
6038defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
6048defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
6058defd9ff6930b4e24729971a61cf7469daf119beSteve Block
606109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::RecordWriteCodeEntryField(Register js_function,
607109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                               Register code_entry,
608109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                               Register scratch) {
609109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  const int offset = JSFunction::kCodeEntryOffset;
610109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
611109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Since a code entry (value) is always in old space, we don't need to update
612109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // remembered set. If incremental marking is off, there is nothing for us to
613109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // do.
614109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (!FLAG_incremental_marking) return;
615109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
616109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(!js_function.is(code_entry));
617109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(!js_function.is(scratch));
618109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(!code_entry.is(scratch));
619109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  AssertNotSmi(js_function);
620109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
621109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (emit_debug_code()) {
622109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Label ok;
623109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    lea(scratch, FieldOperand(js_function, offset));
624109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    cmp(code_entry, Operand(scratch, 0));
625109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    j(equal, &ok, Label::kNear);
626109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    int3();
627109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    bind(&ok);
628109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
629109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
630109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // First, check if a write barrier is even needed. The tests below
631109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // catch stores of Smis and stores into young gen.
632109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Label done;
633109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
634109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  CheckPageFlag(code_entry, scratch,
635109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                MemoryChunk::kPointersToHereAreInterestingMask, zero, &done,
636109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                Label::kNear);
637109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  CheckPageFlag(js_function, scratch,
638109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                MemoryChunk::kPointersFromHereAreInterestingMask, zero, &done,
639109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                Label::kNear);
640109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
641109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Save input registers.
642109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  push(js_function);
643109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  push(code_entry);
644109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
645109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  const Register dst = scratch;
646109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  lea(dst, FieldOperand(js_function, offset));
647109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
648109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Save caller-saved registers.
649109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PushCallerSaved(kDontSaveFPRegs, js_function, code_entry);
650109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
651109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  int argument_count = 3;
652109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PrepareCallCFunction(argument_count, code_entry);
653109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  mov(Operand(esp, 0 * kPointerSize), js_function);
654109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  mov(Operand(esp, 1 * kPointerSize), dst);  // Slot.
655109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  mov(Operand(esp, 2 * kPointerSize),
656109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      Immediate(ExternalReference::isolate_address(isolate())));
657109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
658109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  {
659109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    AllowExternalCallThatCantCauseGC scope(this);
660109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    CallCFunction(
661109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        ExternalReference::incremental_marking_record_write_code_entry_function(
662109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch            isolate()),
663109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        argument_count);
664109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
665109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
666109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Restore caller-saved registers.
667109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PopCallerSaved(kDontSaveFPRegs, js_function, code_entry);
668109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
669109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Restore input registers.
670109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  pop(code_entry);
671109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  pop(js_function);
672109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
673109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  bind(&done);
674109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
6758defd9ff6930b4e24729971a61cf7469daf119beSteve Block
67662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid MacroAssembler::MaybeDropFrames() {
67762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Check whether we need to drop frames to restart a function on the stack.
67862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ExternalReference restart_fp =
67962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      ExternalReference::debug_restart_fp_address(isolate());
68062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  mov(ebx, Operand::StaticVariable(restart_fp));
68162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  test(ebx, ebx);
68262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  j(not_zero, isolate()->builtins()->FrameDropperTrampoline(),
68362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    RelocInfo::CODE_TARGET);
684402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Cvtsi2sd(XMMRegister dst, const Operand& src) {
687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  xorps(dst, dst);
688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cvtsi2sd(dst, src);
689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
692109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::Cvtui2ss(XMMRegister dst, Register src, Register tmp) {
693109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Label msb_set_src;
694109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Label jmp_return;
695109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  test(src, src);
696109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  j(sign, &msb_set_src, Label::kNear);
697109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  cvtsi2ss(dst, src);
698109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  jmp(&jmp_return, Label::kNear);
699109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  bind(&msb_set_src);
700109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  mov(tmp, src);
701109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  shr(src, 1);
702109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Recover the least significant bit to avoid rounding errors.
703109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  and_(tmp, Immediate(1));
704109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  or_(src, tmp);
705109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  cvtsi2ss(dst, src);
706109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  addss(dst, dst);
707109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  bind(&jmp_return);
708109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
709109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
7103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::ShlPair(Register high, Register low, uint8_t shift) {
7113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (shift >= 32) {
7123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    mov(high, low);
7133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shl(high, shift - 32);
7143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    xor_(low, low);
7153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
7163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shld(high, low, shift);
7173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shl(low, shift);
7183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
7193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
7203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
7213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::ShlPair_cl(Register high, Register low) {
7223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  shld_cl(high, low);
7233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  shl_cl(low);
7243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label done;
7253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test(ecx, Immediate(0x20));
7263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  j(equal, &done, Label::kNear);
7273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(high, low);
7283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  xor_(low, low);
7293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&done);
7303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
7313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
7323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::ShrPair(Register high, Register low, uint8_t shift) {
7333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (shift >= 32) {
7343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    mov(low, high);
7353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shr(low, shift - 32);
7363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    xor_(high, high);
7373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
7383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shrd(high, low, shift);
7393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shr(high, shift);
7403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
7413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
7423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
7433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::ShrPair_cl(Register high, Register low) {
7443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  shrd_cl(low, high);
7453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  shr_cl(high);
7463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label done;
7473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test(ecx, Immediate(0x20));
7483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  j(equal, &done, Label::kNear);
7493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(low, high);
7503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  xor_(high, high);
7513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&done);
7523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
7533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
7543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::SarPair(Register high, Register low, uint8_t shift) {
7553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (shift >= 32) {
7563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    mov(low, high);
7573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    sar(low, shift - 32);
7583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    sar(high, 31);
7593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
7603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shrd(high, low, shift);
7613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    sar(high, shift);
7623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
7633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
7643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
7653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::SarPair_cl(Register high, Register low) {
7663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  shrd_cl(low, high);
7673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  sar_cl(high);
7683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label done;
7693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test(ecx, Immediate(0x20));
7703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  j(equal, &done, Label::kNear);
7713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(low, high);
7723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  sar(high, 31);
7733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&done);
7743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
775109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
776053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Blockbool MacroAssembler::IsUnsafeImmediate(const Immediate& x) {
777053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  static const int kMaxImmediateBits = 17;
778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!RelocInfo::IsNone(x.rmode_)) return false;
779053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  return !is_intn(x.x_, kMaxImmediateBits);
780053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block}
781053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
782053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::SafeMove(Register dst, const Immediate& x) {
784053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  if (IsUnsafeImmediate(x) && jit_cookie() != 0) {
785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(dst, Immediate(x.x_ ^ jit_cookie()));
786053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block    xor_(dst, jit_cookie());
787053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  } else {
788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(dst, x);
789053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  }
790053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block}
791053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
792053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
793053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Blockvoid MacroAssembler::SafePush(const Immediate& x) {
794053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  if (IsUnsafeImmediate(x) && jit_cookie() != 0) {
795053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block    push(Immediate(x.x_ ^ jit_cookie()));
796053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block    xor_(Operand(esp, 0), Immediate(jit_cookie()));
797053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  } else {
798053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block    push(x);
799053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  }
800053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block}
801053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
802053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpObjectType(Register heap_object,
804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   InstanceType type,
805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   Register map) {
806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(map, FieldOperand(heap_object, HeapObject::kMapOffset));
807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CmpInstanceType(map, type);
808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpInstanceType(Register map, InstanceType type) {
8123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  cmpb(FieldOperand(map, Map::kInstanceTypeOffset), Immediate(type));
813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CompareMap(Register obj, Handle<Map> map) {
8163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmp(FieldOperand(obj, HeapObject::kMapOffset), map);
8173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
8183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::CheckMap(Register obj,
8213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Handle<Map> map,
8223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Label* fail,
823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              SmiCheckType smi_check_type) {
824257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (smi_check_type == DO_SMI_CHECK) {
825257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    JumpIfSmi(obj, fail);
8263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
8273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompareMap(obj, map);
8293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  j(not_equal, fail);
8303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
8313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
8323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
833958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::DispatchWeakMap(Register obj, Register scratch1,
834958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                     Register scratch2, Handle<WeakCell> cell,
835958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                     Handle<Code> success,
836958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                     SmiCheckType smi_check_type) {
837257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label fail;
838257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (smi_check_type == DO_SMI_CHECK) {
839257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    JumpIfSmi(obj, &fail);
840257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
841958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  mov(scratch1, FieldOperand(obj, HeapObject::kMapOffset));
842958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CmpWeakValue(scratch1, cell, scratch2);
843257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(equal, success);
844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
845257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&fail);
846257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
847257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
848257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
849e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeCondition MacroAssembler::IsObjectStringType(Register heap_object,
850e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                             Register map,
851e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                             Register instance_type) {
852e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  mov(map, FieldOperand(heap_object, HeapObject::kMapOffset));
853e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
85469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kNotStringTag != 0);
855e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  test(instance_type, Immediate(kIsNotStringMask));
856e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  return zero;
857e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
858e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
859e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochCondition MacroAssembler::IsObjectNameType(Register heap_object,
861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register map,
862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register instance_type) {
863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(map, FieldOperand(heap_object, HeapObject::kMapOffset));
864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
8653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  cmpb(instance_type, Immediate(LAST_NAME_TYPE));
866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return below_equal;
867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::FCmp() {
871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fucomip();
872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fstp(0);
873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertNumber(Register object) {
877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label ok;
879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    JumpIfSmi(object, &ok);
880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(FieldOperand(object, HeapObject::kMapOffset),
881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate()->factory()->heap_number_map());
882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, kOperandNotANumber);
883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&ok);
8843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::AssertNotNumber(Register object) {
8883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (emit_debug_code()) {
8893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    test(object, Immediate(kSmiTagMask));
8903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Check(not_equal, kOperandIsANumber);
8913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    cmp(FieldOperand(object, HeapObject::kMapOffset),
8923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        isolate()->factory()->heap_number_map());
8933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Check(not_equal, kOperandIsANumber);
8943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
8953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertSmi(Register object) {
898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(object, Immediate(kSmiTagMask));
900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, kOperandIsNotASmi);
901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertString(Register object) {
906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(object, Immediate(kSmiTagMask));
908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kOperandIsASmiAndNotAString);
909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    push(object);
910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(object, FieldOperand(object, HeapObject::kMapOffset));
911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CmpInstanceType(object, FIRST_NONSTRING_TYPE);
912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    pop(object);
913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(below, kOperandIsNotAString);
914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertName(Register object) {
919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(object, Immediate(kSmiTagMask));
921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kOperandIsASmiAndNotAName);
922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    push(object);
923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(object, FieldOperand(object, HeapObject::kMapOffset));
924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CmpInstanceType(object, LAST_NAME_TYPE);
925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    pop(object);
926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(below_equal, kOperandIsNotAName);
927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
931014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::AssertFunction(Register object) {
932014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (emit_debug_code()) {
933014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    test(object, Immediate(kSmiTagMask));
934014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(not_equal, kOperandIsASmiAndNotAFunction);
935014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(object);
936014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CmpObjectType(object, JS_FUNCTION_TYPE, object);
937014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Pop(object);
938014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(equal, kOperandIsNotAFunction);
939014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
940014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
941014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
942014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
943014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::AssertBoundFunction(Register object) {
944014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (emit_debug_code()) {
945014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    test(object, Immediate(kSmiTagMask));
946014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(not_equal, kOperandIsASmiAndNotABoundFunction);
947014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(object);
948014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CmpObjectType(object, JS_BOUND_FUNCTION_TYPE, object);
949014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Pop(object);
950014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(equal, kOperandIsNotABoundFunction);
951014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
952014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
953014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
954bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::AssertGeneratorObject(Register object) {
955bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (emit_debug_code()) {
956bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    test(object, Immediate(kSmiTagMask));
957bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Check(not_equal, kOperandIsASmiAndNotAGeneratorObject);
958bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Push(object);
959bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    CmpObjectType(object, JS_GENERATOR_OBJECT_TYPE, object);
960bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Pop(object);
961bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Check(equal, kOperandIsNotAGeneratorObject);
962bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
963bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
964014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
965109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::AssertReceiver(Register object) {
966109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (emit_debug_code()) {
967109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    test(object, Immediate(kSmiTagMask));
968109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Check(not_equal, kOperandIsASmiAndNotAReceiver);
969109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Push(object);
970109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
971109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    CmpObjectType(object, FIRST_JS_RECEIVER_TYPE, object);
972109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Pop(object);
973109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Check(above_equal, kOperandIsNotAReceiver);
974109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
975109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
976109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
977109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertUndefinedOrAllocationSite(Register object) {
979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label done_checking;
981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AssertNotSmi(object);
982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(object, isolate()->factory()->undefined_value());
983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(equal, &done_checking);
984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(FieldOperand(object, 0),
985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Immediate(isolate()->factory()->allocation_site_map()));
986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Assert(equal, kExpectedUndefinedOrCell);
987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&done_checking);
988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
989402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
990402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
991402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertNotSmi(Register object) {
993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(object, Immediate(kSmiTagMask));
995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kOperandIsASmi);
996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
997756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
998756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
9993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::StubPrologue(StackFrame::Type type) {
1000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  push(ebp);  // Caller's frame pointer.
1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(ebp, esp);
100262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  push(Immediate(StackFrame::TypeToMarker(type)));
100380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
100480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Prologue(bool code_pre_aging) {
1006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PredictableCodeSizeScope predictible_code_size_scope(this,
1007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kNoCodeAgeSequenceLength);
1008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (code_pre_aging) {
1009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Pre-age the code.
1010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    call(isolate()->builtins()->MarkCodeAsExecutedOnce(),
1011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        RelocInfo::CODE_AGE_SEQUENCE);
1012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Nop(kNoCodeAgeSequenceLength - Assembler::kCallInstructionLength);
1013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    push(ebp);  // Caller's frame pointer.
1015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(ebp, esp);
1016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    push(esi);  // Callee's context.
1017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    push(edi);  // Callee's JS function.
1018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
10196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
10206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
102162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid MacroAssembler::EmitLoadFeedbackVector(Register vector) {
1022014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(vector, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
102362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  mov(vector, FieldOperand(vector, JSFunction::kFeedbackVectorOffset));
102462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  mov(vector, FieldOperand(vector, Cell::kValueOffset));
1025014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1026014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1027014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1028958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::EnterFrame(StackFrame::Type type,
1029958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                bool load_constant_pool_pointer_reg) {
1030958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Out-of-line constant pool not implemented on ia32.
1031958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  UNREACHABLE();
1032958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1033958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1034958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::EnterFrame(StackFrame::Type type) {
1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(ebp);
10373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(ebp, esp);
103862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  push(Immediate(StackFrame::TypeToMarker(type)));
10393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (type == StackFrame::INTERNAL) {
10403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    push(Immediate(CodeObject()));
10413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
104244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
104344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    cmp(Operand(esp, 0), Immediate(isolate()->factory()->undefined_value()));
1044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kCodeObjectNotProperlyPatched);
1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LeaveFrame(StackFrame::Type type) {
105044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
10513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    cmp(Operand(ebp, CommonFrameConstants::kContextOrFrameTypeOffset),
105262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Immediate(StackFrame::TypeToMarker(type)));
1053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, kStackFrameTypesMustMatch);
1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  leave();
1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1058f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MacroAssembler::EnterBuiltinFrame(Register context, Register target,
1059f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                       Register argc) {
1060f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Push(ebp);
1061f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Move(ebp, esp);
1062f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Push(context);
1063f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Push(target);
1064f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Push(argc);
1065f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
1066f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1067f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MacroAssembler::LeaveBuiltinFrame(Register context, Register target,
1068f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                       Register argc) {
1069f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Pop(argc);
1070f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Pop(target);
1071f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Pop(context);
1072f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  leave();
1073f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
1074f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1075f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MacroAssembler::EnterExitFramePrologue(StackFrame::Type frame_type) {
1076f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(frame_type == StackFrame::EXIT ||
1077f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch         frame_type == StackFrame::BUILTIN_EXIT);
107880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
10793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up the frame structure on the stack.
10803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(+2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement);
10813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(+1 * kPointerSize, ExitFrameConstants::kCallerPCOffset);
10823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset);
1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(ebp);
10843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(ebp, esp);
1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
108680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Reserve room for entry stack pointer and push the code object.
108762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  push(Immediate(StackFrame::TypeToMarker(frame_type)));
10883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(-2 * kPointerSize, ExitFrameConstants::kSPOffset);
1089402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  push(Immediate(0));  // Saved entry sp, patched before call.
10903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(-3 * kPointerSize, ExitFrameConstants::kCodeOffset);
1091402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  push(Immediate(CodeObject()));  // Accessed from ExitFrame::code_slot.
1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Save the frame pointer and the context in top.
1094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress, isolate());
1095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference context_address(Isolate::kContextAddress, isolate());
1096958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ExternalReference c_function_address(Isolate::kCFunctionAddress, isolate());
1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(Operand::StaticVariable(c_entry_fp_address), ebp);
1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(Operand::StaticVariable(context_address), esi);
1099958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  mov(Operand::StaticVariable(c_function_address), ebx);
1100d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid MacroAssembler::EnterExitFrameEpilogue(int argc, bool save_doubles) {
1104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Optionally save all XMM registers.
1105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (save_doubles) {
1106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int space = XMMRegister::kMaxNumRegisters * kDoubleSize +
1107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                argc * kPointerSize;
11083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sub(esp, Immediate(space));
11093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    const int offset = -ExitFrameConstants::kFixedFrameSizeFromFp;
1110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
1111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      XMMRegister reg = XMMRegister::from_code(i);
1112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movsd(Operand(ebp, offset - ((i + 1) * kDoubleSize)), reg);
1113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
11153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sub(esp, Immediate(argc * kPointerSize));
1116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the required frame alignment for the OS.
1119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kFrameAlignment = base::OS::ActivationFrameAlignment();
1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (kFrameAlignment > 0) {
1121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(base::bits::IsPowerOfTwo32(kFrameAlignment));
1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    and_(esp, -kFrameAlignment);
1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the saved entry sp.
1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(Operand(ebp, ExitFrameConstants::kSPOffset), esp);
1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1129f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MacroAssembler::EnterExitFrame(int argc, bool save_doubles,
1130f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                    StackFrame::Type frame_type) {
1131f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  EnterExitFramePrologue(frame_type);
1132d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
11333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up argc and argv in callee-saved registers.
1134d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
11353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(edi, eax);
1136d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  lea(esi, Operand(ebp, eax, times_4, offset));
1137d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
113844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Reserve space for argc, argv and isolate.
1139109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  EnterExitFrameEpilogue(argc, save_doubles);
1140d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1141d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1142d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
11438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid MacroAssembler::EnterApiExitFrame(int argc) {
1144f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  EnterExitFramePrologue(StackFrame::EXIT);
1145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  EnterExitFrameEpilogue(argc, false);
1146d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1147d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1148d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LeaveExitFrame(bool save_doubles, bool pop_arguments) {
1150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Optionally restore all XMM registers.
1151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (save_doubles) {
11523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    const int offset = -ExitFrameConstants::kFixedFrameSizeFromFp;
1153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
1154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      XMMRegister reg = XMMRegister::from_code(i);
1155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movsd(reg, Operand(ebp, offset - ((i + 1) * kDoubleSize)));
1156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (pop_arguments) {
1160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Get the return address from the stack and restore the frame pointer.
1161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mov(ecx, Operand(ebp, 1 * kPointerSize));
1162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mov(ebp, Operand(ebp, 0 * kPointerSize));
1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Pop the arguments and the receiver from the caller stack.
1165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    lea(esp, Operand(esi, 1 * kPointerSize));
1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Push the return address to get ready to return.
1168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    push(ecx);
1169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
1170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Otherwise just leave the exit frame.
1171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    leave();
1172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
11738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LeaveExitFrameEpilogue(true);
11758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
11768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::LeaveExitFrameEpilogue(bool restore_context) {
1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Restore current context from top and clear it in debug mode.
1180589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ExternalReference context_address(Isolate::kContextAddress, isolate());
1181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (restore_context) {
1182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(esi, Operand::StaticVariable(context_address));
1183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(Operand::StaticVariable(context_address), Immediate(0));
1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clear the top frame.
1189589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress,
119044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       isolate());
1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(Operand::StaticVariable(c_entry_fp_address), Immediate(0));
1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::LeaveApiExitFrame(bool restore_context) {
11963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(esp, ebp);
11978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  pop(ebp);
11988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LeaveExitFrameEpilogue(restore_context);
12008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
12018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
12028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::PushStackHandler() {
1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Adjust this code if not the case.
1205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(StackHandlerConstants::kSize == 1 * kPointerSize);
120669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
12073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Link the current handler as the next handler.
12093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
12103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  push(Operand::StaticVariable(handler_address));
1211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
12123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set this new handler as the current one.
12133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(Operand::StaticVariable(handler_address), esp);
1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::PopStackHandler() {
121869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
12193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
12203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  pop(Operand::StaticVariable(handler_address));
12213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(esp, Immediate(StackHandlerConstants::kSize - kPointerSize));
12223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
12233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Compute the hash code from the untagged key.  This must be kept in sync with
1226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ComputeIntegerHash in utils.h and KeyedLoadGenericStub in
1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// code-stub-hydrogen.cc
1228c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch//
1229c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch// Note: r0 will contain hash code
1230c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdochvoid MacroAssembler::GetNumberHash(Register r0, Register scratch) {
1231c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // Xor original key with a seed.
1232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (serializer_enabled()) {
12333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ExternalReference roots_array_start =
12343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ExternalReference::roots_array_start(isolate());
1235c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    mov(scratch, Immediate(Heap::kHashSeedRootIndex));
12363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(scratch,
12373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Operand::StaticArray(scratch, times_pointer_size, roots_array_start));
1238c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    SmiUntag(scratch);
12393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    xor_(r0, scratch);
1240c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  } else {
1241c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    int32_t seed = isolate()->heap()->HashSeed();
12423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    xor_(r0, Immediate(seed));
1243c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  }
1244c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
1245c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = ~hash + (hash << 15);
1246c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  mov(scratch, r0);
1247c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  not_(r0);
1248c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  shl(scratch, 15);
12493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(r0, scratch);
1250c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash ^ (hash >> 12);
1251c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  mov(scratch, r0);
1252c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  shr(scratch, 12);
12533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  xor_(r0, scratch);
1254c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash + (hash << 2);
1255c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  lea(r0, Operand(r0, r0, times_4, 0));
1256c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash ^ (hash >> 4);
1257c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  mov(scratch, r0);
1258c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  shr(scratch, 4);
12593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  xor_(r0, scratch);
1260c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash * 2057;
1261c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  imul(r0, r0, 2057);
1262c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash ^ (hash >> 16);
1263c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  mov(scratch, r0);
1264c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  shr(scratch, 16);
12653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  xor_(r0, scratch);
1266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  and_(r0, 0x3fffffff);
1267c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch}
1268c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LoadAllocationTopHelper(Register result,
1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register scratch,
1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             AllocationFlags flags) {
1272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_top =
1273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationTopReference(isolate(), flags);
1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Just return if allocation top is already known.
1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((flags & RESULT_CONTAINS_TOP) != 0) {
1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // No use of scratch if allocation top is provided.
1278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(scratch.is(no_reg));
1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Assert that result actually contains top on entry.
1281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(result, Operand::StaticVariable(allocation_top));
1282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, kUnexpectedAllocationTop);
1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Move address of new object to result. Use scratch register if available.
1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (scratch.is(no_reg)) {
1289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(result, Operand::StaticVariable(allocation_top));
1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(scratch, Immediate(allocation_top));
1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(result, Operand(scratch, 0));
1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::UpdateAllocationTopHelper(Register result_end,
1298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register scratch,
1299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               AllocationFlags flags) {
130044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
1301d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    test(result_end, Immediate(kObjectAlignmentMask));
1302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(zero, kUnalignedAllocationInNewSpace);
1303d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1304d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_top =
1306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationTopReference(isolate(), flags);
1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update new top. Use scratch if available.
1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (scratch.is(no_reg)) {
1310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(Operand::StaticVariable(allocation_top), result_end);
1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(Operand(scratch, 0), result_end);
1313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Allocate(int object_size,
1318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result,
1319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result_end,
1320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register scratch,
1321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Label* gc_required,
1322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              AllocationFlags flags) {
1323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0);
1324f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(object_size <= kMaxRegularHeapObjectSize);
1325bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK((flags & ALLOCATION_FOLDED) == 0);
13265913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  if (!FLAG_inline_new) {
132744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (emit_debug_code()) {
13285913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // Trash the registers to simulate an allocation failure.
13295913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      mov(result, Immediate(0x7091));
13305913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (result_end.is_valid()) {
13315913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        mov(result_end, Immediate(0x7191));
13325913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
13335913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (scratch.is_valid()) {
13345913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        mov(scratch, Immediate(0x7291));
13355913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
13365913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    }
13375913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    jmp(gc_required);
13385913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    return;
13395913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
1340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result.is(result_end));
1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load address of new object into result.
13438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LoadAllocationTopHelper(result, scratch, flags);
1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_limit =
1346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationLimitReference(isolate(), flags);
1347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Align the next allocation. Storing the filler map without checking top is
1349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // safe in new-space because the limit of the heap is aligned there.
1350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
1351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
1352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label aligned;
1353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(result, Immediate(kDoubleAlignmentMask));
1354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(zero, &aligned, Label::kNear);
1355014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if ((flags & PRETENURE) != 0) {
1356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cmp(result, Operand::StaticVariable(allocation_limit));
1357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      j(above_equal, gc_required);
1358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(Operand(result, 0),
1360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Immediate(isolate()->factory()->one_pointer_filler_map()));
1361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    add(result, Immediate(kDoubleSize / 2));
1362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&aligned);
1363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Calculate new top and bail out if space is exhausted.
1366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register top_reg = result_end.is_valid() ? result_end : result;
1367bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
13681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (!top_reg.is(result)) {
13691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    mov(top_reg, result);
1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
13713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(top_reg, Immediate(object_size));
1372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(top_reg, Operand::StaticVariable(allocation_limit));
1373257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(above, gc_required);
1374e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1375bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
1376bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // The top pointer is not updated for allocation folding dominators.
1377bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    UpdateAllocationTopHelper(top_reg, scratch, flags);
1378bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1379bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1380bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (top_reg.is(result)) {
1381bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    sub(result, Immediate(object_size - kHeapObjectTag));
1382bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  } else {
1383bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // Tag the result.
1384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kHeapObjectTag == 1);
1385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    inc(result);
1386bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
1387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Allocate(int header_size,
1391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              ScaleFactor element_size,
1392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register element_count,
1393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              RegisterValueType element_count_type,
1394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result,
1395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result_end,
1396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register scratch,
1397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Label* gc_required,
1398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              AllocationFlags flags) {
1399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((flags & SIZE_IN_WORDS) == 0);
1400bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK((flags & ALLOCATION_FOLDING_DOMINATOR) == 0);
1401bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK((flags & ALLOCATION_FOLDED) == 0);
14025913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  if (!FLAG_inline_new) {
140344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (emit_debug_code()) {
14045913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // Trash the registers to simulate an allocation failure.
14055913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      mov(result, Immediate(0x7091));
14065913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      mov(result_end, Immediate(0x7191));
14075913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (scratch.is_valid()) {
14085913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        mov(scratch, Immediate(0x7291));
14095913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
14105913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // Register element_count is not modified by the function.
14115913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    }
14125913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    jmp(gc_required);
14135913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    return;
14145913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
1415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result.is(result_end));
1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load address of new object into result.
14188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LoadAllocationTopHelper(result, scratch, flags);
1419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_limit =
1421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationLimitReference(isolate(), flags);
1422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Align the next allocation. Storing the filler map without checking top is
1424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // safe in new-space because the limit of the heap is aligned there.
1425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
1426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
1427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label aligned;
1428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(result, Immediate(kDoubleAlignmentMask));
1429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(zero, &aligned, Label::kNear);
1430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if ((flags & PRETENURE) != 0) {
1431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cmp(result, Operand::StaticVariable(allocation_limit));
1432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      j(above_equal, gc_required);
1433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(Operand(result, 0),
1435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Immediate(isolate()->factory()->one_pointer_filler_map()));
1436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    add(result, Immediate(kDoubleSize / 2));
1437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&aligned);
1438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
14391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Calculate new top and bail out if space is exhausted.
14411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // We assume that element_count*element_size + header_size does not
14421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // overflow.
1443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (element_count_type == REGISTER_VALUE_IS_SMI) {
1444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(static_cast<ScaleFactor>(times_2 - 1) == times_1);
1445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(static_cast<ScaleFactor>(times_4 - 1) == times_2);
1446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(static_cast<ScaleFactor>(times_8 - 1) == times_4);
1447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(element_size >= times_2);
1448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kSmiTagSize == 1);
1449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    element_size = static_cast<ScaleFactor>(element_size - 1);
1450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(element_count_type == REGISTER_VALUE_IS_INT32);
1452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1453bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
14541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  lea(result_end, Operand(element_count, element_size, header_size));
14553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(result_end, result);
1456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(result_end, Operand::StaticVariable(allocation_limit));
1457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(above, gc_required);
1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1459bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Tag result.
1460bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(kHeapObjectTag == 1);
1461bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  inc(result);
1462e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UpdateAllocationTopHelper(result_end, scratch, flags);
1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Allocate(Register object_size,
1468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result,
1469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result_end,
1470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register scratch,
1471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Label* gc_required,
1472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              AllocationFlags flags) {
1473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0);
1474bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK((flags & ALLOCATION_FOLDED) == 0);
14755913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  if (!FLAG_inline_new) {
147644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (emit_debug_code()) {
14775913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // Trash the registers to simulate an allocation failure.
14785913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      mov(result, Immediate(0x7091));
14795913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      mov(result_end, Immediate(0x7191));
14805913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (scratch.is_valid()) {
14815913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        mov(scratch, Immediate(0x7291));
14825913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
14835913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // object_size is left unchanged by this function.
14845913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    }
14855913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    jmp(gc_required);
14865913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    return;
14875913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
1488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result.is(result_end));
1489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load address of new object into result.
14918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LoadAllocationTopHelper(result, scratch, flags);
1492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_limit =
1494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationLimitReference(isolate(), flags);
1495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Align the next allocation. Storing the filler map without checking top is
1497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // safe in new-space because the limit of the heap is aligned there.
1498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
1499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
1500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label aligned;
1501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(result, Immediate(kDoubleAlignmentMask));
1502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(zero, &aligned, Label::kNear);
1503014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if ((flags & PRETENURE) != 0) {
1504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cmp(result, Operand::StaticVariable(allocation_limit));
1505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      j(above_equal, gc_required);
1506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(Operand(result, 0),
1508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Immediate(isolate()->factory()->one_pointer_filler_map()));
1509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    add(result, Immediate(kDoubleSize / 2));
1510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&aligned);
1511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Calculate new top and bail out if space is exhausted.
1514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!object_size.is(result_end)) {
1515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(result_end, object_size);
1516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
15173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(result_end, result);
1518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(result_end, Operand::StaticVariable(allocation_limit));
1519257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(above, gc_required);
1520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1521bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Tag result.
1522bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(kHeapObjectTag == 1);
1523bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  inc(result);
1524bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1525bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
1526bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // The top pointer is not updated for allocation folding dominators.
1527bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    UpdateAllocationTopHelper(result_end, scratch, flags);
1528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1529bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1530e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1531bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::FastAllocate(int object_size, Register result,
1532bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                  Register result_end, AllocationFlags flags) {
1533bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!result.is(result_end));
1534bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Load address of new object into result.
1535bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  LoadAllocationTopHelper(result, no_reg, flags);
1536bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1537bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
1538bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
1539bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Label aligned;
1540bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    test(result, Immediate(kDoubleAlignmentMask));
1541bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    j(zero, &aligned, Label::kNear);
1542bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    mov(Operand(result, 0),
1543bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        Immediate(isolate()->factory()->one_pointer_filler_map()));
1544bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    add(result, Immediate(kDoubleSize / 2));
1545bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    bind(&aligned);
1546bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1547bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1548bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  lea(result_end, Operand(result, object_size));
1549bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  UpdateAllocationTopHelper(result_end, no_reg, flags);
1550bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1551bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(kHeapObjectTag == 1);
1552bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  inc(result);
1553bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1554bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1555bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::FastAllocate(Register object_size, Register result,
1556bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                  Register result_end, AllocationFlags flags) {
1557bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!result.is(result_end));
1558bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Load address of new object into result.
1559bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  LoadAllocationTopHelper(result, no_reg, flags);
1560bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1561bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
1562bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
1563bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Label aligned;
1564bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    test(result, Immediate(kDoubleAlignmentMask));
1565bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    j(zero, &aligned, Label::kNear);
1566bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    mov(Operand(result, 0),
1567bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        Immediate(isolate()->factory()->one_pointer_filler_map()));
1568bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    add(result, Immediate(kDoubleSize / 2));
1569bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    bind(&aligned);
1570bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1571bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1572bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  lea(result_end, Operand(result, object_size, times_1, 0));
1573bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  UpdateAllocationTopHelper(result_end, no_reg, flags);
1574bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1575bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(kHeapObjectTag == 1);
1576bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  inc(result);
1577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::AllocateHeapNumber(Register result,
15813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                        Register scratch1,
15823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                        Register scratch2,
1583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        Label* gc_required,
1584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        MutableMode mode) {
15853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Allocate heap number in new space.
1586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(HeapNumber::kSize, result, scratch1, scratch2, gc_required,
1587bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
1588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Map> map = mode == MUTABLE
1590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ? isolate()->factory()->mutable_heap_number_map()
1591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : isolate()->factory()->heap_number_map();
15923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Set the map.
1594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(FieldOperand(result, HeapObject::kMapOffset), Immediate(map));
15953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
15963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1597014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::AllocateJSValue(Register result, Register constructor,
1598014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                     Register value, Register scratch,
1599014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                     Label* gc_required) {
1600014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!result.is(constructor));
1601014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!result.is(scratch));
1602014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!result.is(value));
1603014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1604014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Allocate JSValue in new space.
1605bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Allocate(JSValue::kSize, result, scratch, no_reg, gc_required,
1606bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
1607014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1608014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Initialize the JSValue.
1609014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LoadGlobalFunctionInitialMap(constructor, scratch);
1610014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(FieldOperand(result, HeapObject::kMapOffset), scratch);
1611014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LoadRoot(scratch, Heap::kEmptyFixedArrayRootIndex);
1612014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(FieldOperand(result, JSObject::kPropertiesOffset), scratch);
1613014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(FieldOperand(result, JSObject::kElementsOffset), scratch);
1614014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(FieldOperand(result, JSValue::kValueOffset), value);
1615014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
1616014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1617014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1618014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::InitializeFieldsWithFiller(Register current_address,
1619014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                Register end_address,
16203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Register filler) {
16213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label loop, entry;
1622109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  jmp(&entry, Label::kNear);
16233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&loop);
1624014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(Operand(current_address, 0), filler);
1625014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  add(current_address, Immediate(kPointerSize));
16263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&entry);
1627014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  cmp(current_address, end_address);
1628109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  j(below, &loop, Label::kNear);
16293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
16303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::BooleanBitTest(Register object,
16333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    int field_offset,
16343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    int bit_index) {
16353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bit_index += kSmiTagSize + kSmiShiftSize;
1636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(base::bits::IsPowerOfTwo32(kBitsPerByte));
16373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int byte_index = bit_index / kBitsPerByte;
16383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int byte_bit_index = bit_index & (kBitsPerByte - 1);
16393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test_b(FieldOperand(object, field_offset + byte_index),
16403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch         Immediate(1 << byte_bit_index));
16413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
16423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::NegativeZeroTest(Register result,
1646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register op,
1647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Label* then_label) {
1648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label ok;
16493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(result, result);
1650109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  j(not_zero, &ok, Label::kNear);
16513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(op, op);
1652109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  j(sign, then_label, Label::kNear);
1653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&ok);
1654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::NegativeZeroTest(Register result,
1658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register op1,
1659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register op2,
1660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register scratch,
1661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Label* then_label) {
1662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label ok;
16633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(result, result);
1664109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  j(not_zero, &ok, Label::kNear);
16653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(scratch, op1);
16663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  or_(scratch, op2);
1667109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  j(sign, then_label, Label::kNear);
1668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&ok);
1669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1672014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::GetMapConstructor(Register result, Register map,
1673014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                       Register temp) {
1674014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label done, loop;
1675014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(result, FieldOperand(map, Map::kConstructorOrBackPointerOffset));
1676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&loop);
1677014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  JumpIfSmi(result, &done, Label::kNear);
1678014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CmpObjectType(result, MAP_TYPE, temp);
1679014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_equal, &done, Label::kNear);
1680014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(result, FieldOperand(result, Map::kConstructorOrBackPointerOffset));
1681014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  jmp(&loop);
1682014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&done);
1683014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
16843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CallStub(CodeStub* stub, TypeFeedbackId ast_id) {
1686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(AllowThisStubCall(stub));  // Calls are not allowed in some stubs.
1687257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id);
1688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1691d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::TailCallStub(CodeStub* stub) {
1692d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  jmp(stub->GetCode(), RelocInfo::CODE_TARGET);
1693d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1694d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1695d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
169685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochvoid MacroAssembler::StubReturn(int argc) {
1697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(argc >= 1 && generating_stub());
169885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  ret((argc - 1) * kPointerSize);
1699592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch}
1700592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1701592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
17023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
1703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return has_frame_ || !stub->SometimesSetsUpAFrame();
1704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
170644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CallRuntime(const Runtime::Function* f,
1707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 int num_arguments,
1708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 SaveFPRegsMode save_doubles) {
1709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the expected number of arguments of the runtime function is
1710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // constant, we check that the actual number of arguments match the
1711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // expectation.
1712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(f->nargs < 0 || f->nargs == num_arguments);
1713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // TODO(1236192): Most runtime routines don't need the number of
17154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // arguments passed in because it is constant. At some point we
17164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // should remove this need and make the runtime routine entry code
17174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // smarter.
1718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Move(eax, Immediate(num_arguments));
171944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  mov(ebx, Immediate(ExternalReference(f, isolate())));
1720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CEntryStub ces(isolate(), 1, save_doubles);
17214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  CallStub(&ces);
1722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1725bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid MacroAssembler::CallExternalReference(ExternalReference ref,
1726bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                           int num_arguments) {
1727bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  mov(eax, Immediate(num_arguments));
1728bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  mov(ebx, Immediate(ref));
1729bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CEntryStub stub(isolate(), 1);
1731bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  CallStub(&stub);
1732bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
1733bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1734bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1735014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::TailCallRuntime(Runtime::FunctionId fid) {
1736014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // ----------- S t a t e -------------
1737014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  -- esp[0]                 : return address
1738014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  -- esp[8]                 : argument num_arguments - 1
1739014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  ...
1740014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  -- esp[8 * num_arguments] : argument 0 (receiver)
1741014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //
1742014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  For runtime functions with variable arguments:
1743014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  -- eax                    : number of  arguments
1744014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // -----------------------------------
17453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1746014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const Runtime::Function* function = Runtime::FunctionForId(fid);
1747014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(1, function->result_size);
1748014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (function->nargs >= 0) {
1749014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // TODO(1236192): Most runtime routines don't need the number of
1750014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // arguments passed in because it is constant. At some point we
1751014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // should remove this need and make the runtime routine entry code
1752014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // smarter.
1753014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mov(eax, Immediate(function->nargs));
1754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1755014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  JumpToExternalReference(ExternalReference(fid, isolate()));
1756d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1757d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1758f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MacroAssembler::JumpToExternalReference(const ExternalReference& ext,
1759f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                             bool builtin_exit_frame) {
1760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set the entry point and jump to the C entry runtime stub.
1761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(ebx, Immediate(ext));
1762f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  CEntryStub ces(isolate(), 1, kDontSaveFPRegs, kArgvOnStack,
1763f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                 builtin_exit_frame);
1764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  jmp(ces.GetCode(), RelocInfo::CODE_TARGET);
1765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::PrepareForTailCall(
17683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    const ParameterCount& callee_args_count, Register caller_args_count_reg,
17693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Register scratch0, Register scratch1, ReturnAddressState ra_state,
17703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    int number_of_temp_values_after_return_address) {
17713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#if DEBUG
17723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (callee_args_count.is_reg()) {
17733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(!AreAliased(callee_args_count.reg(), caller_args_count_reg, scratch0,
17743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                       scratch1));
17753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
17763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(!AreAliased(caller_args_count_reg, scratch0, scratch1));
17773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
17783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK(ra_state != ReturnAddressState::kNotOnStack ||
17793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch         number_of_temp_values_after_return_address == 0);
17803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#endif
17813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
17823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Calculate the destination address where we will put the return address
17833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // after we drop current frame.
17843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Register new_sp_reg = scratch0;
17853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (callee_args_count.is_reg()) {
17863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    sub(caller_args_count_reg, callee_args_count.reg());
17873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    lea(new_sp_reg,
17883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Operand(ebp, caller_args_count_reg, times_pointer_size,
17893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                StandardFrameConstants::kCallerPCOffset -
17903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                    number_of_temp_values_after_return_address * kPointerSize));
17913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
17923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    lea(new_sp_reg, Operand(ebp, caller_args_count_reg, times_pointer_size,
17933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                            StandardFrameConstants::kCallerPCOffset -
17943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                (callee_args_count.immediate() +
17953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                 number_of_temp_values_after_return_address) *
17963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                    kPointerSize));
17973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
17983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
17993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (FLAG_debug_code) {
18003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    cmp(esp, new_sp_reg);
18013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Check(below, kStackAccessBelowStackPointer);
18023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
18033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
18043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Copy return address from caller's frame to current frame's return address
18053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // to avoid its trashing and let the following loop copy it to the right
18063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // place.
18073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Register tmp_reg = scratch1;
18083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (ra_state == ReturnAddressState::kOnStack) {
18093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    mov(tmp_reg, Operand(ebp, StandardFrameConstants::kCallerPCOffset));
18103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    mov(Operand(esp, number_of_temp_values_after_return_address * kPointerSize),
18113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        tmp_reg);
18123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
18133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(ReturnAddressState::kNotOnStack == ra_state);
18143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK_EQ(0, number_of_temp_values_after_return_address);
18153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Push(Operand(ebp, StandardFrameConstants::kCallerPCOffset));
18163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
18173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
18183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Restore caller's frame pointer now as it could be overwritten by
18193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // the copying loop.
18203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(ebp, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
18213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
18223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // +2 here is to copy both receiver and return address.
18233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Register count_reg = caller_args_count_reg;
18243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (callee_args_count.is_reg()) {
18253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    lea(count_reg, Operand(callee_args_count.reg(),
18263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                           2 + number_of_temp_values_after_return_address));
18273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
18283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    mov(count_reg, Immediate(callee_args_count.immediate() + 2 +
18293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                             number_of_temp_values_after_return_address));
18303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // TODO(ishell): Unroll copying loop for small immediate values.
18313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
18323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
18333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Now copy callee arguments to the caller frame going backwards to avoid
18343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // callee arguments corruption (source and destination areas could overlap).
18353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label loop, entry;
18363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  jmp(&entry, Label::kNear);
18373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&loop);
18383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  dec(count_reg);
18393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(tmp_reg, Operand(esp, count_reg, times_pointer_size, 0));
18403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(Operand(new_sp_reg, count_reg, times_pointer_size, 0), tmp_reg);
18413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&entry);
18423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  cmp(count_reg, Immediate(0));
18433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  j(not_equal, &loop, Label::kNear);
18443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
18453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Leave current frame.
18463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(esp, new_sp_reg);
18473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
1848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokePrologue(const ParameterCount& expected,
1850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    const ParameterCount& actual,
1851257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Label* done,
18523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    bool* definitely_mismatches,
1853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                    InvokeFlag flag,
1854257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Label::Distance done_near,
1855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const CallWrapper& call_wrapper) {
1856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool definitely_matches = false;
18573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  *definitely_mismatches = false;
1858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label invoke;
1859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (expected.is_immediate()) {
1860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(actual.is_immediate());
1861014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mov(eax, actual.immediate());
1862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (expected.immediate() == actual.immediate()) {
1863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      definitely_matches = true;
1864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
1865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel;
1866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (expected.immediate() == sentinel) {
1867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Don't worry about adapting arguments for builtins that
1868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // don't want that done. Skip adaption code by making it look
1869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // like we have a match between expected and actual number of
1870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // arguments.
1871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        definitely_matches = true;
1872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
18733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        *definitely_mismatches = true;
1874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mov(ebx, expected.immediate());
1875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (actual.is_immediate()) {
1879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Expected is in register, actual is immediate. This is the
1880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // case when we invoke function values without going through the
1881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // IC mechanism.
1882014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      mov(eax, actual.immediate());
1883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      cmp(expected.reg(), actual.immediate());
1884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      j(equal, &invoke);
1885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(expected.reg().is(ebx));
1886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else if (!expected.reg().is(actual.reg())) {
1887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Both expected and actual are in (different) registers. This
1888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // is the case when we invoke functions using call and apply.
18893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      cmp(expected.reg(), actual.reg());
1890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      j(equal, &invoke);
1891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(actual.reg().is(eax));
1892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(expected.reg().is(ebx));
1893014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
189462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      definitely_matches = true;
1895014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Move(eax, actual.reg());
1896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!definitely_matches) {
1900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Handle<Code> adaptor =
190144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        isolate()->builtins()->ArgumentsAdaptorTrampoline();
1902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (flag == CALL_FUNCTION) {
1903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      call_wrapper.BeforeCall(CallSize(adaptor, RelocInfo::CODE_TARGET));
1904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      call(adaptor, RelocInfo::CODE_TARGET);
1905257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      call_wrapper.AfterCall();
19063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (!*definitely_mismatches) {
19073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        jmp(done, done_near);
19083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
1909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
1910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      jmp(adaptor, RelocInfo::CODE_TARGET);
1911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bind(&invoke);
1913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
191662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid MacroAssembler::CheckDebugHook(Register fun, Register new_target,
191762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                    const ParameterCount& expected,
191862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                    const ParameterCount& actual) {
191962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Label skip_hook;
192062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ExternalReference debug_hook_active =
192162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      ExternalReference::debug_hook_on_function_call_address(isolate());
192262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  cmpb(Operand::StaticVariable(debug_hook_active), Immediate(0));
192362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  j(equal, &skip_hook);
1924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  {
1925014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    FrameScope frame(this,
1926014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     has_frame() ? StackFrame::NONE : StackFrame::INTERNAL);
1927014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (expected.is_reg()) {
1928014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SmiTag(expected.reg());
1929014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Push(expected.reg());
1930014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1931014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (actual.is_reg()) {
1932014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SmiTag(actual.reg());
1933014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Push(actual.reg());
1934014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1935014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (new_target.is_valid()) {
1936014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Push(new_target);
1937014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1938014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(fun);
1939014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(fun);
194062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    CallRuntime(Runtime::kDebugOnFunctionCall);
1941014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Pop(fun);
1942014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (new_target.is_valid()) {
1943014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pop(new_target);
1944014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1945014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (actual.is_reg()) {
1946014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pop(actual.reg());
1947014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SmiUntag(actual.reg());
1948014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1949014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (expected.is_reg()) {
1950014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pop(expected.reg());
1951014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SmiUntag(expected.reg());
1952014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1953014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
195462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  bind(&skip_hook);
1955014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1956014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1957014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1958014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::InvokeFunctionCode(Register function, Register new_target,
1959014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        const ParameterCount& expected,
1960014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        const ParameterCount& actual,
1961014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        InvokeFlag flag,
1962014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        const CallWrapper& call_wrapper) {
19633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a function without a valid frame.
1964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(flag == JUMP_FUNCTION || has_frame());
1965014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(function.is(edi));
1966014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_IMPLIES(new_target.is_valid(), new_target.is(edx));
1967014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
196862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (call_wrapper.NeedsDebugHookCheck()) {
196962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    CheckDebugHook(function, new_target, expected, actual);
1970014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1971014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1972014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Clear the new.target register if not given.
1973014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!new_target.is_valid()) {
1974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mov(edx, isolate()->factory()->undefined_value());
1975014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
19763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1977257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
19783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool definitely_mismatches = false;
1979014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InvokePrologue(expected, actual, &done, &definitely_mismatches, flag,
1980014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 Label::kNear, call_wrapper);
19813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!definitely_mismatches) {
1982014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // We call indirectly through the code field in the function to
1983014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // allow recompilation to take effect without changing any of the
1984014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // call sites.
1985014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Operand code = FieldOperand(function, JSFunction::kCodeEntryOffset);
19863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (flag == CALL_FUNCTION) {
19873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call_wrapper.BeforeCall(CallSize(code));
19883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call(code);
19893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call_wrapper.AfterCall();
19903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
1991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(flag == JUMP_FUNCTION);
19923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      jmp(code);
19933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
19943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&done);
1995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeFunction(Register fun,
2000014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    Register new_target,
2001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    const ParameterCount& actual,
2002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                    InvokeFlag flag,
2003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const CallWrapper& call_wrapper) {
20043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a function without a valid frame.
2005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(flag == JUMP_FUNCTION || has_frame());
20063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(fun.is(edi));
2008014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
2009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
2010014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kFormalParameterCountOffset));
20117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  SmiUntag(ebx);
2012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ParameterCount expected(ebx);
2014014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InvokeFunctionCode(edi, new_target, expected, actual, flag, call_wrapper);
2015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::InvokeFunction(Register fun,
2019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const ParameterCount& expected,
2020402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                    const ParameterCount& actual,
2021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                    InvokeFlag flag,
2022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const CallWrapper& call_wrapper) {
20233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a function without a valid frame.
2024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(flag == JUMP_FUNCTION || has_frame());
20253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(fun.is(edi));
2027402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
2028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2029014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InvokeFunctionCode(edi, no_reg, expected, actual, flag, call_wrapper);
2030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::InvokeFunction(Handle<JSFunction> function,
2034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const ParameterCount& expected,
2035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const ParameterCount& actual,
2036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    InvokeFlag flag,
2037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const CallWrapper& call_wrapper) {
2038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LoadHeapObject(edi, function);
2039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InvokeFunction(edi, expected, actual, flag, call_wrapper);
2040402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
2041402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2043d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::LoadContext(Register dst, int context_chain_length) {
2044d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (context_chain_length > 0) {
2045d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Move up the chain of contexts to the context containing the slot.
20463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    mov(dst, Operand(esi, Context::SlotOffset(Context::PREVIOUS_INDEX)));
2047d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    for (int i = 1; i < context_chain_length; i++) {
20483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      mov(dst, Operand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX)));
2049d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
20501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
20511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Slot is in the current function context.  Move it into the
20521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // destination register in case we store into it (the write barrier
20531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // cannot be allowed to destroy the context in esi).
20541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    mov(dst, esi);
20551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
20561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
20573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // We should not have found a with context by walking the context chain
20581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // (i.e., the static scope chain and runtime context chain do not agree).
20591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // A variable occurring in such a scope should have slot type LOOKUP and
20601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // not CONTEXT.
206144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
20623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    cmp(FieldOperand(dst, HeapObject::kMapOffset),
20633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        isolate()->factory()->with_context_map());
2064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kVariableResolvedToWithContext);
2065d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2066d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2067d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2068d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2069014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LoadGlobalProxy(Register dst) {
2070014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(dst, NativeContextOperand());
2071014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(dst, ContextOperand(dst, Context::GLOBAL_PROXY_INDEX));
2072014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2073014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
207480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::LoadGlobalFunction(int index, Register function) {
2075014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Load the native context from the current context.
2076014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(function, NativeContextOperand());
2077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the function from the native context.
2078014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(function, ContextOperand(function, index));
207980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
208080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
208180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
208280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
208380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                                  Register map) {
208480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Load the initial map.  The global functions all have initial maps.
208580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  mov(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
208644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
208780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Label ok, fail;
2088257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CheckMap(map, isolate()->factory()->meta_map(), &fail, DO_SMI_CHECK);
208980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    jmp(&ok);
209080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    bind(&fail);
2091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Abort(kGlobalFunctionsMustHaveInitialMap);
209280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    bind(&ok);
209380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
209480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
209580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2096d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2097e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Store the value in register src in the safepoint register stack
2098e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// slot for register dst.
2099e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Register src) {
2100e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  mov(SafepointRegisterSlot(dst), src);
2101e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2102e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2103e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2104e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Immediate src) {
2105e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  mov(SafepointRegisterSlot(dst), src);
2106e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2107e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2108e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2109e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) {
2110e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  mov(dst, SafepointRegisterSlot(src));
2111e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2112e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2113e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2114e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochOperand MacroAssembler::SafepointRegisterSlot(Register reg) {
2115e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return Operand(esp, SafepointRegisterStackIndex(reg.code()) * kPointerSize);
2116e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2117e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2118e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochint MacroAssembler::SafepointRegisterStackIndex(int reg_code) {
2120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The registers are pushed starting with the lowest encoding,
2121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // which means that lowest encodings are furthest away from
2122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // the stack pointer.
2123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(reg_code >= 0 && reg_code < kNumSafepointRegisters);
2124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return kNumSafepointRegisters - reg_code - 1;
2125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
21283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::LoadHeapObject(Register result,
21293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    Handle<HeapObject> object) {
2130f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  mov(result, object);
21313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
21323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CmpHeapObject(Register reg, Handle<HeapObject> object) {
2135f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  cmp(reg, object);
21363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
21373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2138f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MacroAssembler::PushHeapObject(Handle<HeapObject> object) { Push(object); }
21393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2140958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::CmpWeakValue(Register value, Handle<WeakCell> cell,
2141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                  Register scratch) {
2142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  mov(scratch, cell);
2143958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  cmp(value, FieldOperand(scratch, WeakCell::kValueOffset));
2144958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2145958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2146958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::GetWeakValue(Register value, Handle<WeakCell> cell) {
2148958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  mov(value, cell);
2149958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  mov(value, FieldOperand(value, WeakCell::kValueOffset));
2150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LoadWeakValue(Register value, Handle<WeakCell> cell,
2154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                   Label* miss) {
2155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GetWeakValue(value, cell);
2156958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  JumpIfSmi(value, miss);
2157958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2158958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2159958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Ret() {
2161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ret(0);
2162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::Ret(int bytes_dropped, Register scratch) {
21661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (is_uint16(bytes_dropped)) {
21671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ret(bytes_dropped);
21681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
21691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    pop(scratch);
21703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    add(esp, Immediate(bytes_dropped));
21711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    push(scratch);
21721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ret(0);
21731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
21741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
21751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
21761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2177e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::Drop(int stack_elements) {
2178e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (stack_elements > 0) {
21793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    add(esp, Immediate(stack_elements * kPointerSize));
2180e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2181e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
2182e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2183e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
21840d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::Move(Register dst, Register src) {
21850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (!dst.is(src)) {
21860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    mov(dst, src);
21870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
21880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
21890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
21900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
2191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Move(Register dst, const Immediate& x) {
219213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (x.is_zero() && RelocInfo::IsNone(x.rmode_)) {
2193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    xor_(dst, dst);  // Shorter than mov of 32-bit immediate 0.
2194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(dst, x);
2196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Move(const Operand& dst, const Immediate& x) {
2201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(dst, x);
2202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2205958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::Move(XMMRegister dst, uint32_t src) {
2206958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (src == 0) {
2207958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    pxor(dst, dst);
2208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2209958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    unsigned cnt = base::bits::CountPopulation32(src);
2210958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    unsigned nlz = base::bits::CountLeadingZeros32(src);
2211958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    unsigned ntz = base::bits::CountTrailingZeros32(src);
2212958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (nlz + cnt + ntz == 32) {
2213958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      pcmpeqd(dst, dst);
2214958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (ntz == 0) {
2215958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        psrld(dst, 32 - cnt);
2216958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      } else {
2217958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        pslld(dst, 32 - cnt);
2218958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        if (nlz != 0) psrld(dst, nlz);
2219958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
2220958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
2221958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      push(eax);
2222958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      mov(eax, Immediate(src));
2223958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      movd(dst, Operand(eax));
2224958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      pop(eax);
2225958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
2226958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
2227958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2228958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2229958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2230958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::Move(XMMRegister dst, uint64_t src) {
2231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (src == 0) {
2232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    pxor(dst, dst);
2233958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
2234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    uint32_t lower = static_cast<uint32_t>(src);
2235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    uint32_t upper = static_cast<uint32_t>(src >> 32);
2236958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    unsigned cnt = base::bits::CountPopulation64(src);
2237958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    unsigned nlz = base::bits::CountLeadingZeros64(src);
2238958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    unsigned ntz = base::bits::CountTrailingZeros64(src);
2239958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (nlz + cnt + ntz == 64) {
2240958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      pcmpeqd(dst, dst);
2241958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (ntz == 0) {
2242958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        psrlq(dst, 64 - cnt);
2243958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      } else {
2244958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        psllq(dst, 64 - cnt);
2245958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        if (nlz != 0) psrlq(dst, nlz);
2246958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
2247958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else if (lower == 0) {
2248958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Move(dst, upper);
2249958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      psllq(dst, 32);
2250958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else if (CpuFeatures::IsSupported(SSE4_1)) {
2251958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      CpuFeatureScope scope(this, SSE4_1);
2252958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      push(eax);
2253958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Move(eax, Immediate(lower));
2254958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      movd(dst, Operand(eax));
2255958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Move(eax, Immediate(upper));
2256958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      pinsrd(dst, Operand(eax), 1);
2257958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      pop(eax);
2258958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
2259958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      push(Immediate(upper));
2260958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      push(Immediate(lower));
2261958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      movsd(dst, Operand(esp, 0));
2262958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      add(esp, Immediate(kDoubleSize));
2263958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
2264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Pextrd(Register dst, XMMRegister src, int8_t imm8) {
2269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (imm8 == 0) {
2270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movd(dst, src);
2271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
2272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(1, imm8);
2274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(SSE4_1)) {
2275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope sse_scope(this, SSE4_1);
2276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    pextrd(dst, src, imm8);
2277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
2278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  pshufd(xmm0, src, 1);
2280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movd(dst, xmm0);
2281014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2284014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Pinsrd(XMMRegister dst, const Operand& src, int8_t imm8) {
2285014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(imm8 == 0 || imm8 == 1);
2286014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(SSE4_1)) {
2287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope sse_scope(this, SSE4_1);
2288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    pinsrd(dst, src, imm8);
2289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
2290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2291014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movd(xmm0, src);
2292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (imm8 == 1) {
2293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    punpckldq(dst, xmm0);
2294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2295014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK_EQ(0, imm8);
2296014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    psrlq(dst, 32);
2297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    punpckldq(xmm0, dst);
2298014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movaps(dst, xmm0);
2299014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2300014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2301014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2302014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2303014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Lzcnt(Register dst, const Operand& src) {
2304014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(LZCNT)) {
2305014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, LZCNT);
2306014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    lzcnt(dst, src);
2307014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
2308014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2309014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label not_zero_src;
2310014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bsr(dst, src);
2311014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_zero, &not_zero_src, Label::kNear);
2312014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Move(dst, Immediate(63));  // 63^31 == 32
2313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&not_zero_src);
2314014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  xor_(dst, Immediate(31));  // for x in [0..31], 31^x == 31-x.
2315014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2316014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2317014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2318014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Tzcnt(Register dst, const Operand& src) {
2319014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(BMI1)) {
2320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, BMI1);
2321014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    tzcnt(dst, src);
2322014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
2323014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2324014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label not_zero_src;
2325014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bsf(dst, src);
2326014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_zero, &not_zero_src, Label::kNear);
2327014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Move(dst, Immediate(32));  // The result of tzcnt is 32 if src = 0.
2328014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&not_zero_src);
2329014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2330014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2331014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2332014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Popcnt(Register dst, const Operand& src) {
2333014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(POPCNT)) {
2334014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, POPCNT);
2335014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    popcnt(dst, src);
2336014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
2337014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2338014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  UNREACHABLE();
2339014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2340014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2341014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SetCounter(StatsCounter* counter, int value) {
2343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
2344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(Operand::StaticVariable(ExternalReference(counter)), Immediate(value));
2345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::IncrementCounter(StatsCounter* counter, int value) {
2350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(value > 0);
2351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
2352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Operand operand = Operand::StaticVariable(ExternalReference(counter));
2353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (value == 1) {
2354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      inc(operand);
2355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
2356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      add(operand, Immediate(value));
2357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::DecrementCounter(StatsCounter* counter, int value) {
2363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(value > 0);
2364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
2365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Operand operand = Operand::StaticVariable(ExternalReference(counter));
2366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (value == 1) {
2367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      dec(operand);
2368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
2369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      sub(operand, Immediate(value));
2370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2375d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid MacroAssembler::IncrementCounter(Condition cc,
2376d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                      StatsCounter* counter,
2377d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                      int value) {
2378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(value > 0);
2379d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (FLAG_native_code_counters && counter->Enabled()) {
2380d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Label skip;
2381d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    j(NegateCondition(cc), &skip);
2382d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    pushfd();
2383d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    IncrementCounter(counter, value);
2384d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    popfd();
2385d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    bind(&skip);
2386d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
2387d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
2388d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2389d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2390d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid MacroAssembler::DecrementCounter(Condition cc,
2391d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                      StatsCounter* counter,
2392d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                      int value) {
2393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(value > 0);
2394d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (FLAG_native_code_counters && counter->Enabled()) {
2395d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Label skip;
2396d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    j(NegateCondition(cc), &skip);
2397d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    pushfd();
2398d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    DecrementCounter(counter, value);
2399d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    popfd();
2400d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    bind(&skip);
2401d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
2402d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
2403d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2404d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Assert(Condition cc, BailoutReason reason) {
2406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) Check(cc, reason);
2407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2410756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid MacroAssembler::AssertFastElements(Register elements) {
241144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
241244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Factory* factory = isolate()->factory();
2413756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Label ok;
2414756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    cmp(FieldOperand(elements, HeapObject::kMapOffset),
241544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Immediate(factory->fixed_array_map()));
2416756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    j(equal, &ok);
2417756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    cmp(FieldOperand(elements, HeapObject::kMapOffset),
24183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        Immediate(factory->fixed_double_array_map()));
24193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    j(equal, &ok);
24203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    cmp(FieldOperand(elements, HeapObject::kMapOffset),
242144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Immediate(factory->fixed_cow_array_map()));
2422756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    j(equal, &ok);
2423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Abort(kJSObjectWithFastElementsMapHasSlowElements);
2424756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    bind(&ok);
2425756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
2426756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
2427756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2428756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Check(Condition cc, BailoutReason reason) {
2430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label L;
2431257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(cc, &L);
2432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Abort(reason);
2433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // will not return here
2434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&L);
2435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24386ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::CheckStackAlignment() {
2439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int frame_alignment = base::OS::ActivationFrameAlignment();
24406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int frame_alignment_mask = frame_alignment - 1;
24416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (frame_alignment > kPointerSize) {
2442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
24436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Label alignment_as_expected;
24446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    test(esp, Immediate(frame_alignment_mask));
24456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    j(zero, &alignment_as_expected);
24466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Abort if stack is not aligned.
24476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int3();
24486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    bind(&alignment_as_expected);
24496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
24506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
24516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
24526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Abort(BailoutReason reason) {
2454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* msg = GetBailoutReason(reason);
2456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (msg != NULL) {
2457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RecordComment("Abort message: ");
2458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RecordComment(msg);
2459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_trap_on_abort) {
2462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int3();
2463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
2464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2466d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2467f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Check if Abort() has already been initialized.
2468f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(isolate()->builtins()->Abort()->IsHeapObject());
2469f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2470f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Move(edx, Smi::FromInt(static_cast<int>(reason)));
2471f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
24723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Disable stub call restrictions to always allow calls to abort.
24733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!has_frame_) {
24743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // We don't actually want to generate a pile of code for this, so just
24753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // claim there is a stack frame, without generating one.
24763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(this, StackFrame::NONE);
2477f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Call(isolate()->builtins()->Abort(), RelocInfo::CODE_TARGET);
24783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
2479f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Call(isolate()->builtins()->Abort(), RelocInfo::CODE_TARGET);
24803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // will not return here
2482d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int3();
2483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::LoadInstanceDescriptors(Register map,
2487257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Register descriptors) {
2488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(descriptors, FieldOperand(map, Map::kDescriptorsOffset));
2489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) {
2493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(dst, FieldOperand(map, Map::kBitField3Offset));
2494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DecodeField<Map::NumberOfOwnDescriptorsBits>(dst);
2495756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
2496756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2497756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2498014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LoadAccessor(Register dst, Register holder,
2499014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  int accessor_index,
2500014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  AccessorComponent accessor) {
2501014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(dst, FieldOperand(holder, HeapObject::kMapOffset));
2502014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LoadInstanceDescriptors(dst, dst);
2503014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(dst, FieldOperand(dst, DescriptorArray::GetValueOffset(accessor_index)));
2504014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int offset = accessor == ACCESSOR_GETTER ? AccessorPair::kGetterOffset
2505014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                           : AccessorPair::kSetterOffset;
2506014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(dst, FieldOperand(dst, offset));
2507014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2508014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2509014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
25100d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::LoadPowerOf2(XMMRegister dst,
25110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                  Register scratch,
25120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                  int power) {
2513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uintn(power + HeapNumber::kExponentBias,
25140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                  HeapNumber::kExponentBits));
25150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  mov(scratch, Immediate(power + HeapNumber::kExponentBias));
25163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movd(dst, scratch);
25170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  psllq(dst, HeapNumber::kMantissaBits);
25180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
25190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
2520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfNotBothSequentialOneByteStrings(Register object1,
2521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                           Register object2,
2522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                           Register scratch1,
2523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                           Register scratch2,
2524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                           Label* failure) {
2525d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Check that both objects are not smis.
252669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
25273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(scratch1, object1);
25283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(scratch1, object2);
25293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  JumpIfSmi(scratch1, failure);
2530d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2531d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Load instance type for both strings.
2532d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  mov(scratch1, FieldOperand(object1, HeapObject::kMapOffset));
2533d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  mov(scratch2, FieldOperand(object2, HeapObject::kMapOffset));
2534d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  movzx_b(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset));
2535d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  movzx_b(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset));
2536d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that both are flat one-byte strings.
2538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kFlatOneByteStringMask =
2539d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
2540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kFlatOneByteStringTag =
2541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kStringTag | kOneByteStringTag | kSeqStringTag;
2542d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Interleave bits from both instance types and compare them in one check.
254362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  const int kShift = 8;
254462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(0, kFlatOneByteStringMask & (kFlatOneByteStringMask << kShift));
2545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  and_(scratch1, kFlatOneByteStringMask);
2546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  and_(scratch2, kFlatOneByteStringMask);
254762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  shl(scratch2, kShift);
254862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  or_(scratch1, scratch2);
254962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  cmp(scratch1, kFlatOneByteStringTag | (kFlatOneByteStringTag << kShift));
2550d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  j(not_equal, failure);
2551d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
2552d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2553d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfNotUniqueNameInstanceType(Operand operand,
2555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                     Label* not_unique_name,
2556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                     Label::Distance distance) {
2557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
2558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label succeed;
2559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  test(operand, Immediate(kIsNotStringMask | kIsNotInternalizedMask));
2560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(zero, &succeed);
25613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  cmpb(operand, Immediate(SYMBOL_TYPE));
2562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(not_equal, not_unique_name, distance);
2563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&succeed);
2565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::EmitSeqStringSetCharCheck(Register string,
2569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register index,
2570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register value,
2571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               uint32_t encoding_mask) {
2572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label is_object;
2573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JumpIfNotSmi(string, &is_object, Label::kNear);
2574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Abort(kNonObject);
2575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&is_object);
2576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  push(value);
2578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(value, FieldOperand(string, HeapObject::kMapOffset));
2579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movzx_b(value, FieldOperand(value, Map::kInstanceTypeOffset));
2580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  and_(value, Immediate(kStringRepresentationMask | kStringEncodingMask));
2582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(value, Immediate(encoding_mask));
2583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pop(value);
2584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(equal, kUnexpectedStringType);
2585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The index is assumed to be untagged coming in, tag it to compare with the
2587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // string length without using a temp register, it is restored at the end of
2588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // this function.
2589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiTag(index);
2590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(no_overflow, kIndexIsTooLarge);
2591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(index, FieldOperand(string, String::kLengthOffset));
2593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(less, kIndexIsTooLarge);
2594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2595c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  cmp(index, Immediate(Smi::kZero));
2596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(greater_equal, kIndexIsNegative);
2597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Restore the index
2599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiUntag(index);
2600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
26036ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::PrepareCallCFunction(int num_arguments, Register scratch) {
2604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int frame_alignment = base::OS::ActivationFrameAlignment();
26058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (frame_alignment != 0) {
26066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Make stack end at alignment and make room for num_arguments words
26076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // and the original value of esp.
26086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    mov(scratch, esp);
26093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sub(esp, Immediate((num_arguments + 1) * kPointerSize));
2610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
26118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    and_(esp, -frame_alignment);
26126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    mov(Operand(esp, num_arguments * kPointerSize), scratch);
26136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
26143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sub(esp, Immediate(num_arguments * kPointerSize));
26156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
26166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
26176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
26186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
26196ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::CallCFunction(ExternalReference function,
26206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                   int num_arguments) {
26216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Trashing eax is ok as it will be the return value.
26223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(eax, Immediate(function));
26236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CallCFunction(eax, num_arguments);
26246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
26256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
26266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
26276ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::CallCFunction(Register function,
26286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                   int num_arguments) {
2629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(has_frame());
26306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check stack alignment.
263144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
26326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CheckStackAlignment();
26336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
26346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
26353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  call(function);
2636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (base::OS::ActivationFrameAlignment() != 0) {
26376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    mov(esp, Operand(esp, num_arguments * kPointerSize));
26386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
26393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    add(esp, Immediate(num_arguments * kPointerSize));
26406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
26416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
26426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
26436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
2645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool AreAliased(Register reg1,
2646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg2,
2647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg3,
2648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg4,
2649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg5,
2650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg6,
2651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg7,
2652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg8) {
2653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int n_of_valid_regs = reg1.is_valid() + reg2.is_valid() +
2654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reg3.is_valid() + reg4.is_valid() + reg5.is_valid() + reg6.is_valid() +
2655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reg7.is_valid() + reg8.is_valid();
2656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RegList regs = 0;
2658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg1.is_valid()) regs |= reg1.bit();
2659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg2.is_valid()) regs |= reg2.bit();
2660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg3.is_valid()) regs |= reg3.bit();
2661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg4.is_valid()) regs |= reg4.bit();
2662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg5.is_valid()) regs |= reg5.bit();
2663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg6.is_valid()) regs |= reg6.bit();
2664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg7.is_valid()) regs |= reg7.bit();
2665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg8.is_valid()) regs |= reg8.bit();
2666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int n_of_non_aliasing_regs = NumRegs(regs);
2667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return n_of_valid_regs != n_of_non_aliasing_regs;
26693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
2670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
26713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2673014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochCodePatcher::CodePatcher(Isolate* isolate, byte* address, int size)
26748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    : address_(address),
26758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      size_(size),
2676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      masm_(isolate, address, size + Assembler::kGap, CodeObjectRequired::kNo) {
2677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a new macro assembler pointing to the address of the code to patch.
2678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The size is adjusted with kGap on order for the assembler to generate size
2679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // bytes of instructions without failing with buffer size constraints.
2680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
2681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCodePatcher::~CodePatcher() {
2685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Indicate that code has changed.
2686014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Assembler::FlushICache(masm_.isolate(), address_, size_);
2687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the code was patched as expected.
2689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(masm_.pc_ == address_ + size_);
2690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
2691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckPageFlag(
26953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register object,
26963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch,
26973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int mask,
26983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Condition cc,
26993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* condition_met,
27003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label::Distance condition_met_distance) {
2701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(cc == zero || cc == not_zero);
27023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (scratch.is(object)) {
27033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    and_(scratch, Immediate(~Page::kPageAlignmentMask));
27043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
27053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(scratch, Immediate(~Page::kPageAlignmentMask));
27063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    and_(scratch, object);
27073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
27083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (mask < (1 << kBitsPerByte)) {
27093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    test_b(Operand(scratch, MemoryChunk::kFlagsOffset), Immediate(mask));
27103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
27113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    test(Operand(scratch, MemoryChunk::kFlagsOffset), Immediate(mask));
27123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
27133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(cc, condition_met, condition_met_distance);
27143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
27153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CheckPageFlagForMap(
2718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Map> map,
2719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int mask,
2720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Condition cc,
2721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label* condition_met,
2722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label::Distance condition_met_distance) {
2723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(cc == zero || cc == not_zero);
2724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Page* page = Page::FromAddress(map->address());
2725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!serializer_enabled());  // Serializer cannot match page_flags.
2726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference reference(ExternalReference::page_flags(page));
2727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The inlined static address check of the page's flags relies
2728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // on maps never being compacted.
2729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!isolate()->heap()->mark_compact_collector()->
2730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         IsOnEvacuationCandidate(*map));
2731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (mask < (1 << kBitsPerByte)) {
27323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    test_b(Operand::StaticVariable(reference), Immediate(mask));
2733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(Operand::StaticVariable(reference), Immediate(mask));
2735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(cc, condition_met, condition_met_distance);
2737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
27403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::JumpIfBlack(Register object,
27413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register scratch0,
27423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register scratch1,
27433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Label* on_black,
27443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Label::Distance on_black_near) {
2745014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  HasColor(object, scratch0, scratch1, on_black, on_black_near, 1,
2746014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch           1);  // kBlackBitPattern.
2747014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0);
27483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
27493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::HasColor(Register object,
27523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Register bitmap_scratch,
27533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Register mask_scratch,
27543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Label* has_color,
27553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Label::Distance has_color_distance,
27563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              int first_bit,
27573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              int second_bit) {
2758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(object, bitmap_scratch, mask_scratch, ecx));
27593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GetMarkBits(object, bitmap_scratch, mask_scratch);
27613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label other_color, word_boundary;
27633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
27643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(first_bit == 1 ? zero : not_zero, &other_color, Label::kNear);
27653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(mask_scratch, mask_scratch);  // Shift left 1 by adding.
27663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(zero, &word_boundary, Label::kNear);
27673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
27683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(second_bit == 1 ? not_zero : zero, has_color, has_color_distance);
27693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  jmp(&other_color, Label::kNear);
27703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&word_boundary);
27723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test_b(Operand(bitmap_scratch, MemoryChunk::kHeaderSize + kPointerSize),
27733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch         Immediate(1));
27743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(second_bit == 1 ? not_zero : zero, has_color, has_color_distance);
27763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&other_color);
27773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
27783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::GetMarkBits(Register addr_reg,
27813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register bitmap_reg,
27823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register mask_reg) {
2783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(addr_reg, mask_reg, bitmap_reg, ecx));
27843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(bitmap_reg, Immediate(~Page::kPageAlignmentMask));
27853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(bitmap_reg, addr_reg);
27863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(ecx, addr_reg);
27873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int shift =
27883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Bitmap::kBitsPerCellLog2 + kPointerSizeLog2 - Bitmap::kBytesPerCellLog2;
27893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  shr(ecx, shift);
27903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(ecx,
27913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       (Page::kPageAlignmentMask >> shift) & ~(Bitmap::kBytesPerCell - 1));
27923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(bitmap_reg, ecx);
27943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(ecx, addr_reg);
27953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  shr(ecx, kPointerSizeLog2);
27963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(ecx, (1 << Bitmap::kBitsPerCellLog2) - 1);
27973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(mask_reg, Immediate(1));
27983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  shl_cl(mask_reg);
27993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
28003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2802014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::JumpIfWhite(Register value, Register bitmap_scratch,
2803014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 Register mask_scratch, Label* value_is_white,
2804014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 Label::Distance distance) {
2805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(value, bitmap_scratch, mask_scratch, ecx));
28063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GetMarkBits(value, bitmap_scratch, mask_scratch);
28073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If the value is black or grey we don't need to do anything.
2809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0);
2810014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0);
2811014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(strcmp(Marking::kGreyBitPattern, "10") == 0);
2812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0);
28133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Since both black and grey have a 1 in the first position and white does
28153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // not have a 1 there we only need to check one bit.
28163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
2817014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(zero, value_is_white, Label::kNear);
28183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
28193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::EnumLength(Register dst, Register map) {
2822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(Map::EnumLengthBits::kShift == 0);
2823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(dst, FieldOperand(map, Map::kBitField3Offset));
2824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  and_(dst, Immediate(Map::EnumLengthBits::kMask));
2825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiTag(dst);
2826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
28293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckEnumCache(Label* call_runtime) {
2830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label next, start;
28313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(ecx, eax);
2832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check if the enum length field is properly initialized, indicating that
2834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // there is an enum cache.
2835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset));
2836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EnumLength(edx, ebx);
2838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(edx, Immediate(Smi::FromInt(kInvalidEnumCacheSentinel)));
2839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(equal, call_runtime);
2840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  jmp(&start);
2842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
28433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&next);
2844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset));
28453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // For all objects but the receiver, check that the cache is empty.
2847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EnumLength(edx, ebx);
2848c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  cmp(edx, Immediate(Smi::kZero));
28493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_equal, call_runtime);
28503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&start);
28523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that there are no elements. Register rcx contains the current JS
2854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // object we've reached through the prototype chain.
2855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label no_elements;
2856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset));
2857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(ecx, isolate()->factory()->empty_fixed_array());
2858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(equal, &no_elements);
28593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Second chance, the object may be using the empty slow element dictionary.
2861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(ecx, isolate()->factory()->empty_slow_element_dictionary());
28623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_equal, call_runtime);
28633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&no_elements);
28653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset));
28663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmp(ecx, isolate()->factory()->null_value());
28673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_equal, &next);
28683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
28693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TestJSArrayForAllocationMemento(
2872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register receiver_reg,
2873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch_reg,
2874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label* no_memento_found) {
28753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label map_check;
28763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label top_check;
2877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference new_space_allocation_top =
2878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::new_space_allocation_top_address(isolate());
28793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  const int kMementoMapOffset = JSArray::kSize - kHeapObjectTag;
2880c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  const int kMementoLastWordOffset =
2881c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      kMementoMapOffset + AllocationMemento::kSize - kPointerSize;
28823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
28833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Bail out if the object is not in new space.
28843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  JumpIfNotInNewSpace(receiver_reg, scratch_reg, no_memento_found);
28853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // If the object is in new space, we need to check whether it is on the same
28863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // page as the current top.
2887c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  lea(scratch_reg, Operand(receiver_reg, kMementoLastWordOffset));
28883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  xor_(scratch_reg, Operand::StaticVariable(new_space_allocation_top));
28893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test(scratch_reg, Immediate(~Page::kPageAlignmentMask));
28903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  j(zero, &top_check);
28913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // The object is on a different page than allocation top. Bail out if the
28923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // object sits on the page boundary as no memento can follow and we cannot
28933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // touch the memory following it.
2894c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  lea(scratch_reg, Operand(receiver_reg, kMementoLastWordOffset));
28953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  xor_(scratch_reg, receiver_reg);
28963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test(scratch_reg, Immediate(~Page::kPageAlignmentMask));
28973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  j(not_zero, no_memento_found);
28983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Continue with the actual map check.
28993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  jmp(&map_check);
29003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // If top is on the same page as the current object, we need to check whether
29013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // we are below top.
29023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&top_check);
2903c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  lea(scratch_reg, Operand(receiver_reg, kMementoLastWordOffset));
2904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(scratch_reg, Operand::StaticVariable(new_space_allocation_top));
2905c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  j(greater_equal, no_memento_found);
29063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Memento map check.
29073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&map_check);
29083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(scratch_reg, Operand(receiver_reg, kMementoMapOffset));
29093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  cmp(scratch_reg, Immediate(isolate()->factory()->allocation_memento_map()));
2910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TruncatingDiv(Register dividend, int32_t divisor) {
2913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dividend.is(eax));
2914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dividend.is(edx));
2915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::MagicNumbersForDivision<uint32_t> mag =
2916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      base::SignedDivisionByConstant(static_cast<uint32_t>(divisor));
2917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(eax, Immediate(mag.multiplier));
2918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  imul(dividend);
2919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool neg = (mag.multiplier & (static_cast<uint32_t>(1) << 31)) != 0;
2920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor > 0 && neg) add(edx, dividend);
2921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor < 0 && !neg && mag.multiplier > 0) sub(edx, dividend);
2922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (mag.shift > 0) sar(edx, mag.shift);
2923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(eax, dividend);
2924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shr(eax, 31);
2925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  add(edx, eax);
2926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2929014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
2930014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
2931f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2932f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_IA32
2933