macro-assembler-ia32.cc revision bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8
13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_IA32
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/bits.h"
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/division-by-constant.h"
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/bootstrapper.h"
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h"
11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/debug/debug.h"
12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/ia32/frames-ia32.h"
13014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/ia32/macro-assembler-ia32.h"
14958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/runtime/runtime.h"
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -------------------------------------------------------------------------
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// MacroAssembler implementation.
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochMacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size,
23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                               CodeObjectRequired create_code_object)
248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    : Assembler(arg_isolate, buffer, size),
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      generating_stub_(false),
263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      has_frame_(false) {
27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (create_code_object == CodeObjectRequired::kYes) {
28014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    code_object_ =
29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Handle<Object>::New(isolate()->heap()->undefined_value(), isolate());
308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Load(Register dst, const Operand& src, Representation r) {
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!r.IsDouble());
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (r.IsInteger8()) {
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movsx_b(dst, src);
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsUInteger8()) {
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movzx_b(dst, src);
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsInteger16()) {
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movsx_w(dst, src);
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsUInteger16()) {
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movzx_w(dst, src);
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(dst, src);
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Store(Register src, const Operand& dst, Representation r) {
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!r.IsDouble());
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (r.IsInteger8() || r.IsUInteger8()) {
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov_b(dst, src);
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsInteger16() || r.IsUInteger16()) {
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov_w(dst, src);
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (r.IsHeapObject()) {
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AssertNotSmi(src);
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (r.IsSmi()) {
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AssertSmi(src);
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(dst, src);
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index) {
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (isolate()->heap()->RootCanBeTreatedAsConstant(index)) {
69014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mov(destination, isolate()->heap()->root_handle(index));
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference roots_array_start =
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::roots_array_start(isolate());
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(destination, Immediate(index));
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(destination, Operand::StaticArray(destination,
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        times_pointer_size,
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        roots_array_start));
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::StoreRoot(Register source,
82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Register scratch,
83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Heap::RootListIndex index) {
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(Heap::RootCanBeWrittenAfterInitialization(index));
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference roots_array_start =
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::roots_array_start(isolate());
87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(scratch, Immediate(index));
88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(Operand::StaticArray(scratch, times_pointer_size, roots_array_start),
89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      source);
90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CompareRoot(Register with,
94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Register scratch,
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Heap::RootListIndex index) {
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference roots_array_start =
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::roots_array_start(isolate());
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(scratch, Immediate(index));
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(with, Operand::StaticArray(scratch,
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                times_pointer_size,
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                roots_array_start));
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) {
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(isolate()->heap()->RootCanBeTreatedAsConstant(index));
107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  cmp(with, isolate()->heap()->root_handle(index));
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CompareRoot(const Operand& with,
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Heap::RootListIndex index) {
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(isolate()->heap()->RootCanBeTreatedAsConstant(index));
114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  cmp(with, isolate()->heap()->root_handle(index));
115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::PushRoot(Heap::RootListIndex index) {
119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(isolate()->heap()->RootCanBeTreatedAsConstant(index));
120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Push(isolate()->heap()->root_handle(index));
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
123109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#define REG(Name) \
124109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  { Register::kCode_##Name }
125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
126109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochstatic const Register saved_regs[] = {REG(eax), REG(ecx), REG(edx)};
127109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
128109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#undef REG
129109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
130109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochstatic const int kNumberOfSavedRegs = sizeof(saved_regs) / sizeof(Register);
131109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
132109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::PushCallerSaved(SaveFPRegsMode fp_mode,
133109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                     Register exclusion1, Register exclusion2,
134109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                     Register exclusion3) {
135109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // We don't allow a GC during a store buffer overflow so there is no need to
136109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // store the registers in any particular way, but we do have to store and
137109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // restore them.
138109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  for (int i = 0; i < kNumberOfSavedRegs; i++) {
139109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Register reg = saved_regs[i];
140109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    if (!reg.is(exclusion1) && !reg.is(exclusion2) && !reg.is(exclusion3)) {
141109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      push(reg);
142109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
143109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
144109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (fp_mode == kSaveFPRegs) {
145109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    sub(esp, Immediate(kDoubleSize * (XMMRegister::kMaxNumRegisters - 1)));
146109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // Save all XMM registers except XMM0.
147109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    for (int i = XMMRegister::kMaxNumRegisters - 1; i > 0; i--) {
148109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      XMMRegister reg = XMMRegister::from_code(i);
149109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      movsd(Operand(esp, (i - 1) * kDoubleSize), reg);
150109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
151109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
152109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
153109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
154109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
155109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                    Register exclusion2, Register exclusion3) {
156109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (fp_mode == kSaveFPRegs) {
157109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // Restore all XMM registers except XMM0.
158109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    for (int i = XMMRegister::kMaxNumRegisters - 1; i > 0; i--) {
159109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      XMMRegister reg = XMMRegister::from_code(i);
160109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      movsd(reg, Operand(esp, (i - 1) * kDoubleSize));
161109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
162109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    add(esp, Immediate(kDoubleSize * (XMMRegister::kMaxNumRegisters - 1)));
163109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
164109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
165109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  for (int i = kNumberOfSavedRegs - 1; i >= 0; i--) {
166109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Register reg = saved_regs[i];
167109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    if (!reg.is(exclusion1) && !reg.is(exclusion2) && !reg.is(exclusion3)) {
168109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      pop(reg);
169109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
1706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
171109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
172109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
173109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::InNewSpace(Register object, Register scratch, Condition cc,
174109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                Label* condition_met,
175109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                Label::Distance distance) {
176109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  const int mask =
177109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      (1 << MemoryChunk::IN_FROM_SPACE) | (1 << MemoryChunk::IN_TO_SPACE);
178109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  CheckPageFlag(object, scratch, mask, cc, condition_met, distance);
1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::RememberedSetHelper(
1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register object,  // Only used for debug checks.
1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register addr,
1853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch,
1863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SaveFPRegsMode save_fp,
1873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MacroAssembler::RememberedSetFinalAction and_then) {
1883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
1903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label ok;
1913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JumpIfNotInNewSpace(object, scratch, &ok, Label::kNear);
1923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int3();
1933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&ok);
1943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load store buffer top.
1963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExternalReference store_buffer =
1973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ExternalReference::store_buffer_top(isolate());
1983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(scratch, Operand::StaticVariable(store_buffer));
1993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Store pointer to buffer.
2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(Operand(scratch, 0), addr);
2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Increment buffer top.
2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(scratch, Immediate(kPointerSize));
2033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Write back new top of buffer.
2043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(Operand::StaticVariable(store_buffer), scratch);
2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Call stub on end of buffer.
2063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for end of buffer.
2073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test(scratch, Immediate(StoreBuffer::kStoreBufferMask));
2083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (and_then == kReturnAtEnd) {
2093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label buffer_overflowed;
2103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    j(equal, &buffer_overflowed, Label::kNear);
2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ret(0);
2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&buffer_overflowed);
2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(and_then == kFallThroughAtEnd);
2153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    j(not_equal, &done, Label::kNear);
2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StoreBufferOverflowStub store_buffer_overflow(isolate(), save_fp);
2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallStub(&store_buffer_overflow);
2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (and_then == kReturnAtEnd) {
2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ret(0);
2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(and_then == kFallThroughAtEnd);
2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&done);
2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::ClampDoubleToUint8(XMMRegister input_reg,
229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                        XMMRegister scratch_reg,
230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                        Register result_reg) {
231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label conv_failure;
233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  xorps(scratch_reg, scratch_reg);
234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cvtsd2si(result_reg, input_reg);
235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  test(result_reg, Immediate(0xFFFFFF00));
236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(zero, &done, Label::kNear);
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(result_reg, Immediate(0x1));
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(overflow, &conv_failure, Label::kNear);
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(result_reg, Immediate(0));
240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  setcc(sign, result_reg);
241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  sub(result_reg, Immediate(1));
242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  and_(result_reg, Immediate(255));
243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  jmp(&done, Label::kNear);
244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&conv_failure);
245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Move(result_reg, Immediate(0));
246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ucomisd(input_reg, scratch_reg);
247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(below, &done, Label::kNear);
248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Move(result_reg, Immediate(255));
249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&done);
250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::ClampUint8(Register reg) {
254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  test(reg, Immediate(0xFFFFFF00));
256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(zero, &done, Label::kNear);
257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  setcc(negative, reg);  // 1 if negative, 0 if positive.
258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  dec_b(reg);  // 0 if negative, 255 if positive.
259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&done);
260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::SlowTruncateToI(Register result_reg,
264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     Register input_reg,
265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     int offset) {
266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleToIStub stub(isolate(), input_reg, result_reg, offset, true);
267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  call(stub.GetCode(), RelocInfo::CODE_TARGET);
268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TruncateDoubleToI(Register result_reg,
272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       XMMRegister input_reg) {
273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cvttsd2si(result_reg, Operand(input_reg));
275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(result_reg, 0x1);
276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(no_overflow, &done, Label::kNear);
277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  sub(esp, Immediate(kDoubleSize));
279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movsd(MemOperand(esp, 0), input_reg);
280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SlowTruncateToI(result_reg, esp, 0);
281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  add(esp, Immediate(kDoubleSize));
282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::DoubleToI(Register result_reg, XMMRegister input_reg,
287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               XMMRegister scratch,
288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               MinusZeroMode minus_zero_mode,
289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Label* lost_precision, Label* is_nan,
290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Label* minus_zero, Label::Distance dst) {
291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!input_reg.is(scratch));
292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cvttsd2si(result_reg, Operand(input_reg));
293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Cvtsi2sd(scratch, Operand(result_reg));
294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ucomisd(scratch, input_reg);
295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(not_equal, lost_precision, dst);
296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(parity_even, is_nan, dst);
297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (minus_zero_mode == FAIL_ON_MINUS_ZERO) {
298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label done;
299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // The integer converted back is equal to the original. We
300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // only have to test if we got -0 as an input.
301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(result_reg, Operand(result_reg));
302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(not_zero, &done, Label::kNear);
303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movmskpd(result_reg, input_reg);
304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Bit 0 contains the sign of the double in input_reg.
305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If input was positive, we are ok and return 0, otherwise
306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // jump to minus_zero.
307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    and_(result_reg, 1);
308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(not_zero, minus_zero, dst);
309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&done);
310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TruncateHeapNumberToI(Register result_reg,
315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register input_reg) {
316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done, slow_case;
317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (CpuFeatures::IsSupported(SSE3)) {
319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CpuFeatureScope scope(this, SSE3);
320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label convert;
321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Use more powerful conversion when sse3 is available.
322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Load x87 register with heap number.
323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Get exponent alone and check for too-big exponent.
325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(result_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset));
326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    and_(result_reg, HeapNumber::kExponentMask);
327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const uint32_t kTooBigExponent =
328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift;
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(Operand(result_reg), Immediate(kTooBigExponent));
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(greater_equal, &slow_case, Label::kNear);
331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Reserve space for 64 bit answer.
333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sub(Operand(esp), Immediate(kDoubleSize));
334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Do conversion, which cannot fail because we checked the exponent.
335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    fisttp_d(Operand(esp, 0));
336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(result_reg, Operand(esp, 0));  // Low word of answer is the result.
337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    add(Operand(esp), Immediate(kDoubleSize));
338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    jmp(&done, Label::kNear);
339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Slow case.
341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&slow_case);
342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (input_reg.is(result_reg)) {
343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Input is clobbered. Restore number from fpu stack
344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      sub(Operand(esp), Immediate(kDoubleSize));
345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      fstp_d(Operand(esp, 0));
346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SlowTruncateToI(result_reg, esp, 0);
347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      add(esp, Immediate(kDoubleSize));
348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      fstp(0);
350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SlowTruncateToI(result_reg, input_reg);
351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cvttsd2si(result_reg, Operand(xmm0));
355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(result_reg, 0x1);
356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(no_overflow, &done, Label::kNear);
357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Check if the input was 0x8000000 (kMinInt).
358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If no, then we got an overflow and we deoptimize.
359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ExternalReference min_int = ExternalReference::address_of_min_int();
360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ucomisd(xmm0, Operand::StaticVariable(min_int));
361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(not_equal, &slow_case, Label::kNear);
362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(parity_even, &slow_case, Label::kNear);  // NaN.
363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    jmp(&done, Label::kNear);
364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Slow case.
366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&slow_case);
367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (input_reg.is(result_reg)) {
368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Input is clobbered. Restore number from double scratch.
369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      sub(esp, Immediate(kDoubleSize));
370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movsd(MemOperand(esp, 0), xmm0);
371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SlowTruncateToI(result_reg, esp, 0);
372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      add(esp, Immediate(kDoubleSize));
373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SlowTruncateToI(result_reg, input_reg);
375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
381958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::LoadUint32(XMMRegister dst, const Operand& src) {
382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(src, Immediate(0));
384958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ExternalReference uint32_bias = ExternalReference::address_of_uint32_bias();
385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Cvtsi2sd(dst, src);
386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(not_sign, &done, Label::kNear);
387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  addsd(dst, Operand::StaticVariable(uint32_bias));
388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::RecordWriteArray(
393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register object,
394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register value,
395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register index,
396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SaveFPRegsMode save_fp,
397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RememberedSetAction remembered_set_action,
398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiCheck smi_check,
399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PointersToHereCheck pointers_to_here_check_for_value) {
4003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // First, check if a write barrier is even needed. The tests below
4013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // catch stores of Smis.
4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Skip barrier if writing a smi.
4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (smi_check == INLINE_SMI_CHECK) {
406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_EQ(0, kSmiTag);
4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    test(value, Immediate(kSmiTagMask));
4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(zero, &done);
4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Array access: calculate the destination address in the same manner as
4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // KeyedStoreIC::GenerateGeneric.  Multiply a smi by 2 to get an offset
4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // into an array of words.
4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register dst = index;
4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lea(dst, Operand(object, index, times_half_pointer_size,
4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   FixedArray::kHeaderSize - kHeapObjectTag));
4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordWrite(object, dst, value, save_fp, remembered_set_action,
419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              OMIT_SMI_CHECK, pointers_to_here_check_for_value);
4203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&done);
4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Clobber clobbered input registers when running with the debug-code flag
4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // turned on to provoke errors.
4253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (emit_debug_code()) {
426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(value, Immediate(bit_cast<int32_t>(kZapValue)));
427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(index, Immediate(bit_cast<int32_t>(kZapValue)));
428257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::RecordWriteField(
4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register object,
4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int offset,
4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register value,
4363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register dst,
4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SaveFPRegsMode save_fp,
4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RememberedSetAction remembered_set_action,
439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiCheck smi_check,
440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PointersToHereCheck pointers_to_here_check_for_value) {
4417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // First, check if a write barrier is even needed. The tests below
4423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // catch stores of Smis.
443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Skip barrier if writing a smi.
4463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (smi_check == INLINE_SMI_CHECK) {
4473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JumpIfSmi(value, &done, Label::kNear);
4483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Although the object register is tagged, the offset is relative to the start
4513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // of the object, so so offset must be a multiple of kPointerSize.
452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsAligned(offset, kPointerSize));
453592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
4543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lea(dst, FieldOperand(object, offset));
4553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (emit_debug_code()) {
4563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label ok;
4573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    test_b(dst, Immediate((1 << kPointerSizeLog2) - 1));
4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(zero, &ok, Label::kNear);
4593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int3();
4603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&ok);
46185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  }
4623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordWrite(object, dst, value, save_fp, remembered_set_action,
464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              OMIT_SMI_CHECK, pointers_to_here_check_for_value);
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&done);
4674515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
4683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Clobber clobbered input registers when running with the debug-code flag
4694515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // turned on to provoke errors.
47044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(value, Immediate(bit_cast<int32_t>(kZapValue)));
472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(dst, Immediate(bit_cast<int32_t>(kZapValue)));
4734515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::RecordWriteForMap(
478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register object,
479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Map> map,
480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch1,
481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch2,
482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SaveFPRegsMode save_fp) {
483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register address = scratch1;
486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register value = scratch2;
4873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (emit_debug_code()) {
488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label ok;
489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    lea(address, FieldOperand(object, HeapObject::kMapOffset));
4903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    test_b(address, Immediate((1 << kPointerSizeLog2) - 1));
491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(zero, &ok, Label::kNear);
492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int3();
493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&ok);
494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!object.is(value));
497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!object.is(address));
498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!value.is(address));
499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertNotSmi(object);
500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!FLAG_incremental_marking) {
502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Compute the address.
506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lea(address, FieldOperand(object, HeapObject::kMapOffset));
507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // A single check of the map's pages interesting flag suffices, since it is
509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // only set during incremental collection, and then it's also guaranteed that
510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the from object's page's interesting flag is also set.  This optimization
511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // relies on the fact that maps can never be in new space.
512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!isolate()->heap()->InNewSpace(*map));
513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckPageFlagForMap(map,
514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      MemoryChunk::kPointersToHereAreInterestingMask,
515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      zero,
516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      &done,
517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      Label::kNear);
518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordWriteStub stub(isolate(), object, value, address, OMIT_REMEMBERED_SET,
520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       save_fp);
521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallStub(&stub);
522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Count number of write barriers in generated code.
526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate()->counters()->write_barriers_static()->Increment();
527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1);
528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Clobber clobbered input registers when running with the debug-code flag
530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // turned on to provoke errors.
531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(value, Immediate(bit_cast<int32_t>(kZapValue)));
533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(scratch1, Immediate(bit_cast<int32_t>(kZapValue)));
534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(scratch2, Immediate(bit_cast<int32_t>(kZapValue)));
535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::RecordWrite(
540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register object,
541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register address,
542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register value,
543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SaveFPRegsMode fp_mode,
544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RememberedSetAction remembered_set_action,
545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiCheck smi_check,
546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PointersToHereCheck pointers_to_here_check_for_value) {
547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!object.is(value));
548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!object.is(address));
549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!value.is(address));
550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertNotSmi(object);
551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (remembered_set_action == OMIT_REMEMBERED_SET &&
5533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      !FLAG_incremental_marking) {
5543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return;
5553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
5583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label ok;
5593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    cmp(value, Operand(address, 0));
5603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(equal, &ok, Label::kNear);
5613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int3();
5623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&ok);
5633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5658defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // First, check if a write barrier is even needed. The tests below
5668defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // catch stores of Smis and stores into young gen.
5678defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Label done;
5688defd9ff6930b4e24729971a61cf7469daf119beSteve Block
5693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (smi_check == INLINE_SMI_CHECK) {
5703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Skip barrier if writing a smi.
5713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JumpIfSmi(value, &done, Label::kNear);
5723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (pointers_to_here_check_for_value != kPointersToHereAreAlwaysInteresting) {
575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CheckPageFlag(value,
576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  value,  // Used as scratch.
577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  MemoryChunk::kPointersToHereAreInterestingMask,
578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  zero,
579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  &done,
580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  Label::kNear);
581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPageFlag(object,
5833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                value,  // Used as scratch.
5843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                MemoryChunk::kPointersFromHereAreInterestingMask,
5853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                zero,
5863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                &done,
5873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                Label::kNear);
5883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordWriteStub stub(isolate(), object, value, address, remembered_set_action,
590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       fp_mode);
5913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallStub(&stub);
5928defd9ff6930b4e24729971a61cf7469daf119beSteve Block
5938defd9ff6930b4e24729971a61cf7469daf119beSteve Block  bind(&done);
5948defd9ff6930b4e24729971a61cf7469daf119beSteve Block
595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Count number of write barriers in generated code.
596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate()->counters()->write_barriers_static()->Increment();
597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1);
598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Clobber clobbered registers when running with the debug-code flag
6008defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // turned on to provoke errors.
60144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(address, Immediate(bit_cast<int32_t>(kZapValue)));
603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(value, Immediate(bit_cast<int32_t>(kZapValue)));
6048defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
6058defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
6068defd9ff6930b4e24729971a61cf7469daf119beSteve Block
607109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::RecordWriteCodeEntryField(Register js_function,
608109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                               Register code_entry,
609109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                               Register scratch) {
610109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  const int offset = JSFunction::kCodeEntryOffset;
611109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
612109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Since a code entry (value) is always in old space, we don't need to update
613109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // remembered set. If incremental marking is off, there is nothing for us to
614109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // do.
615109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (!FLAG_incremental_marking) return;
616109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
617109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(!js_function.is(code_entry));
618109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(!js_function.is(scratch));
619109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(!code_entry.is(scratch));
620109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  AssertNotSmi(js_function);
621109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
622109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (emit_debug_code()) {
623109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Label ok;
624109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    lea(scratch, FieldOperand(js_function, offset));
625109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    cmp(code_entry, Operand(scratch, 0));
626109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    j(equal, &ok, Label::kNear);
627109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    int3();
628109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    bind(&ok);
629109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
630109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
631109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // First, check if a write barrier is even needed. The tests below
632109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // catch stores of Smis and stores into young gen.
633109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Label done;
634109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
635109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  CheckPageFlag(code_entry, scratch,
636109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                MemoryChunk::kPointersToHereAreInterestingMask, zero, &done,
637109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                Label::kNear);
638109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  CheckPageFlag(js_function, scratch,
639109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                MemoryChunk::kPointersFromHereAreInterestingMask, zero, &done,
640109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                Label::kNear);
641109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
642109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Save input registers.
643109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  push(js_function);
644109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  push(code_entry);
645109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
646109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  const Register dst = scratch;
647109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  lea(dst, FieldOperand(js_function, offset));
648109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
649109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Save caller-saved registers.
650109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PushCallerSaved(kDontSaveFPRegs, js_function, code_entry);
651109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
652109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  int argument_count = 3;
653109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PrepareCallCFunction(argument_count, code_entry);
654109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  mov(Operand(esp, 0 * kPointerSize), js_function);
655109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  mov(Operand(esp, 1 * kPointerSize), dst);  // Slot.
656109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  mov(Operand(esp, 2 * kPointerSize),
657109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      Immediate(ExternalReference::isolate_address(isolate())));
658109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
659109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  {
660109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    AllowExternalCallThatCantCauseGC scope(this);
661109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    CallCFunction(
662109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        ExternalReference::incremental_marking_record_write_code_entry_function(
663109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch            isolate()),
664109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        argument_count);
665109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
666109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
667109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Restore caller-saved registers.
668109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PopCallerSaved(kDontSaveFPRegs, js_function, code_entry);
669109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
670109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Restore input registers.
671109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  pop(code_entry);
672109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  pop(js_function);
673109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
674109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  bind(&done);
675109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
6768defd9ff6930b4e24729971a61cf7469daf119beSteve Block
677402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::DebugBreak() {
678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Move(eax, Immediate(0));
679014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(ebx, Immediate(ExternalReference(Runtime::kHandleDebuggerStatement,
680014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                       isolate())));
681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CEntryStub ces(isolate(), 1);
682014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  call(ces.GetCode(), RelocInfo::DEBUGGER_STATEMENT);
683402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Cvtsi2sd(XMMRegister dst, const Operand& src) {
686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  xorps(dst, dst);
687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cvtsi2sd(dst, src);
688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
691109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::Cvtui2ss(XMMRegister dst, Register src, Register tmp) {
692109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Label msb_set_src;
693109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Label jmp_return;
694109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  test(src, src);
695109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  j(sign, &msb_set_src, Label::kNear);
696109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  cvtsi2ss(dst, src);
697109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  jmp(&jmp_return, Label::kNear);
698109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  bind(&msb_set_src);
699109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  mov(tmp, src);
700109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  shr(src, 1);
701109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Recover the least significant bit to avoid rounding errors.
702109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  and_(tmp, Immediate(1));
703109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  or_(src, tmp);
704109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  cvtsi2ss(dst, src);
705109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  addss(dst, dst);
706109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  bind(&jmp_return);
707109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
708109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
7093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::ShlPair(Register high, Register low, uint8_t shift) {
7103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (shift >= 32) {
7113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    mov(high, low);
7123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shl(high, shift - 32);
7133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    xor_(low, low);
7143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
7153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shld(high, low, shift);
7163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shl(low, shift);
7173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
7183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
7193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
7203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::ShlPair_cl(Register high, Register low) {
7213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  shld_cl(high, low);
7223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  shl_cl(low);
7233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label done;
7243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test(ecx, Immediate(0x20));
7253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  j(equal, &done, Label::kNear);
7263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(high, low);
7273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  xor_(low, low);
7283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&done);
7293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
7303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
7313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::ShrPair(Register high, Register low, uint8_t shift) {
7323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (shift >= 32) {
7333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    mov(low, high);
7343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shr(low, shift - 32);
7353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    xor_(high, high);
7363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
7373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shrd(high, low, shift);
7383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shr(high, shift);
7393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
7403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
7413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
7423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::ShrPair_cl(Register high, Register low) {
7433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  shrd_cl(low, high);
7443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  shr_cl(high);
7453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label done;
7463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test(ecx, Immediate(0x20));
7473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  j(equal, &done, Label::kNear);
7483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(low, high);
7493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  xor_(high, high);
7503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&done);
7513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
7523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
7533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::SarPair(Register high, Register low, uint8_t shift) {
7543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (shift >= 32) {
7553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    mov(low, high);
7563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    sar(low, shift - 32);
7573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    sar(high, 31);
7583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
7593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shrd(high, low, shift);
7603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    sar(high, shift);
7613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
7623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
7633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
7643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::SarPair_cl(Register high, Register low) {
7653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  shrd_cl(low, high);
7663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  sar_cl(high);
7673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label done;
7683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test(ecx, Immediate(0x20));
7693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  j(equal, &done, Label::kNear);
7703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(low, high);
7713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  sar(high, 31);
7723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&done);
7733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
774109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
775053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Blockbool MacroAssembler::IsUnsafeImmediate(const Immediate& x) {
776053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  static const int kMaxImmediateBits = 17;
777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!RelocInfo::IsNone(x.rmode_)) return false;
778053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  return !is_intn(x.x_, kMaxImmediateBits);
779053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block}
780053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
781053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::SafeMove(Register dst, const Immediate& x) {
783053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  if (IsUnsafeImmediate(x) && jit_cookie() != 0) {
784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(dst, Immediate(x.x_ ^ jit_cookie()));
785053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block    xor_(dst, jit_cookie());
786053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  } else {
787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(dst, x);
788053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  }
789053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block}
790053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
791053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
792053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Blockvoid MacroAssembler::SafePush(const Immediate& x) {
793053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  if (IsUnsafeImmediate(x) && jit_cookie() != 0) {
794053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block    push(Immediate(x.x_ ^ jit_cookie()));
795053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block    xor_(Operand(esp, 0), Immediate(jit_cookie()));
796053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  } else {
797053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block    push(x);
798053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  }
799053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block}
800053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
801053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpObjectType(Register heap_object,
803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   InstanceType type,
804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   Register map) {
805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(map, FieldOperand(heap_object, HeapObject::kMapOffset));
806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CmpInstanceType(map, type);
807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpInstanceType(Register map, InstanceType type) {
8113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  cmpb(FieldOperand(map, Map::kInstanceTypeOffset), Immediate(type));
812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::CheckFastElements(Register map,
8163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                       Label* fail,
8173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                       Label::Distance distance) {
818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_ELEMENTS == 2);
821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
8223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmpb(FieldOperand(map, Map::kBitField2Offset),
8233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch       Immediate(Map::kMaximumBitField2FastHoleyElementValue));
8243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(above, fail, distance);
8253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
8263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckFastObjectElements(Register map,
8293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Label* fail,
8303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Label::Distance distance) {
831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_ELEMENTS == 2);
834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
8353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmpb(FieldOperand(map, Map::kBitField2Offset),
8363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch       Immediate(Map::kMaximumBitField2FastHoleySmiElementValue));
8373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(below_equal, fail, distance);
8383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  cmpb(FieldOperand(map, Map::kBitField2Offset),
8393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch       Immediate(Map::kMaximumBitField2FastHoleyElementValue));
8403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  j(above, fail, distance);
8413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
8423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
8433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CheckFastSmiElements(Register map,
845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          Label* fail,
846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          Label::Distance distance) {
847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
8493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmpb(FieldOperand(map, Map::kBitField2Offset),
8503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch       Immediate(Map::kMaximumBitField2FastHoleySmiElementValue));
8513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(above, fail, distance);
8523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
8533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::StoreNumberToDoubleElements(
8563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register maybe_number,
8573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register elements,
8583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register key,
8593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch1,
8603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    XMMRegister scratch2,
8613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* fail,
862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int elements_offset) {
863014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label smi_value, done;
8643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpIfSmi(maybe_number, &smi_value, Label::kNear);
8653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckMap(maybe_number,
8673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           isolate()->factory()->heap_number_map(),
8683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           fail,
8693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           DONT_DO_SMI_CHECK);
8703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
871014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Double value, turn potential sNaN into qNaN.
872014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Move(scratch2, 1.0);
873014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mulsd(scratch2, FieldOperand(maybe_number, HeapNumber::kValueOffset));
874014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  jmp(&done, Label::kNear);
8753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&smi_value);
8773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Value is a smi. Convert to a double and store.
8783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Preserve original value.
8793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(scratch1, maybe_number);
8803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SmiUntag(scratch1);
881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Cvtsi2sd(scratch2, scratch1);
882014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&done);
883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movsd(FieldOperand(elements, key, times_4,
884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     FixedDoubleArray::kHeaderSize - elements_offset),
885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        scratch2);
8863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
8873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CompareMap(Register obj, Handle<Map> map) {
8903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmp(FieldOperand(obj, HeapObject::kMapOffset), map);
8913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
8923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::CheckMap(Register obj,
8953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Handle<Map> map,
8963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Label* fail,
897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              SmiCheckType smi_check_type) {
898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (smi_check_type == DO_SMI_CHECK) {
899257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    JumpIfSmi(obj, fail);
9003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
9013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompareMap(obj, map);
9033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  j(not_equal, fail);
9043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
9053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
907958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::DispatchWeakMap(Register obj, Register scratch1,
908958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                     Register scratch2, Handle<WeakCell> cell,
909958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                     Handle<Code> success,
910958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                     SmiCheckType smi_check_type) {
911257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label fail;
912257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (smi_check_type == DO_SMI_CHECK) {
913257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    JumpIfSmi(obj, &fail);
914257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
915958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  mov(scratch1, FieldOperand(obj, HeapObject::kMapOffset));
916958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CmpWeakValue(scratch1, cell, scratch2);
917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(equal, success);
918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&fail);
920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
923e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeCondition MacroAssembler::IsObjectStringType(Register heap_object,
924e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                             Register map,
925e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                             Register instance_type) {
926e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  mov(map, FieldOperand(heap_object, HeapObject::kMapOffset));
927e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
92869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kNotStringTag != 0);
929e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  test(instance_type, Immediate(kIsNotStringMask));
930e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  return zero;
931e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
932e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
933e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochCondition MacroAssembler::IsObjectNameType(Register heap_object,
935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register map,
936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register instance_type) {
937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(map, FieldOperand(heap_object, HeapObject::kMapOffset));
938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
9393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  cmpb(instance_type, Immediate(LAST_NAME_TYPE));
940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return below_equal;
941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::FCmp() {
945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fucomip();
946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fstp(0);
947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertNumber(Register object) {
951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label ok;
953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    JumpIfSmi(object, &ok);
954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(FieldOperand(object, HeapObject::kMapOffset),
955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate()->factory()->heap_number_map());
956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, kOperandNotANumber);
957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&ok);
9583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::AssertNotNumber(Register object) {
9623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (emit_debug_code()) {
9633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    test(object, Immediate(kSmiTagMask));
9643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Check(not_equal, kOperandIsANumber);
9653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    cmp(FieldOperand(object, HeapObject::kMapOffset),
9663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        isolate()->factory()->heap_number_map());
9673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Check(not_equal, kOperandIsANumber);
9683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
9693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertSmi(Register object) {
972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(object, Immediate(kSmiTagMask));
974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, kOperandIsNotASmi);
975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertString(Register object) {
980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(object, Immediate(kSmiTagMask));
982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kOperandIsASmiAndNotAString);
983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    push(object);
984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(object, FieldOperand(object, HeapObject::kMapOffset));
985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CmpInstanceType(object, FIRST_NONSTRING_TYPE);
986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    pop(object);
987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(below, kOperandIsNotAString);
988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertName(Register object) {
993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(object, Immediate(kSmiTagMask));
995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kOperandIsASmiAndNotAName);
996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    push(object);
997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(object, FieldOperand(object, HeapObject::kMapOffset));
998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CmpInstanceType(object, LAST_NAME_TYPE);
999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    pop(object);
1000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(below_equal, kOperandIsNotAName);
1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1005014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::AssertFunction(Register object) {
1006014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (emit_debug_code()) {
1007014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    test(object, Immediate(kSmiTagMask));
1008014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(not_equal, kOperandIsASmiAndNotAFunction);
1009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(object);
1010014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CmpObjectType(object, JS_FUNCTION_TYPE, object);
1011014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Pop(object);
1012014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(equal, kOperandIsNotAFunction);
1013014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1014014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1015014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1016014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1017014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::AssertBoundFunction(Register object) {
1018014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (emit_debug_code()) {
1019014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    test(object, Immediate(kSmiTagMask));
1020014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(not_equal, kOperandIsASmiAndNotABoundFunction);
1021014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(object);
1022014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CmpObjectType(object, JS_BOUND_FUNCTION_TYPE, object);
1023014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Pop(object);
1024014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(equal, kOperandIsNotABoundFunction);
1025014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1026014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1027014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1028bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::AssertGeneratorObject(Register object) {
1029bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (emit_debug_code()) {
1030bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    test(object, Immediate(kSmiTagMask));
1031bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Check(not_equal, kOperandIsASmiAndNotAGeneratorObject);
1032bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Push(object);
1033bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    CmpObjectType(object, JS_GENERATOR_OBJECT_TYPE, object);
1034bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Pop(object);
1035bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Check(equal, kOperandIsNotAGeneratorObject);
1036bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1037bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1038014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1039109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::AssertReceiver(Register object) {
1040109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (emit_debug_code()) {
1041109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    test(object, Immediate(kSmiTagMask));
1042109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Check(not_equal, kOperandIsASmiAndNotAReceiver);
1043109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Push(object);
1044109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
1045109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    CmpObjectType(object, FIRST_JS_RECEIVER_TYPE, object);
1046109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Pop(object);
1047109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Check(above_equal, kOperandIsNotAReceiver);
1048109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
1049109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
1050109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1051109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertUndefinedOrAllocationSite(Register object) {
1053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
1054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label done_checking;
1055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AssertNotSmi(object);
1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(object, isolate()->factory()->undefined_value());
1057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(equal, &done_checking);
1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(FieldOperand(object, 0),
1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Immediate(isolate()->factory()->allocation_site_map()));
1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Assert(equal, kExpectedUndefinedOrCell);
1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&done_checking);
1062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1063402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
1064402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1065402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertNotSmi(Register object) {
1067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
1068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(object, Immediate(kSmiTagMask));
1069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kOperandIsASmi);
1070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1071756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
1072756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
10733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::StubPrologue(StackFrame::Type type) {
1074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  push(ebp);  // Caller's frame pointer.
1075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(ebp, esp);
10763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  push(Immediate(Smi::FromInt(type)));
107780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
107880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Prologue(bool code_pre_aging) {
1080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PredictableCodeSizeScope predictible_code_size_scope(this,
1081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kNoCodeAgeSequenceLength);
1082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (code_pre_aging) {
1083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Pre-age the code.
1084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    call(isolate()->builtins()->MarkCodeAsExecutedOnce(),
1085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        RelocInfo::CODE_AGE_SEQUENCE);
1086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Nop(kNoCodeAgeSequenceLength - Assembler::kCallInstructionLength);
1087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    push(ebp);  // Caller's frame pointer.
1089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(ebp, esp);
1090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    push(esi);  // Callee's context.
1091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    push(edi);  // Callee's JS function.
1092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
10936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
10946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1096014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::EmitLoadTypeFeedbackVector(Register vector) {
1097014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(vector, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1098014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(vector, FieldOperand(vector, JSFunction::kSharedFunctionInfoOffset));
1099014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(vector, FieldOperand(vector, SharedFunctionInfo::kFeedbackVectorOffset));
1100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1103958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::EnterFrame(StackFrame::Type type,
1104958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                bool load_constant_pool_pointer_reg) {
1105958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Out-of-line constant pool not implemented on ia32.
1106958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  UNREACHABLE();
1107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1108958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1109958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::EnterFrame(StackFrame::Type type) {
1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(ebp);
11123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(ebp, esp);
1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(Immediate(Smi::FromInt(type)));
11143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (type == StackFrame::INTERNAL) {
11153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    push(Immediate(CodeObject()));
11163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
111744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
111844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    cmp(Operand(esp, 0), Immediate(isolate()->factory()->undefined_value()));
1119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kCodeObjectNotProperlyPatched);
1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LeaveFrame(StackFrame::Type type) {
112544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
11263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    cmp(Operand(ebp, CommonFrameConstants::kContextOrFrameTypeOffset),
1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Immediate(Smi::FromInt(type)));
1128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, kStackFrameTypesMustMatch);
1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  leave();
1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
113380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
113480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::EnterExitFramePrologue() {
11353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up the frame structure on the stack.
11363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(+2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement);
11373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(+1 * kPointerSize, ExitFrameConstants::kCallerPCOffset);
11383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset);
1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(ebp);
11403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(ebp, esp);
1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
114280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Reserve room for entry stack pointer and push the code object.
11433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  push(Immediate(Smi::FromInt(StackFrame::EXIT)));
11443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(-2 * kPointerSize, ExitFrameConstants::kSPOffset);
1145402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  push(Immediate(0));  // Saved entry sp, patched before call.
11463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(-3 * kPointerSize, ExitFrameConstants::kCodeOffset);
1147402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  push(Immediate(CodeObject()));  // Accessed from ExitFrame::code_slot.
1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Save the frame pointer and the context in top.
1150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress, isolate());
1151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference context_address(Isolate::kContextAddress, isolate());
1152958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ExternalReference c_function_address(Isolate::kCFunctionAddress, isolate());
1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(Operand::StaticVariable(c_entry_fp_address), ebp);
1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(Operand::StaticVariable(context_address), esi);
1155958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  mov(Operand::StaticVariable(c_function_address), ebx);
1156d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid MacroAssembler::EnterExitFrameEpilogue(int argc, bool save_doubles) {
1160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Optionally save all XMM registers.
1161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (save_doubles) {
1162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int space = XMMRegister::kMaxNumRegisters * kDoubleSize +
1163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                argc * kPointerSize;
11643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sub(esp, Immediate(space));
11653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    const int offset = -ExitFrameConstants::kFixedFrameSizeFromFp;
1166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
1167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      XMMRegister reg = XMMRegister::from_code(i);
1168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movsd(Operand(ebp, offset - ((i + 1) * kDoubleSize)), reg);
1169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
11713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sub(esp, Immediate(argc * kPointerSize));
1172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the required frame alignment for the OS.
1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kFrameAlignment = base::OS::ActivationFrameAlignment();
1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (kFrameAlignment > 0) {
1177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(base::bits::IsPowerOfTwo32(kFrameAlignment));
1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    and_(esp, -kFrameAlignment);
1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the saved entry sp.
1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(Operand(ebp, ExitFrameConstants::kSPOffset), esp);
1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1186109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::EnterExitFrame(int argc, bool save_doubles) {
118780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  EnterExitFramePrologue();
1188d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
11893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up argc and argv in callee-saved registers.
1190d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
11913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(edi, eax);
1192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  lea(esi, Operand(ebp, eax, times_4, offset));
1193d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
119444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Reserve space for argc, argv and isolate.
1195109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  EnterExitFrameEpilogue(argc, save_doubles);
1196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1197d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
11998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid MacroAssembler::EnterApiExitFrame(int argc) {
120080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  EnterExitFramePrologue();
1201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  EnterExitFrameEpilogue(argc, false);
1202d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1203d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LeaveExitFrame(bool save_doubles, bool pop_arguments) {
1206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Optionally restore all XMM registers.
1207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (save_doubles) {
12083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    const int offset = -ExitFrameConstants::kFixedFrameSizeFromFp;
1209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
1210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      XMMRegister reg = XMMRegister::from_code(i);
1211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movsd(reg, Operand(ebp, offset - ((i + 1) * kDoubleSize)));
1212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (pop_arguments) {
1216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Get the return address from the stack and restore the frame pointer.
1217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mov(ecx, Operand(ebp, 1 * kPointerSize));
1218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mov(ebp, Operand(ebp, 0 * kPointerSize));
1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Pop the arguments and the receiver from the caller stack.
1221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    lea(esp, Operand(esi, 1 * kPointerSize));
1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Push the return address to get ready to return.
1224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    push(ecx);
1225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
1226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Otherwise just leave the exit frame.
1227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    leave();
1228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
12298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LeaveExitFrameEpilogue(true);
12318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
12328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::LeaveExitFrameEpilogue(bool restore_context) {
1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Restore current context from top and clear it in debug mode.
1236589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ExternalReference context_address(Isolate::kContextAddress, isolate());
1237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (restore_context) {
1238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(esi, Operand::StaticVariable(context_address));
1239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(Operand::StaticVariable(context_address), Immediate(0));
1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clear the top frame.
1245589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress,
124644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       isolate());
1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(Operand::StaticVariable(c_entry_fp_address), Immediate(0));
1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::LeaveApiExitFrame(bool restore_context) {
12523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(esp, ebp);
12538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  pop(ebp);
12548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LeaveExitFrameEpilogue(restore_context);
12568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
12578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
12588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::PushStackHandler() {
1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Adjust this code if not the case.
1261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(StackHandlerConstants::kSize == 1 * kPointerSize);
126269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
12633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Link the current handler as the next handler.
12653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
12663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  push(Operand::StaticVariable(handler_address));
1267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
12683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set this new handler as the current one.
12693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(Operand::StaticVariable(handler_address), esp);
1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::PopStackHandler() {
127469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
12753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
12763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  pop(Operand::StaticVariable(handler_address));
12773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(esp, Immediate(StackHandlerConstants::kSize - kPointerSize));
12783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
12793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
1282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                            Register scratch1,
1283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                            Register scratch2,
1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            Label* miss) {
1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label same_contexts;
1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!holder_reg.is(scratch1));
1288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!holder_reg.is(scratch2));
1289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!scratch1.is(scratch2));
1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Load current lexical context from the active StandardFrame, which
12923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // may require crawling past STUB frames.
12933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label load_context;
12943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label has_context;
12953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(scratch2, ebp);
12963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&load_context);
12973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(scratch1,
12983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      MemOperand(scratch2, CommonFrameConstants::kContextOrFrameTypeOffset));
12993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  JumpIfNotSmi(scratch1, &has_context);
13003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(scratch2, MemOperand(scratch2, CommonFrameConstants::kCallerFPOffset));
13013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  jmp(&load_context);
13023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&has_context);
1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // When generating debug code, make sure the lexical context is set.
130544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
1306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(scratch1, Immediate(0));
1307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kWeShouldNotHaveAnEmptyLexicalContext);
1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the native context of the current context.
1310014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(scratch1, ContextOperand(scratch1, Context::NATIVE_CONTEXT_INDEX));
1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check the context is a native context.
131344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
1314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Read the first word and compare to native_context_map.
1315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(FieldOperand(scratch1, HeapObject::kMapOffset),
1316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate()->factory()->native_context_map());
1317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext);
1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if both contexts are the same.
1321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(scratch1, FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
1322257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(equal, &same_contexts);
1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compare security tokens, save holder_reg on the stack so we can use it
1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // as a temporary register.
1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the security token in the calling global object is
1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // compatible with the security token in the receiving global
1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object.
1330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(scratch2,
1331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check the context is a native context.
133444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
1335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(scratch2, isolate()->factory()->null_value());
1336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kJSGlobalProxyContextShouldNotBeNull);
1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Read the first word and compare to native_context_map(),
1339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(FieldOperand(scratch2, HeapObject::kMapOffset),
1340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate()->factory()->native_context_map());
1341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext);
1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int token_offset = Context::kHeaderSize +
1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     Context::SECURITY_TOKEN_INDEX * kPointerSize;
1346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(scratch1, FieldOperand(scratch1, token_offset));
1347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(scratch1, FieldOperand(scratch2, token_offset));
1348257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_equal, miss);
1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&same_contexts);
1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Compute the hash code from the untagged key.  This must be kept in sync with
1355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ComputeIntegerHash in utils.h and KeyedLoadGenericStub in
1356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// code-stub-hydrogen.cc
1357c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch//
1358c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch// Note: r0 will contain hash code
1359c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdochvoid MacroAssembler::GetNumberHash(Register r0, Register scratch) {
1360c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // Xor original key with a seed.
1361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (serializer_enabled()) {
13623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ExternalReference roots_array_start =
13633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ExternalReference::roots_array_start(isolate());
1364c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    mov(scratch, Immediate(Heap::kHashSeedRootIndex));
13653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(scratch,
13663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Operand::StaticArray(scratch, times_pointer_size, roots_array_start));
1367c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    SmiUntag(scratch);
13683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    xor_(r0, scratch);
1369c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  } else {
1370c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    int32_t seed = isolate()->heap()->HashSeed();
13713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    xor_(r0, Immediate(seed));
1372c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  }
1373c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
1374c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = ~hash + (hash << 15);
1375c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  mov(scratch, r0);
1376c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  not_(r0);
1377c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  shl(scratch, 15);
13783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(r0, scratch);
1379c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash ^ (hash >> 12);
1380c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  mov(scratch, r0);
1381c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  shr(scratch, 12);
13823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  xor_(r0, scratch);
1383c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash + (hash << 2);
1384c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  lea(r0, Operand(r0, r0, times_4, 0));
1385c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash ^ (hash >> 4);
1386c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  mov(scratch, r0);
1387c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  shr(scratch, 4);
13883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  xor_(r0, scratch);
1389c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash * 2057;
1390c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  imul(r0, r0, 2057);
1391c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash ^ (hash >> 16);
1392c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  mov(scratch, r0);
1393c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  shr(scratch, 16);
13943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  xor_(r0, scratch);
1395014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  and_(r0, 0x3fffffff);
1396c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch}
1397c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
1398c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
1399c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
14003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::LoadFromNumberDictionary(Label* miss,
14013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register elements,
14023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register key,
14033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register r0,
14043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register r1,
14053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register r2,
14063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register result) {
14073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Register use:
14083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
14093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // elements - holds the slow-case elements of the receiver and is unchanged.
14103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
14113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // key      - holds the smi key on entry and is unchanged.
14123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
14133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Scratch registers:
14143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
14153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // r0 - holds the untagged key on entry and holds the hash once computed.
14163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
14173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // r1 - used to hold the capacity mask of the dictionary
14183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
14193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // r2 - used for the index into the dictionary.
14203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
14213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // result - holds the result on exit if the load succeeds and we fall through.
14223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
14233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label done;
14243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1425c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  GetNumberHash(r0, r1);
14263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
14273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Compute capacity mask.
1428c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  mov(r1, FieldOperand(elements, SeededNumberDictionary::kCapacityOffset));
14293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  shr(r1, kSmiTagSize);  // convert smi to int
14303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  dec(r1);
14313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
14323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Generate an unrolled loop that performs a few probes before giving up.
1433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < kNumberDictionaryProbes; i++) {
14343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Use r2 for index calculations and keep the hash intact in r0.
14353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    mov(r2, r0);
14363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Compute the masked index: (hash + i + i * i) & mask.
14373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (i > 0) {
14383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      add(r2, Immediate(SeededNumberDictionary::GetProbeOffset(i)));
14393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
14403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    and_(r2, r1);
14413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
14423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Scale the index by multiplying by the entry size.
1443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SeededNumberDictionary::kEntrySize == 3);
14443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    lea(r2, Operand(r2, r2, times_2, 0));  // r2 = r2 * 3
14453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
14463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Check if the key matches.
14473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    cmp(key, FieldOperand(elements,
14483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          r2,
14493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          times_pointer_size,
1450c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                          SeededNumberDictionary::kElementsStartOffset));
1451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (i != (kNumberDictionaryProbes - 1)) {
14523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      j(equal, &done);
14533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
14543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      j(not_equal, miss);
14553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
14563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
14573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
14583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bind(&done);
1459958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check that the value is a field property.
14603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const int kDetailsOffset =
1461c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize;
1462014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(DATA, 0);
14633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset),
1464589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch       Immediate(PropertyDetails::TypeField::kMask << kSmiTagSize));
14653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  j(not_zero, miss);
14663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
14673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Get the value at the masked, scaled index.
14683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const int kValueOffset =
1469c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      SeededNumberDictionary::kElementsStartOffset + kPointerSize;
14703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  mov(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset));
14713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
14723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
14733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LoadAllocationTopHelper(Register result,
1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register scratch,
1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             AllocationFlags flags) {
1477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_top =
1478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationTopReference(isolate(), flags);
1479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Just return if allocation top is already known.
1481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((flags & RESULT_CONTAINS_TOP) != 0) {
1482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // No use of scratch if allocation top is provided.
1483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(scratch.is(no_reg));
1484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Assert that result actually contains top on entry.
1486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(result, Operand::StaticVariable(allocation_top));
1487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, kUnexpectedAllocationTop);
1488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
1490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Move address of new object to result. Use scratch register if available.
1493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (scratch.is(no_reg)) {
1494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(result, Operand::StaticVariable(allocation_top));
1495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(scratch, Immediate(allocation_top));
1497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(result, Operand(scratch, 0));
1498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::UpdateAllocationTopHelper(Register result_end,
1503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register scratch,
1504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               AllocationFlags flags) {
150544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
1506d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    test(result_end, Immediate(kObjectAlignmentMask));
1507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(zero, kUnalignedAllocationInNewSpace);
1508d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1509d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_top =
1511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationTopReference(isolate(), flags);
1512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update new top. Use scratch if available.
1514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (scratch.is(no_reg)) {
1515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(Operand::StaticVariable(allocation_top), result_end);
1516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(Operand(scratch, 0), result_end);
1518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Allocate(int object_size,
1523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result,
1524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result_end,
1525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register scratch,
1526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Label* gc_required,
1527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              AllocationFlags flags) {
1528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0);
1529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(object_size <= Page::kMaxRegularHeapObjectSize);
1530bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK((flags & ALLOCATION_FOLDED) == 0);
15315913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  if (!FLAG_inline_new) {
153244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (emit_debug_code()) {
15335913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // Trash the registers to simulate an allocation failure.
15345913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      mov(result, Immediate(0x7091));
15355913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (result_end.is_valid()) {
15365913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        mov(result_end, Immediate(0x7191));
15375913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
15385913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (scratch.is_valid()) {
15395913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        mov(scratch, Immediate(0x7291));
15405913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
15415913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    }
15425913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    jmp(gc_required);
15435913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    return;
15445913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
1545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result.is(result_end));
1546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load address of new object into result.
15488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LoadAllocationTopHelper(result, scratch, flags);
1549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_limit =
1551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationLimitReference(isolate(), flags);
1552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Align the next allocation. Storing the filler map without checking top is
1554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // safe in new-space because the limit of the heap is aligned there.
1555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
1556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
1557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label aligned;
1558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(result, Immediate(kDoubleAlignmentMask));
1559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(zero, &aligned, Label::kNear);
1560014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if ((flags & PRETENURE) != 0) {
1561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cmp(result, Operand::StaticVariable(allocation_limit));
1562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      j(above_equal, gc_required);
1563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(Operand(result, 0),
1565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Immediate(isolate()->factory()->one_pointer_filler_map()));
1566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    add(result, Immediate(kDoubleSize / 2));
1567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&aligned);
1568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Calculate new top and bail out if space is exhausted.
1571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register top_reg = result_end.is_valid() ? result_end : result;
1572bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
15731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (!top_reg.is(result)) {
15741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    mov(top_reg, result);
1575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
15763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(top_reg, Immediate(object_size));
1577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(top_reg, Operand::StaticVariable(allocation_limit));
1578257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(above, gc_required);
1579e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1580bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
1581bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // The top pointer is not updated for allocation folding dominators.
1582bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    UpdateAllocationTopHelper(top_reg, scratch, flags);
1583bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1584bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1585bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (top_reg.is(result)) {
1586bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    sub(result, Immediate(object_size - kHeapObjectTag));
1587bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  } else {
1588bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // Tag the result.
1589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kHeapObjectTag == 1);
1590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    inc(result);
1591bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
1592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Allocate(int header_size,
1596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              ScaleFactor element_size,
1597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register element_count,
1598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              RegisterValueType element_count_type,
1599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result,
1600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result_end,
1601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register scratch,
1602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Label* gc_required,
1603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              AllocationFlags flags) {
1604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((flags & SIZE_IN_WORDS) == 0);
1605bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK((flags & ALLOCATION_FOLDING_DOMINATOR) == 0);
1606bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK((flags & ALLOCATION_FOLDED) == 0);
16075913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  if (!FLAG_inline_new) {
160844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (emit_debug_code()) {
16095913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // Trash the registers to simulate an allocation failure.
16105913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      mov(result, Immediate(0x7091));
16115913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      mov(result_end, Immediate(0x7191));
16125913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (scratch.is_valid()) {
16135913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        mov(scratch, Immediate(0x7291));
16145913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
16155913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // Register element_count is not modified by the function.
16165913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    }
16175913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    jmp(gc_required);
16185913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    return;
16195913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
1620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result.is(result_end));
1621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load address of new object into result.
16238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LoadAllocationTopHelper(result, scratch, flags);
1624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_limit =
1626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationLimitReference(isolate(), flags);
1627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Align the next allocation. Storing the filler map without checking top is
1629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // safe in new-space because the limit of the heap is aligned there.
1630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
1631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
1632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label aligned;
1633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(result, Immediate(kDoubleAlignmentMask));
1634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(zero, &aligned, Label::kNear);
1635014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if ((flags & PRETENURE) != 0) {
1636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cmp(result, Operand::StaticVariable(allocation_limit));
1637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      j(above_equal, gc_required);
1638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(Operand(result, 0),
1640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Immediate(isolate()->factory()->one_pointer_filler_map()));
1641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    add(result, Immediate(kDoubleSize / 2));
1642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&aligned);
1643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
16441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Calculate new top and bail out if space is exhausted.
16461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // We assume that element_count*element_size + header_size does not
16471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // overflow.
1648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (element_count_type == REGISTER_VALUE_IS_SMI) {
1649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(static_cast<ScaleFactor>(times_2 - 1) == times_1);
1650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(static_cast<ScaleFactor>(times_4 - 1) == times_2);
1651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(static_cast<ScaleFactor>(times_8 - 1) == times_4);
1652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(element_size >= times_2);
1653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kSmiTagSize == 1);
1654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    element_size = static_cast<ScaleFactor>(element_size - 1);
1655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(element_count_type == REGISTER_VALUE_IS_INT32);
1657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1658bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
16591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  lea(result_end, Operand(element_count, element_size, header_size));
16603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(result_end, result);
1661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(result_end, Operand::StaticVariable(allocation_limit));
1662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(above, gc_required);
1663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1664bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Tag result.
1665bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(kHeapObjectTag == 1);
1666bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  inc(result);
1667e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UpdateAllocationTopHelper(result_end, scratch, flags);
1669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Allocate(Register object_size,
1673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result,
1674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result_end,
1675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register scratch,
1676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Label* gc_required,
1677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              AllocationFlags flags) {
1678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0);
1679bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK((flags & ALLOCATION_FOLDED) == 0);
16805913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  if (!FLAG_inline_new) {
168144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (emit_debug_code()) {
16825913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // Trash the registers to simulate an allocation failure.
16835913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      mov(result, Immediate(0x7091));
16845913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      mov(result_end, Immediate(0x7191));
16855913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (scratch.is_valid()) {
16865913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        mov(scratch, Immediate(0x7291));
16875913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
16885913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // object_size is left unchanged by this function.
16895913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    }
16905913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    jmp(gc_required);
16915913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    return;
16925913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
1693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result.is(result_end));
1694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load address of new object into result.
16968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LoadAllocationTopHelper(result, scratch, flags);
1697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_limit =
1699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationLimitReference(isolate(), flags);
1700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Align the next allocation. Storing the filler map without checking top is
1702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // safe in new-space because the limit of the heap is aligned there.
1703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
1704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
1705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label aligned;
1706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(result, Immediate(kDoubleAlignmentMask));
1707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(zero, &aligned, Label::kNear);
1708014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if ((flags & PRETENURE) != 0) {
1709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cmp(result, Operand::StaticVariable(allocation_limit));
1710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      j(above_equal, gc_required);
1711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(Operand(result, 0),
1713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Immediate(isolate()->factory()->one_pointer_filler_map()));
1714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    add(result, Immediate(kDoubleSize / 2));
1715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&aligned);
1716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Calculate new top and bail out if space is exhausted.
1719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!object_size.is(result_end)) {
1720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(result_end, object_size);
1721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
17223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(result_end, result);
1723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(result_end, Operand::StaticVariable(allocation_limit));
1724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(above, gc_required);
1725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1726bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Tag result.
1727bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(kHeapObjectTag == 1);
1728bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  inc(result);
1729bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1730bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
1731bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // The top pointer is not updated for allocation folding dominators.
1732bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    UpdateAllocationTopHelper(result_end, scratch, flags);
1733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1734bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1735e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1736bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::FastAllocate(int object_size, Register result,
1737bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                  Register result_end, AllocationFlags flags) {
1738bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!result.is(result_end));
1739bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Load address of new object into result.
1740bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  LoadAllocationTopHelper(result, no_reg, flags);
1741bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1742bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
1743bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
1744bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Label aligned;
1745bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    test(result, Immediate(kDoubleAlignmentMask));
1746bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    j(zero, &aligned, Label::kNear);
1747bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    mov(Operand(result, 0),
1748bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        Immediate(isolate()->factory()->one_pointer_filler_map()));
1749bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    add(result, Immediate(kDoubleSize / 2));
1750bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    bind(&aligned);
1751bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1752bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1753bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  lea(result_end, Operand(result, object_size));
1754bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  UpdateAllocationTopHelper(result_end, no_reg, flags);
1755bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1756bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(kHeapObjectTag == 1);
1757bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  inc(result);
1758bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1759bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1760bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::FastAllocate(Register object_size, Register result,
1761bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                  Register result_end, AllocationFlags flags) {
1762bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!result.is(result_end));
1763bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Load address of new object into result.
1764bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  LoadAllocationTopHelper(result, no_reg, flags);
1765bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1766bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
1767bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
1768bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Label aligned;
1769bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    test(result, Immediate(kDoubleAlignmentMask));
1770bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    j(zero, &aligned, Label::kNear);
1771bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    mov(Operand(result, 0),
1772bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        Immediate(isolate()->factory()->one_pointer_filler_map()));
1773bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    add(result, Immediate(kDoubleSize / 2));
1774bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    bind(&aligned);
1775bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1776bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1777bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  lea(result_end, Operand(result, object_size, times_1, 0));
1778bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  UpdateAllocationTopHelper(result_end, no_reg, flags);
1779bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1780bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(kHeapObjectTag == 1);
1781bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  inc(result);
1782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::AllocateHeapNumber(Register result,
17863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                        Register scratch1,
17873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                        Register scratch2,
1788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        Label* gc_required,
1789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        MutableMode mode) {
17903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Allocate heap number in new space.
1791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(HeapNumber::kSize, result, scratch1, scratch2, gc_required,
1792bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
1793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Map> map = mode == MUTABLE
1795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ? isolate()->factory()->mutable_heap_number_map()
1796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : isolate()->factory()->heap_number_map();
17973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
17983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Set the map.
1799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(FieldOperand(result, HeapObject::kMapOffset), Immediate(map));
18003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
18013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
18023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1803d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::AllocateTwoByteString(Register result,
1804d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                           Register length,
1805d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                           Register scratch1,
1806d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                           Register scratch2,
1807d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                           Register scratch3,
1808d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                           Label* gc_required) {
1809d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Calculate the number of bytes needed for the characters in the string while
1810d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // observing object alignment.
1811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
1812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(kShortSize == 2);
1813e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // scratch1 = length * 2 + kObjectAlignmentMask.
1814e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  lea(scratch1, Operand(length, length, times_1, kObjectAlignmentMask));
18153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(scratch1, Immediate(~kObjectAlignmentMask));
1816d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1817d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Allocate two byte string in new space.
1818bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Allocate(SeqTwoByteString::kHeaderSize, times_1, scratch1,
1819bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           REGISTER_VALUE_IS_INT32, result, scratch2, scratch3, gc_required,
1820bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
1821d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1822d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Set the map, length and hash field.
1823d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  mov(FieldOperand(result, HeapObject::kMapOffset),
182444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Immediate(isolate()->factory()->string_map()));
18256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  mov(scratch1, length);
18266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  SmiTag(scratch1);
18276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  mov(FieldOperand(result, String::kLengthOffset), scratch1);
1828d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  mov(FieldOperand(result, String::kHashFieldOffset),
1829d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Immediate(String::kEmptyHashField));
1830d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1831d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1832d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AllocateOneByteString(Register result, Register length,
1834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register scratch1, Register scratch2,
1835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register scratch3,
1836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Label* gc_required) {
1837d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Calculate the number of bytes needed for the characters in the string while
1838d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // observing object alignment.
1839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0);
1840d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  mov(scratch1, length);
1841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(kCharSize == 1);
18423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(scratch1, Immediate(kObjectAlignmentMask));
18433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(scratch1, Immediate(~kObjectAlignmentMask));
1844d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Allocate one-byte string in new space.
1846bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Allocate(SeqOneByteString::kHeaderSize, times_1, scratch1,
1847bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           REGISTER_VALUE_IS_INT32, result, scratch2, scratch3, gc_required,
1848bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
1849d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1850d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Set the map, length and hash field.
1851d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  mov(FieldOperand(result, HeapObject::kMapOffset),
1852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Immediate(isolate()->factory()->one_byte_string_map()));
18536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  mov(scratch1, length);
18546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  SmiTag(scratch1);
18556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  mov(FieldOperand(result, String::kLengthOffset), scratch1);
1856d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  mov(FieldOperand(result, String::kHashFieldOffset),
1857d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Immediate(String::kEmptyHashField));
1858d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1859d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1860d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AllocateOneByteString(Register result, int length,
1862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register scratch1, Register scratch2,
1863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Label* gc_required) {
1864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(length > 0);
18659ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick
1866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Allocate one-byte string in new space.
1867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(SeqOneByteString::SizeFor(length), result, scratch1, scratch2,
1868bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           gc_required, NO_ALLOCATION_FLAGS);
18699ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick
18709ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  // Set the map, length and hash field.
18719ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  mov(FieldOperand(result, HeapObject::kMapOffset),
1872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Immediate(isolate()->factory()->one_byte_string_map()));
18739ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  mov(FieldOperand(result, String::kLengthOffset),
18749ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick      Immediate(Smi::FromInt(length)));
18759ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  mov(FieldOperand(result, String::kHashFieldOffset),
18769ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick      Immediate(String::kEmptyHashField));
18779ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick}
18789ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick
18799ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick
1880589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid MacroAssembler::AllocateTwoByteConsString(Register result,
1881d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                        Register scratch1,
1882d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                        Register scratch2,
1883d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                        Label* gc_required) {
1884d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Allocate heap number in new space.
1885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
1886bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
1887d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1888d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Set the map. The other fields are left uninitialized.
1889d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  mov(FieldOperand(result, HeapObject::kMapOffset),
189044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Immediate(isolate()->factory()->cons_string_map()));
1891d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1892d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1893d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AllocateOneByteConsString(Register result,
1895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register scratch1,
1896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register scratch2,
1897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Label* gc_required) {
1898bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
1899bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
1900d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1901d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Set the map. The other fields are left uninitialized.
1902d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  mov(FieldOperand(result, HeapObject::kMapOffset),
1903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Immediate(isolate()->factory()->cons_one_byte_string_map()));
1904d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1905d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1906b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1907589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid MacroAssembler::AllocateTwoByteSlicedString(Register result,
190869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                          Register scratch1,
190969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                          Register scratch2,
191069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                          Label* gc_required) {
191169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Allocate heap number in new space.
1912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
1913bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
191469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
191569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Set the map. The other fields are left uninitialized.
191669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  mov(FieldOperand(result, HeapObject::kMapOffset),
191769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      Immediate(isolate()->factory()->sliced_string_map()));
191869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
191969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
192069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
1921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AllocateOneByteSlicedString(Register result,
1922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                 Register scratch1,
1923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                 Register scratch2,
1924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                 Label* gc_required) {
192569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Allocate heap number in new space.
1926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
1927bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
192869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
192969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Set the map. The other fields are left uninitialized.
193069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  mov(FieldOperand(result, HeapObject::kMapOffset),
1931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Immediate(isolate()->factory()->sliced_one_byte_string_map()));
193269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
193369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
193469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
1935014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::AllocateJSValue(Register result, Register constructor,
1936014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                     Register value, Register scratch,
1937014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                     Label* gc_required) {
1938014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!result.is(constructor));
1939014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!result.is(scratch));
1940014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!result.is(value));
1941014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1942014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Allocate JSValue in new space.
1943bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Allocate(JSValue::kSize, result, scratch, no_reg, gc_required,
1944bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
1945014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1946014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Initialize the JSValue.
1947014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LoadGlobalFunctionInitialMap(constructor, scratch);
1948014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(FieldOperand(result, HeapObject::kMapOffset), scratch);
1949014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LoadRoot(scratch, Heap::kEmptyFixedArrayRootIndex);
1950014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(FieldOperand(result, JSObject::kPropertiesOffset), scratch);
1951014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(FieldOperand(result, JSObject::kElementsOffset), scratch);
1952014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(FieldOperand(result, JSValue::kValueOffset), value);
1953014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
1954014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1955014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1956014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1957b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// Copy memory, byte-by-byte, from source to destination.  Not optimized for
1958b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// long or aligned copies.  The contents of scratch and length are destroyed.
1959b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// Source and destination are incremented by length.
1960b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// Many variants of movsb, loop unrolling, word moves, and indexed operands
1961b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// have been tried here already, and this is fastest.
1962b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// A simpler loop is faster on small copies, but 30% slower on large ones.
1963b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// The cld() instruction must have been emitted, to set the direction flag(),
1964b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// before calling this function.
1965b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid MacroAssembler::CopyBytes(Register source,
1966b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                               Register destination,
1967b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                               Register length,
1968b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                               Register scratch) {
1969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label short_loop, len4, len8, len12, done, short_string;
1970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(source.is(esi));
1971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(destination.is(edi));
1972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(length.is(ecx));
1973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(length, Immediate(4));
1974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(below, &short_string, Label::kNear);
1975b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1976b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Because source is 4-byte aligned in our uses of this function,
1977b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // we keep source aligned for the rep_movs call by copying the odd bytes
1978b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // at the end of the ranges.
1979b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  mov(scratch, Operand(source, length, times_1, -4));
1980b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  mov(Operand(destination, length, times_1, -4), scratch);
1981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(length, Immediate(8));
1983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(below_equal, &len4, Label::kNear);
1984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(length, Immediate(12));
1985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(below_equal, &len8, Label::kNear);
1986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(length, Immediate(16));
1987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(below_equal, &len12, Label::kNear);
1988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1989b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  mov(scratch, ecx);
1990b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  shr(ecx, 2);
1991b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  rep_movs();
19923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(scratch, Immediate(0x3));
19933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(destination, scratch);
1994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  jmp(&done, Label::kNear);
1995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&len12);
1997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(scratch, Operand(source, 8));
1998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(Operand(destination, 8), scratch);
1999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&len8);
2000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(scratch, Operand(source, 4));
2001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(Operand(destination, 4), scratch);
2002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&len4);
2003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(scratch, Operand(source, 0));
2004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(Operand(destination, 0), scratch);
2005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  add(destination, length);
2006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  jmp(&done, Label::kNear);
2007b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
2008b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  bind(&short_string);
20093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(length, length);
2010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(zero, &done, Label::kNear);
2011b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
2012b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  bind(&short_loop);
2013b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  mov_b(scratch, Operand(source, 0));
2014b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  mov_b(Operand(destination, 0), scratch);
2015b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  inc(source);
2016b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  inc(destination);
2017b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  dec(length);
2018b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  j(not_zero, &short_loop);
2019b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
2020b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  bind(&done);
20218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
20228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
2023d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2024014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::InitializeFieldsWithFiller(Register current_address,
2025014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                Register end_address,
20263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Register filler) {
20273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label loop, entry;
2028109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  jmp(&entry, Label::kNear);
20293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&loop);
2030014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(Operand(current_address, 0), filler);
2031014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  add(current_address, Immediate(kPointerSize));
20323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&entry);
2033014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  cmp(current_address, end_address);
2034109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  j(below, &loop, Label::kNear);
20353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
20363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::BooleanBitTest(Register object,
20393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    int field_offset,
20403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    int bit_index) {
20413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bit_index += kSmiTagSize + kSmiShiftSize;
2042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(base::bits::IsPowerOfTwo32(kBitsPerByte));
20433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int byte_index = bit_index / kBitsPerByte;
20443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int byte_bit_index = bit_index & (kBitsPerByte - 1);
20453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test_b(FieldOperand(object, field_offset + byte_index),
20463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch         Immediate(1 << byte_bit_index));
20473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
20483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::NegativeZeroTest(Register result,
2052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register op,
2053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Label* then_label) {
2054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label ok;
20553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(result, result);
2056109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  j(not_zero, &ok, Label::kNear);
20573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(op, op);
2058109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  j(sign, then_label, Label::kNear);
2059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&ok);
2060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::NegativeZeroTest(Register result,
2064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register op1,
2065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register op2,
2066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register scratch,
2067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Label* then_label) {
2068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label ok;
20693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(result, result);
2070109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  j(not_zero, &ok, Label::kNear);
20713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(scratch, op1);
20723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  or_(scratch, op2);
2073109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  j(sign, then_label, Label::kNear);
2074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&ok);
2075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2078014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::GetMapConstructor(Register result, Register map,
2079014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                       Register temp) {
2080014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label done, loop;
2081014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(result, FieldOperand(map, Map::kConstructorOrBackPointerOffset));
2082014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&loop);
2083014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  JumpIfSmi(result, &done, Label::kNear);
2084014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CmpObjectType(result, MAP_TYPE, temp);
2085014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_equal, &done, Label::kNear);
2086014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(result, FieldOperand(result, Map::kConstructorOrBackPointerOffset));
2087014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  jmp(&loop);
2088014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&done);
2089014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
20903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2092014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::TryGetFunctionPrototype(Register function, Register result,
2093014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                             Register scratch, Label* miss) {
2094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the prototype or initial map from the function.
2095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(result,
2096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
2097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the prototype or initial map is the hole, don't return it and
2099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // simply miss the cache instead. This will allow us to allocate a
2100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // prototype object on-demand in the runtime system.
21013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmp(result, Immediate(isolate()->factory()->the_hole_value()));
2102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(equal, miss);
2103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the function does not have an initial map, we're done.
2105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label done;
2106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CmpObjectType(result, MAP_TYPE, scratch);
2107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_equal, &done, Label::kNear);
2108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the prototype from the initial map.
2110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(result, FieldOperand(result, Map::kPrototypeOffset));
2111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // All done.
2113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&done);
2114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CallStub(CodeStub* stub, TypeFeedbackId ast_id) {
2118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(AllowThisStubCall(stub));  // Calls are not allowed in some stubs.
2119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id);
2120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2123d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::TailCallStub(CodeStub* stub) {
2124d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  jmp(stub->GetCode(), RelocInfo::CODE_TARGET);
2125d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2126d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2127d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
212885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochvoid MacroAssembler::StubReturn(int argc) {
2129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(argc >= 1 && generating_stub());
213085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  ret((argc - 1) * kPointerSize);
2131592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch}
2132592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
2133592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
21343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
2135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return has_frame_ || !stub->SometimesSetsUpAFrame();
2136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
213980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::IndexFromHash(Register hash, Register index) {
214080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // The assert checks that the constants for the maximum number of digits
214180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // for an array index cached in the hash field and the number of bits
214280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // reserved for it does not conflict.
2143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(TenToThe(String::kMaxCachedArrayIndexLength) <
214480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen         (1 << String::kArrayIndexValueBits));
214580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (!index.is(hash)) {
214680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    mov(index, hash);
214780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
2148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DecodeFieldToSmi<String::ArrayIndexValueBits>(index);
2149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
215244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CallRuntime(const Runtime::Function* f,
2153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 int num_arguments,
2154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 SaveFPRegsMode save_doubles) {
2155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the expected number of arguments of the runtime function is
2156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // constant, we check that the actual number of arguments match the
2157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // expectation.
2158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(f->nargs < 0 || f->nargs == num_arguments);
2159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21604515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // TODO(1236192): Most runtime routines don't need the number of
21614515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // arguments passed in because it is constant. At some point we
21624515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // should remove this need and make the runtime routine entry code
21634515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // smarter.
2164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Move(eax, Immediate(num_arguments));
216544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  mov(ebx, Immediate(ExternalReference(f, isolate())));
2166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CEntryStub ces(isolate(), 1, save_doubles);
21674515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  CallStub(&ces);
2168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2171bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid MacroAssembler::CallExternalReference(ExternalReference ref,
2172bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                           int num_arguments) {
2173bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  mov(eax, Immediate(num_arguments));
2174bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  mov(ebx, Immediate(ref));
2175bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CEntryStub stub(isolate(), 1);
2177bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  CallStub(&stub);
2178bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
2179bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2180bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::TailCallRuntime(Runtime::FunctionId fid) {
2182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // ----------- S t a t e -------------
2183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  -- esp[0]                 : return address
2184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  -- esp[8]                 : argument num_arguments - 1
2185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  ...
2186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  -- esp[8 * num_arguments] : argument 0 (receiver)
2187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //
2188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  For runtime functions with variable arguments:
2189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  -- eax                    : number of  arguments
2190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // -----------------------------------
21913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const Runtime::Function* function = Runtime::FunctionForId(fid);
2193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(1, function->result_size);
2194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (function->nargs >= 0) {
2195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // TODO(1236192): Most runtime routines don't need the number of
2196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // arguments passed in because it is constant. At some point we
2197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // should remove this need and make the runtime routine entry code
2198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // smarter.
2199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mov(eax, Immediate(function->nargs));
2200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  JumpToExternalReference(ExternalReference(fid, isolate()));
2202d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2203d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
22056ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::JumpToExternalReference(const ExternalReference& ext) {
2206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set the entry point and jump to the C entry runtime stub.
2207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(ebx, Immediate(ext));
2208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CEntryStub ces(isolate(), 1);
2209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  jmp(ces.GetCode(), RelocInfo::CODE_TARGET);
2210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::PrepareForTailCall(
22133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    const ParameterCount& callee_args_count, Register caller_args_count_reg,
22143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Register scratch0, Register scratch1, ReturnAddressState ra_state,
22153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    int number_of_temp_values_after_return_address) {
22163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#if DEBUG
22173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (callee_args_count.is_reg()) {
22183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(!AreAliased(callee_args_count.reg(), caller_args_count_reg, scratch0,
22193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                       scratch1));
22203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
22213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(!AreAliased(caller_args_count_reg, scratch0, scratch1));
22223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
22233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK(ra_state != ReturnAddressState::kNotOnStack ||
22243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch         number_of_temp_values_after_return_address == 0);
22253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#endif
22263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
22273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Calculate the destination address where we will put the return address
22283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // after we drop current frame.
22293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Register new_sp_reg = scratch0;
22303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (callee_args_count.is_reg()) {
22313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    sub(caller_args_count_reg, callee_args_count.reg());
22323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    lea(new_sp_reg,
22333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Operand(ebp, caller_args_count_reg, times_pointer_size,
22343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                StandardFrameConstants::kCallerPCOffset -
22353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                    number_of_temp_values_after_return_address * kPointerSize));
22363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
22373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    lea(new_sp_reg, Operand(ebp, caller_args_count_reg, times_pointer_size,
22383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                            StandardFrameConstants::kCallerPCOffset -
22393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                (callee_args_count.immediate() +
22403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                 number_of_temp_values_after_return_address) *
22413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                    kPointerSize));
22423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
22433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
22443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (FLAG_debug_code) {
22453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    cmp(esp, new_sp_reg);
22463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Check(below, kStackAccessBelowStackPointer);
22473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
22483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
22493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Copy return address from caller's frame to current frame's return address
22503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // to avoid its trashing and let the following loop copy it to the right
22513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // place.
22523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Register tmp_reg = scratch1;
22533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (ra_state == ReturnAddressState::kOnStack) {
22543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    mov(tmp_reg, Operand(ebp, StandardFrameConstants::kCallerPCOffset));
22553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    mov(Operand(esp, number_of_temp_values_after_return_address * kPointerSize),
22563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        tmp_reg);
22573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
22583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(ReturnAddressState::kNotOnStack == ra_state);
22593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK_EQ(0, number_of_temp_values_after_return_address);
22603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Push(Operand(ebp, StandardFrameConstants::kCallerPCOffset));
22613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
22623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
22633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Restore caller's frame pointer now as it could be overwritten by
22643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // the copying loop.
22653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(ebp, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
22663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
22673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // +2 here is to copy both receiver and return address.
22683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Register count_reg = caller_args_count_reg;
22693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (callee_args_count.is_reg()) {
22703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    lea(count_reg, Operand(callee_args_count.reg(),
22713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                           2 + number_of_temp_values_after_return_address));
22723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
22733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    mov(count_reg, Immediate(callee_args_count.immediate() + 2 +
22743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                             number_of_temp_values_after_return_address));
22753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // TODO(ishell): Unroll copying loop for small immediate values.
22763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
22773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
22783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Now copy callee arguments to the caller frame going backwards to avoid
22793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // callee arguments corruption (source and destination areas could overlap).
22803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label loop, entry;
22813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  jmp(&entry, Label::kNear);
22823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&loop);
22833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  dec(count_reg);
22843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(tmp_reg, Operand(esp, count_reg, times_pointer_size, 0));
22853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(Operand(new_sp_reg, count_reg, times_pointer_size, 0), tmp_reg);
22863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&entry);
22873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  cmp(count_reg, Immediate(0));
22883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  j(not_equal, &loop, Label::kNear);
22893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
22903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Leave current frame.
22913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(esp, new_sp_reg);
22923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
2293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokePrologue(const ParameterCount& expected,
2295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    const ParameterCount& actual,
2296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Label* done,
22973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    bool* definitely_mismatches,
2298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                    InvokeFlag flag,
2299257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Label::Distance done_near,
2300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const CallWrapper& call_wrapper) {
2301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool definitely_matches = false;
23023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  *definitely_mismatches = false;
2303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label invoke;
2304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (expected.is_immediate()) {
2305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(actual.is_immediate());
2306014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mov(eax, actual.immediate());
2307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (expected.immediate() == actual.immediate()) {
2308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      definitely_matches = true;
2309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
2310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel;
2311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (expected.immediate() == sentinel) {
2312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Don't worry about adapting arguments for builtins that
2313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // don't want that done. Skip adaption code by making it look
2314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // like we have a match between expected and actual number of
2315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // arguments.
2316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        definitely_matches = true;
2317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
23183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        *definitely_mismatches = true;
2319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mov(ebx, expected.immediate());
2320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
2321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (actual.is_immediate()) {
2324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Expected is in register, actual is immediate. This is the
2325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // case when we invoke function values without going through the
2326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // IC mechanism.
2327014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      mov(eax, actual.immediate());
2328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      cmp(expected.reg(), actual.immediate());
2329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      j(equal, &invoke);
2330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(expected.reg().is(ebx));
2331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else if (!expected.reg().is(actual.reg())) {
2332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Both expected and actual are in (different) registers. This
2333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // is the case when we invoke functions using call and apply.
23343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      cmp(expected.reg(), actual.reg());
2335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      j(equal, &invoke);
2336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(actual.reg().is(eax));
2337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(expected.reg().is(ebx));
2338014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
2339014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Move(eax, actual.reg());
2340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!definitely_matches) {
2344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Handle<Code> adaptor =
234544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        isolate()->builtins()->ArgumentsAdaptorTrampoline();
2346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (flag == CALL_FUNCTION) {
2347257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      call_wrapper.BeforeCall(CallSize(adaptor, RelocInfo::CODE_TARGET));
2348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      call(adaptor, RelocInfo::CODE_TARGET);
2349257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      call_wrapper.AfterCall();
23503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (!*definitely_mismatches) {
23513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        jmp(done, done_near);
23523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
2353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
2354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      jmp(adaptor, RelocInfo::CODE_TARGET);
2355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bind(&invoke);
2357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2361014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::FloodFunctionIfStepping(Register fun, Register new_target,
2362014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                             const ParameterCount& expected,
2363014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                             const ParameterCount& actual) {
2364014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label skip_flooding;
2365014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ExternalReference step_in_enabled =
2366014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ExternalReference::debug_step_in_enabled_address(isolate());
23673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  cmpb(Operand::StaticVariable(step_in_enabled), Immediate(0));
2368014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(equal, &skip_flooding);
2369014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  {
2370014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    FrameScope frame(this,
2371014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     has_frame() ? StackFrame::NONE : StackFrame::INTERNAL);
2372014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (expected.is_reg()) {
2373014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SmiTag(expected.reg());
2374014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Push(expected.reg());
2375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
2376014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (actual.is_reg()) {
2377014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SmiTag(actual.reg());
2378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Push(actual.reg());
2379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
2380014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (new_target.is_valid()) {
2381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Push(new_target);
2382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
2383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(fun);
2384014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(fun);
2385109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    CallRuntime(Runtime::kDebugPrepareStepInIfStepping);
2386014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Pop(fun);
2387014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (new_target.is_valid()) {
2388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pop(new_target);
2389014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
2390014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (actual.is_reg()) {
2391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pop(actual.reg());
2392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SmiUntag(actual.reg());
2393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
2394014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (expected.is_reg()) {
2395014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pop(expected.reg());
2396014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SmiUntag(expected.reg());
2397014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
2398014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2399014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&skip_flooding);
2400014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2401014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2402014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::InvokeFunctionCode(Register function, Register new_target,
2404014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        const ParameterCount& expected,
2405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        const ParameterCount& actual,
2406014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        InvokeFlag flag,
2407014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        const CallWrapper& call_wrapper) {
24083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a function without a valid frame.
2409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(flag == JUMP_FUNCTION || has_frame());
2410014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(function.is(edi));
2411014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_IMPLIES(new_target.is_valid(), new_target.is(edx));
2412014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2413014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (call_wrapper.NeedsDebugStepCheck()) {
2414014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    FloodFunctionIfStepping(function, new_target, expected, actual);
2415014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2416014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2417014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Clear the new.target register if not given.
2418014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!new_target.is_valid()) {
2419014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mov(edx, isolate()->factory()->undefined_value());
2420014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
24213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2422257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
24233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool definitely_mismatches = false;
2424014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InvokePrologue(expected, actual, &done, &definitely_mismatches, flag,
2425014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 Label::kNear, call_wrapper);
24263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!definitely_mismatches) {
2427014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // We call indirectly through the code field in the function to
2428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // allow recompilation to take effect without changing any of the
2429014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // call sites.
2430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Operand code = FieldOperand(function, JSFunction::kCodeEntryOffset);
24313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (flag == CALL_FUNCTION) {
24323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call_wrapper.BeforeCall(CallSize(code));
24333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call(code);
24343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call_wrapper.AfterCall();
24353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
2436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(flag == JUMP_FUNCTION);
24373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      jmp(code);
24383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
24393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&done);
2440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeFunction(Register fun,
2445014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    Register new_target,
2446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    const ParameterCount& actual,
2447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                    InvokeFlag flag,
2448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const CallWrapper& call_wrapper) {
24493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a function without a valid frame.
2450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(flag == JUMP_FUNCTION || has_frame());
24513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(fun.is(edi));
2453014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
2454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
2455014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kFormalParameterCountOffset));
24567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  SmiUntag(ebx);
2457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ParameterCount expected(ebx);
2459014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InvokeFunctionCode(edi, new_target, expected, actual, flag, call_wrapper);
2460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::InvokeFunction(Register fun,
2464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const ParameterCount& expected,
2465402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                    const ParameterCount& actual,
2466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                    InvokeFlag flag,
2467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const CallWrapper& call_wrapper) {
24683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a function without a valid frame.
2469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(flag == JUMP_FUNCTION || has_frame());
24703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(fun.is(edi));
2472402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
2473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2474014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InvokeFunctionCode(edi, no_reg, expected, actual, flag, call_wrapper);
2475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::InvokeFunction(Handle<JSFunction> function,
2479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const ParameterCount& expected,
2480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const ParameterCount& actual,
2481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    InvokeFlag flag,
2482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const CallWrapper& call_wrapper) {
2483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LoadHeapObject(edi, function);
2484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InvokeFunction(edi, expected, actual, flag, call_wrapper);
2485402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
2486402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2488d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::LoadContext(Register dst, int context_chain_length) {
2489d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (context_chain_length > 0) {
2490d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Move up the chain of contexts to the context containing the slot.
24913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    mov(dst, Operand(esi, Context::SlotOffset(Context::PREVIOUS_INDEX)));
2492d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    for (int i = 1; i < context_chain_length; i++) {
24933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      mov(dst, Operand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX)));
2494d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
24951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
24961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Slot is in the current function context.  Move it into the
24971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // destination register in case we store into it (the write barrier
24981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // cannot be allowed to destroy the context in esi).
24991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    mov(dst, esi);
25001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
25011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
25023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // We should not have found a with context by walking the context chain
25031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // (i.e., the static scope chain and runtime context chain do not agree).
25041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // A variable occurring in such a scope should have slot type LOOKUP and
25051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // not CONTEXT.
250644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
25073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    cmp(FieldOperand(dst, HeapObject::kMapOffset),
25083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        isolate()->factory()->with_context_map());
2509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kVariableResolvedToWithContext);
2510d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2511d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2512d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2513d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2514014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LoadGlobalProxy(Register dst) {
2515014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(dst, NativeContextOperand());
2516014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(dst, ContextOperand(dst, Context::GLOBAL_PROXY_INDEX));
2517014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2518014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2519014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
25203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::LoadTransitionedArrayMapConditional(
25213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ElementsKind expected_kind,
25223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ElementsKind transitioned_kind,
25233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register map_in_out,
25243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch,
25253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* no_map_match) {
2526014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsFastElementsKind(expected_kind));
2527014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsFastElementsKind(transitioned_kind));
25283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check that the function's map is the same as the expected cached map.
2530014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(scratch, NativeContextOperand());
2531014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  cmp(map_in_out,
2532014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ContextOperand(scratch, Context::ArrayMapIndex(expected_kind)));
25333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_equal, no_map_match);
25343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Use the transitioned cached map.
2536014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(map_in_out,
2537014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ContextOperand(scratch, Context::ArrayMapIndex(transitioned_kind)));
25383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
25393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
254180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::LoadGlobalFunction(int index, Register function) {
2542014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Load the native context from the current context.
2543014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(function, NativeContextOperand());
2544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the function from the native context.
2545014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(function, ContextOperand(function, index));
254680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
254780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
254880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
254980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
255080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                                  Register map) {
255180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Load the initial map.  The global functions all have initial maps.
255280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  mov(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
255344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
255480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Label ok, fail;
2555257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CheckMap(map, isolate()->factory()->meta_map(), &fail, DO_SMI_CHECK);
255680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    jmp(&ok);
255780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    bind(&fail);
2558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Abort(kGlobalFunctionsMustHaveInitialMap);
255980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    bind(&ok);
256080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
256180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
256280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2563d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2564e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Store the value in register src in the safepoint register stack
2565e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// slot for register dst.
2566e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Register src) {
2567e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  mov(SafepointRegisterSlot(dst), src);
2568e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2569e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2570e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2571e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Immediate src) {
2572e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  mov(SafepointRegisterSlot(dst), src);
2573e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2574e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2575e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2576e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) {
2577e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  mov(dst, SafepointRegisterSlot(src));
2578e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2579e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2580e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2581e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochOperand MacroAssembler::SafepointRegisterSlot(Register reg) {
2582e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return Operand(esp, SafepointRegisterStackIndex(reg.code()) * kPointerSize);
2583e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2584e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2585e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochint MacroAssembler::SafepointRegisterStackIndex(int reg_code) {
2587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The registers are pushed starting with the lowest encoding,
2588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // which means that lowest encodings are furthest away from
2589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // the stack pointer.
2590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(reg_code >= 0 && reg_code < kNumSafepointRegisters);
2591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return kNumSafepointRegisters - reg_code - 1;
2592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
25953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::LoadHeapObject(Register result,
25963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    Handle<HeapObject> object) {
2597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllowDeferredHandleDereference embedding_raw_address;
25983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (isolate()->heap()->InNewSpace(*object)) {
2599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Cell> cell = isolate()->factory()->NewCell(object);
2600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(result, Operand::ForCell(cell));
26013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
26023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(result, object);
26033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
26043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
26053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CmpHeapObject(Register reg, Handle<HeapObject> object) {
2608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllowDeferredHandleDereference using_raw_address;
2609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (isolate()->heap()->InNewSpace(*object)) {
2610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Cell> cell = isolate()->factory()->NewCell(object);
2611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(reg, Operand::ForCell(cell));
2612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(reg, object);
2614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
26183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::PushHeapObject(Handle<HeapObject> object) {
2619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllowDeferredHandleDereference using_raw_address;
26203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (isolate()->heap()->InNewSpace(*object)) {
2621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Cell> cell = isolate()->factory()->NewCell(object);
2622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    push(Operand::ForCell(cell));
26233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
26243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Push(object);
26253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
26263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
26273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2629958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::CmpWeakValue(Register value, Handle<WeakCell> cell,
2630958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                  Register scratch) {
2631958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  mov(scratch, cell);
2632958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  cmp(value, FieldOperand(scratch, WeakCell::kValueOffset));
2633958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2634958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2635958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2636014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::GetWeakValue(Register value, Handle<WeakCell> cell) {
2637958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  mov(value, cell);
2638958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  mov(value, FieldOperand(value, WeakCell::kValueOffset));
2639014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2640014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2641014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2642014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LoadWeakValue(Register value, Handle<WeakCell> cell,
2643014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                   Label* miss) {
2644014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GetWeakValue(value, cell);
2645958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  JumpIfSmi(value, miss);
2646958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2647958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2648958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Ret() {
2650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ret(0);
2651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::Ret(int bytes_dropped, Register scratch) {
26551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (is_uint16(bytes_dropped)) {
26561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ret(bytes_dropped);
26571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
26581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    pop(scratch);
26593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    add(esp, Immediate(bytes_dropped));
26601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    push(scratch);
26611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ret(0);
26621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
26631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
26641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
26651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2666e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::Drop(int stack_elements) {
2667e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (stack_elements > 0) {
26683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    add(esp, Immediate(stack_elements * kPointerSize));
2669e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2670e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
2671e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2672e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
26730d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::Move(Register dst, Register src) {
26740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (!dst.is(src)) {
26750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    mov(dst, src);
26760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
26770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
26780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
26790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
2680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Move(Register dst, const Immediate& x) {
2681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (x.is_zero()) {
2682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    xor_(dst, dst);  // Shorter than mov of 32-bit immediate 0.
2683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(dst, x);
2685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Move(const Operand& dst, const Immediate& x) {
2690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(dst, x);
2691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2694958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::Move(XMMRegister dst, uint32_t src) {
2695958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (src == 0) {
2696958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    pxor(dst, dst);
2697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2698958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    unsigned cnt = base::bits::CountPopulation32(src);
2699958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    unsigned nlz = base::bits::CountLeadingZeros32(src);
2700958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    unsigned ntz = base::bits::CountTrailingZeros32(src);
2701958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (nlz + cnt + ntz == 32) {
2702958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      pcmpeqd(dst, dst);
2703958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (ntz == 0) {
2704958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        psrld(dst, 32 - cnt);
2705958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      } else {
2706958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        pslld(dst, 32 - cnt);
2707958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        if (nlz != 0) psrld(dst, nlz);
2708958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
2709958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
2710958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      push(eax);
2711958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      mov(eax, Immediate(src));
2712958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      movd(dst, Operand(eax));
2713958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      pop(eax);
2714958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
2715958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
2716958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2717958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2718958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2719958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::Move(XMMRegister dst, uint64_t src) {
2720014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (src == 0) {
2721014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    pxor(dst, dst);
2722958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
2723014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    uint32_t lower = static_cast<uint32_t>(src);
2724014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    uint32_t upper = static_cast<uint32_t>(src >> 32);
2725958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    unsigned cnt = base::bits::CountPopulation64(src);
2726958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    unsigned nlz = base::bits::CountLeadingZeros64(src);
2727958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    unsigned ntz = base::bits::CountTrailingZeros64(src);
2728958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (nlz + cnt + ntz == 64) {
2729958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      pcmpeqd(dst, dst);
2730958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (ntz == 0) {
2731958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        psrlq(dst, 64 - cnt);
2732958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      } else {
2733958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        psllq(dst, 64 - cnt);
2734958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        if (nlz != 0) psrlq(dst, nlz);
2735958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
2736958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else if (lower == 0) {
2737958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Move(dst, upper);
2738958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      psllq(dst, 32);
2739958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else if (CpuFeatures::IsSupported(SSE4_1)) {
2740958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      CpuFeatureScope scope(this, SSE4_1);
2741958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      push(eax);
2742958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Move(eax, Immediate(lower));
2743958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      movd(dst, Operand(eax));
2744958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Move(eax, Immediate(upper));
2745958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      pinsrd(dst, Operand(eax), 1);
2746958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      pop(eax);
2747958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
2748958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      push(Immediate(upper));
2749958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      push(Immediate(lower));
2750958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      movsd(dst, Operand(esp, 0));
2751958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      add(esp, Immediate(kDoubleSize));
2752958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
2753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2757014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Pextrd(Register dst, XMMRegister src, int8_t imm8) {
2758014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (imm8 == 0) {
2759014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movd(dst, src);
2760014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
2761014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2762014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(1, imm8);
2763014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(SSE4_1)) {
2764014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope sse_scope(this, SSE4_1);
2765014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    pextrd(dst, src, imm8);
2766014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
2767014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2768014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  pshufd(xmm0, src, 1);
2769014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movd(dst, xmm0);
2770014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2771014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2772014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2773014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Pinsrd(XMMRegister dst, const Operand& src, int8_t imm8) {
2774014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(imm8 == 0 || imm8 == 1);
2775014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(SSE4_1)) {
2776014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope sse_scope(this, SSE4_1);
2777014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    pinsrd(dst, src, imm8);
2778014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
2779014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2780014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movd(xmm0, src);
2781014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (imm8 == 1) {
2782014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    punpckldq(dst, xmm0);
2783014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2784014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK_EQ(0, imm8);
2785014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    psrlq(dst, 32);
2786014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    punpckldq(xmm0, dst);
2787014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movaps(dst, xmm0);
2788014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2789014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2790014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2791014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2792014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Lzcnt(Register dst, const Operand& src) {
2793014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(LZCNT)) {
2794014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, LZCNT);
2795014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    lzcnt(dst, src);
2796014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
2797014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2798014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label not_zero_src;
2799014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bsr(dst, src);
2800014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_zero, &not_zero_src, Label::kNear);
2801014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Move(dst, Immediate(63));  // 63^31 == 32
2802014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&not_zero_src);
2803014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  xor_(dst, Immediate(31));  // for x in [0..31], 31^x == 31-x.
2804014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2805014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2806014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2807014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Tzcnt(Register dst, const Operand& src) {
2808014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(BMI1)) {
2809014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, BMI1);
2810014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    tzcnt(dst, src);
2811014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
2812014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2813014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label not_zero_src;
2814014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bsf(dst, src);
2815014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_zero, &not_zero_src, Label::kNear);
2816014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Move(dst, Immediate(32));  // The result of tzcnt is 32 if src = 0.
2817014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&not_zero_src);
2818014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2819014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2820014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2821014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Popcnt(Register dst, const Operand& src) {
2822014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(POPCNT)) {
2823014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, POPCNT);
2824014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    popcnt(dst, src);
2825014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
2826014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2827014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  UNREACHABLE();
2828014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2829014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2830014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SetCounter(StatsCounter* counter, int value) {
2832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
2833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(Operand::StaticVariable(ExternalReference(counter)), Immediate(value));
2834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::IncrementCounter(StatsCounter* counter, int value) {
2839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(value > 0);
2840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
2841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Operand operand = Operand::StaticVariable(ExternalReference(counter));
2842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (value == 1) {
2843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      inc(operand);
2844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
2845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      add(operand, Immediate(value));
2846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::DecrementCounter(StatsCounter* counter, int value) {
2852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(value > 0);
2853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
2854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Operand operand = Operand::StaticVariable(ExternalReference(counter));
2855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (value == 1) {
2856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      dec(operand);
2857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
2858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      sub(operand, Immediate(value));
2859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2864d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid MacroAssembler::IncrementCounter(Condition cc,
2865d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                      StatsCounter* counter,
2866d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                      int value) {
2867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(value > 0);
2868d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (FLAG_native_code_counters && counter->Enabled()) {
2869d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Label skip;
2870d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    j(NegateCondition(cc), &skip);
2871d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    pushfd();
2872d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    IncrementCounter(counter, value);
2873d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    popfd();
2874d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    bind(&skip);
2875d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
2876d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
2877d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2878d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2879d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid MacroAssembler::DecrementCounter(Condition cc,
2880d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                      StatsCounter* counter,
2881d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                      int value) {
2882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(value > 0);
2883d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (FLAG_native_code_counters && counter->Enabled()) {
2884d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Label skip;
2885d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    j(NegateCondition(cc), &skip);
2886d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    pushfd();
2887d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    DecrementCounter(counter, value);
2888d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    popfd();
2889d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    bind(&skip);
2890d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
2891d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
2892d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2893d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Assert(Condition cc, BailoutReason reason) {
2895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) Check(cc, reason);
2896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2899756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid MacroAssembler::AssertFastElements(Register elements) {
290044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
290144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Factory* factory = isolate()->factory();
2902756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Label ok;
2903756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    cmp(FieldOperand(elements, HeapObject::kMapOffset),
290444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Immediate(factory->fixed_array_map()));
2905756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    j(equal, &ok);
2906756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    cmp(FieldOperand(elements, HeapObject::kMapOffset),
29073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        Immediate(factory->fixed_double_array_map()));
29083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    j(equal, &ok);
29093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    cmp(FieldOperand(elements, HeapObject::kMapOffset),
291044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Immediate(factory->fixed_cow_array_map()));
2911756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    j(equal, &ok);
2912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Abort(kJSObjectWithFastElementsMapHasSlowElements);
2913756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    bind(&ok);
2914756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
2915756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
2916756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2917756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Check(Condition cc, BailoutReason reason) {
2919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label L;
2920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(cc, &L);
2921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Abort(reason);
2922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // will not return here
2923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&L);
2924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29276ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::CheckStackAlignment() {
2928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int frame_alignment = base::OS::ActivationFrameAlignment();
29296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int frame_alignment_mask = frame_alignment - 1;
29306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (frame_alignment > kPointerSize) {
2931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
29326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Label alignment_as_expected;
29336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    test(esp, Immediate(frame_alignment_mask));
29346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    j(zero, &alignment_as_expected);
29356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Abort if stack is not aligned.
29366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int3();
29376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    bind(&alignment_as_expected);
29386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
29396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
29406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
29416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Abort(BailoutReason reason) {
2943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* msg = GetBailoutReason(reason);
2945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (msg != NULL) {
2946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RecordComment("Abort message: ");
2947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RecordComment(msg);
2948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_trap_on_abort) {
2951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int3();
2952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
2953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2955d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  push(Immediate(reinterpret_cast<intptr_t>(Smi::FromInt(reason))));
29573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Disable stub call restrictions to always allow calls to abort.
29583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!has_frame_) {
29593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // We don't actually want to generate a pile of code for this, so just
29603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // claim there is a stack frame, without generating one.
29613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(this, StackFrame::NONE);
2962109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    CallRuntime(Runtime::kAbort);
29633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
2964109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    CallRuntime(Runtime::kAbort);
29653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // will not return here
2967d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int3();
2968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2971257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::LoadInstanceDescriptors(Register map,
2972257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Register descriptors) {
2973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(descriptors, FieldOperand(map, Map::kDescriptorsOffset));
2974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) {
2978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(dst, FieldOperand(map, Map::kBitField3Offset));
2979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DecodeField<Map::NumberOfOwnDescriptorsBits>(dst);
2980756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
2981756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2982756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2983014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LoadAccessor(Register dst, Register holder,
2984014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  int accessor_index,
2985014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  AccessorComponent accessor) {
2986014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(dst, FieldOperand(holder, HeapObject::kMapOffset));
2987014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LoadInstanceDescriptors(dst, dst);
2988014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(dst, FieldOperand(dst, DescriptorArray::GetValueOffset(accessor_index)));
2989014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int offset = accessor == ACCESSOR_GETTER ? AccessorPair::kGetterOffset
2990014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                           : AccessorPair::kSetterOffset;
2991014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(dst, FieldOperand(dst, offset));
2992014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2993014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2994014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
29950d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::LoadPowerOf2(XMMRegister dst,
29960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                  Register scratch,
29970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                  int power) {
2998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uintn(power + HeapNumber::kExponentBias,
29990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                  HeapNumber::kExponentBits));
30000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  mov(scratch, Immediate(power + HeapNumber::kExponentBias));
30013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movd(dst, scratch);
30020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  psllq(dst, HeapNumber::kMantissaBits);
30030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
30040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
30050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
3006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfInstanceTypeIsNotSequentialOneByte(
3007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register instance_type, Register scratch, Label* failure) {
3008402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (!scratch.is(instance_type)) {
3009402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    mov(scratch, instance_type);
3010402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
3011402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  and_(scratch,
3012402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu       kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask);
3013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(scratch, kStringTag | kSeqStringTag | kOneByteStringTag);
3014402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  j(not_equal, failure);
3015402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
3016402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
3017402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
3018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfNotBothSequentialOneByteStrings(Register object1,
3019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                           Register object2,
3020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                           Register scratch1,
3021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                           Register scratch2,
3022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                           Label* failure) {
3023d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Check that both objects are not smis.
302469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
30253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(scratch1, object1);
30263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(scratch1, object2);
30273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  JumpIfSmi(scratch1, failure);
3028d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
3029d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Load instance type for both strings.
3030d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  mov(scratch1, FieldOperand(object1, HeapObject::kMapOffset));
3031d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  mov(scratch2, FieldOperand(object2, HeapObject::kMapOffset));
3032d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  movzx_b(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset));
3033d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  movzx_b(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset));
3034d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
3035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that both are flat one-byte strings.
3036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kFlatOneByteStringMask =
3037d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
3038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kFlatOneByteStringTag =
3039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kStringTag | kOneByteStringTag | kSeqStringTag;
3040d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Interleave bits from both instance types and compare them in one check.
3041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0, kFlatOneByteStringMask & (kFlatOneByteStringMask << 3));
3042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  and_(scratch1, kFlatOneByteStringMask);
3043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  and_(scratch2, kFlatOneByteStringMask);
3044d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  lea(scratch1, Operand(scratch1, scratch2, times_8, 0));
3045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(scratch1, kFlatOneByteStringTag | (kFlatOneByteStringTag << 3));
3046d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  j(not_equal, failure);
3047d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
3048d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
3049d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
3050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfNotUniqueNameInstanceType(Operand operand,
3051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                     Label* not_unique_name,
3052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                     Label::Distance distance) {
3053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
3054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label succeed;
3055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  test(operand, Immediate(kIsNotStringMask | kIsNotInternalizedMask));
3056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(zero, &succeed);
30573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  cmpb(operand, Immediate(SYMBOL_TYPE));
3058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(not_equal, not_unique_name, distance);
3059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&succeed);
3061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::EmitSeqStringSetCharCheck(Register string,
3065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register index,
3066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register value,
3067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               uint32_t encoding_mask) {
3068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label is_object;
3069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JumpIfNotSmi(string, &is_object, Label::kNear);
3070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Abort(kNonObject);
3071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&is_object);
3072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  push(value);
3074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(value, FieldOperand(string, HeapObject::kMapOffset));
3075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movzx_b(value, FieldOperand(value, Map::kInstanceTypeOffset));
3076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  and_(value, Immediate(kStringRepresentationMask | kStringEncodingMask));
3078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(value, Immediate(encoding_mask));
3079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pop(value);
3080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(equal, kUnexpectedStringType);
3081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The index is assumed to be untagged coming in, tag it to compare with the
3083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // string length without using a temp register, it is restored at the end of
3084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // this function.
3085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiTag(index);
3086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(no_overflow, kIndexIsTooLarge);
3087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(index, FieldOperand(string, String::kLengthOffset));
3089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(less, kIndexIsTooLarge);
3090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(index, Immediate(Smi::FromInt(0)));
3092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(greater_equal, kIndexIsNegative);
3093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Restore the index
3095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiUntag(index);
3096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
30996ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::PrepareCallCFunction(int num_arguments, Register scratch) {
3100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int frame_alignment = base::OS::ActivationFrameAlignment();
31018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (frame_alignment != 0) {
31026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Make stack end at alignment and make room for num_arguments words
31036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // and the original value of esp.
31046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    mov(scratch, esp);
31053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sub(esp, Immediate((num_arguments + 1) * kPointerSize));
3106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
31078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    and_(esp, -frame_alignment);
31086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    mov(Operand(esp, num_arguments * kPointerSize), scratch);
31096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
31103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sub(esp, Immediate(num_arguments * kPointerSize));
31116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
31126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
31136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
31146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
31156ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::CallCFunction(ExternalReference function,
31166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                   int num_arguments) {
31176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Trashing eax is ok as it will be the return value.
31183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(eax, Immediate(function));
31196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CallCFunction(eax, num_arguments);
31206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
31216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
31226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
31236ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::CallCFunction(Register function,
31246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                   int num_arguments) {
3125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(has_frame());
31266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check stack alignment.
312744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
31286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CheckStackAlignment();
31296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
31306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
31313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  call(function);
3132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (base::OS::ActivationFrameAlignment() != 0) {
31336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    mov(esp, Operand(esp, num_arguments * kPointerSize));
31346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
31353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    add(esp, Immediate(num_arguments * kPointerSize));
31366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
31376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
31386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
31396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
3141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool AreAliased(Register reg1,
3142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg2,
3143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg3,
3144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg4,
3145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg5,
3146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg6,
3147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg7,
3148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg8) {
3149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int n_of_valid_regs = reg1.is_valid() + reg2.is_valid() +
3150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reg3.is_valid() + reg4.is_valid() + reg5.is_valid() + reg6.is_valid() +
3151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reg7.is_valid() + reg8.is_valid();
3152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RegList regs = 0;
3154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg1.is_valid()) regs |= reg1.bit();
3155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg2.is_valid()) regs |= reg2.bit();
3156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg3.is_valid()) regs |= reg3.bit();
3157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg4.is_valid()) regs |= reg4.bit();
3158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg5.is_valid()) regs |= reg5.bit();
3159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg6.is_valid()) regs |= reg6.bit();
3160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg7.is_valid()) regs |= reg7.bit();
3161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg8.is_valid()) regs |= reg8.bit();
3162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int n_of_non_aliasing_regs = NumRegs(regs);
3163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return n_of_valid_regs != n_of_non_aliasing_regs;
31653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
31673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochCodePatcher::CodePatcher(Isolate* isolate, byte* address, int size)
31708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    : address_(address),
31718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      size_(size),
3172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      masm_(isolate, address, size + Assembler::kGap, CodeObjectRequired::kNo) {
3173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a new macro assembler pointing to the address of the code to patch.
3174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The size is adjusted with kGap on order for the assembler to generate size
3175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // bytes of instructions without failing with buffer size constraints.
3176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
3177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCodePatcher::~CodePatcher() {
3181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Indicate that code has changed.
3182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Assembler::FlushICache(masm_.isolate(), address_, size_);
3183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the code was patched as expected.
3185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(masm_.pc_ == address_ + size_);
3186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
3187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
31903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckPageFlag(
31913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register object,
31923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch,
31933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int mask,
31943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Condition cc,
31953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* condition_met,
31963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label::Distance condition_met_distance) {
3197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(cc == zero || cc == not_zero);
31983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (scratch.is(object)) {
31993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    and_(scratch, Immediate(~Page::kPageAlignmentMask));
32003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
32013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(scratch, Immediate(~Page::kPageAlignmentMask));
32023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    and_(scratch, object);
32033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
32043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (mask < (1 << kBitsPerByte)) {
32053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    test_b(Operand(scratch, MemoryChunk::kFlagsOffset), Immediate(mask));
32063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
32073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    test(Operand(scratch, MemoryChunk::kFlagsOffset), Immediate(mask));
32083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
32093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(cc, condition_met, condition_met_distance);
32103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
32113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CheckPageFlagForMap(
3214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Map> map,
3215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int mask,
3216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Condition cc,
3217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label* condition_met,
3218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label::Distance condition_met_distance) {
3219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(cc == zero || cc == not_zero);
3220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Page* page = Page::FromAddress(map->address());
3221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!serializer_enabled());  // Serializer cannot match page_flags.
3222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference reference(ExternalReference::page_flags(page));
3223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The inlined static address check of the page's flags relies
3224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // on maps never being compacted.
3225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!isolate()->heap()->mark_compact_collector()->
3226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         IsOnEvacuationCandidate(*map));
3227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (mask < (1 << kBitsPerByte)) {
32283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    test_b(Operand::StaticVariable(reference), Immediate(mask));
3229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(Operand::StaticVariable(reference), Immediate(mask));
3231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(cc, condition_met, condition_met_distance);
3233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
32363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::JumpIfBlack(Register object,
32373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register scratch0,
32383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register scratch1,
32393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Label* on_black,
32403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Label::Distance on_black_near) {
3241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  HasColor(object, scratch0, scratch1, on_black, on_black_near, 1,
3242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch           1);  // kBlackBitPattern.
3243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0);
32443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
32453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::HasColor(Register object,
32483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Register bitmap_scratch,
32493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Register mask_scratch,
32503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Label* has_color,
32513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Label::Distance has_color_distance,
32523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              int first_bit,
32533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              int second_bit) {
3254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(object, bitmap_scratch, mask_scratch, ecx));
32553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GetMarkBits(object, bitmap_scratch, mask_scratch);
32573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label other_color, word_boundary;
32593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
32603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(first_bit == 1 ? zero : not_zero, &other_color, Label::kNear);
32613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(mask_scratch, mask_scratch);  // Shift left 1 by adding.
32623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(zero, &word_boundary, Label::kNear);
32633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
32643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(second_bit == 1 ? not_zero : zero, has_color, has_color_distance);
32653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  jmp(&other_color, Label::kNear);
32663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&word_boundary);
32683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test_b(Operand(bitmap_scratch, MemoryChunk::kHeaderSize + kPointerSize),
32693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch         Immediate(1));
32703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(second_bit == 1 ? not_zero : zero, has_color, has_color_distance);
32723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&other_color);
32733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
32743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::GetMarkBits(Register addr_reg,
32773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register bitmap_reg,
32783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register mask_reg) {
3279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(addr_reg, mask_reg, bitmap_reg, ecx));
32803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(bitmap_reg, Immediate(~Page::kPageAlignmentMask));
32813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(bitmap_reg, addr_reg);
32823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(ecx, addr_reg);
32833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int shift =
32843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Bitmap::kBitsPerCellLog2 + kPointerSizeLog2 - Bitmap::kBytesPerCellLog2;
32853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  shr(ecx, shift);
32863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(ecx,
32873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       (Page::kPageAlignmentMask >> shift) & ~(Bitmap::kBytesPerCell - 1));
32883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(bitmap_reg, ecx);
32903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(ecx, addr_reg);
32913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  shr(ecx, kPointerSizeLog2);
32923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(ecx, (1 << Bitmap::kBitsPerCellLog2) - 1);
32933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(mask_reg, Immediate(1));
32943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  shl_cl(mask_reg);
32953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
32963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3298014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::JumpIfWhite(Register value, Register bitmap_scratch,
3299014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 Register mask_scratch, Label* value_is_white,
3300014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 Label::Distance distance) {
3301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(value, bitmap_scratch, mask_scratch, ecx));
33023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GetMarkBits(value, bitmap_scratch, mask_scratch);
33033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If the value is black or grey we don't need to do anything.
3305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0);
3306014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0);
3307014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(strcmp(Marking::kGreyBitPattern, "10") == 0);
3308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0);
33093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Since both black and grey have a 1 in the first position and white does
33113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // not have a 1 there we only need to check one bit.
33123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
3313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(zero, value_is_white, Label::kNear);
33143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
33153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::EnumLength(Register dst, Register map) {
3318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(Map::EnumLengthBits::kShift == 0);
3319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(dst, FieldOperand(map, Map::kBitField3Offset));
3320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  and_(dst, Immediate(Map::EnumLengthBits::kMask));
3321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiTag(dst);
3322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
33253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckEnumCache(Label* call_runtime) {
3326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label next, start;
33273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(ecx, eax);
3328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check if the enum length field is properly initialized, indicating that
3330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // there is an enum cache.
3331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset));
3332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EnumLength(edx, ebx);
3334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(edx, Immediate(Smi::FromInt(kInvalidEnumCacheSentinel)));
3335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(equal, call_runtime);
3336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  jmp(&start);
3338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
33393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&next);
3340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset));
33413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // For all objects but the receiver, check that the cache is empty.
3343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EnumLength(edx, ebx);
3344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(edx, Immediate(Smi::FromInt(0)));
33453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_equal, call_runtime);
33463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&start);
33483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that there are no elements. Register rcx contains the current JS
3350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // object we've reached through the prototype chain.
3351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label no_elements;
3352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset));
3353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(ecx, isolate()->factory()->empty_fixed_array());
3354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(equal, &no_elements);
33553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Second chance, the object may be using the empty slow element dictionary.
3357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(ecx, isolate()->factory()->empty_slow_element_dictionary());
33583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_equal, call_runtime);
33593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&no_elements);
33613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset));
33623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmp(ecx, isolate()->factory()->null_value());
33633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_equal, &next);
33643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
33653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TestJSArrayForAllocationMemento(
3368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register receiver_reg,
3369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch_reg,
3370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label* no_memento_found) {
33713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label map_check;
33723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label top_check;
3373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference new_space_allocation_top =
3374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::new_space_allocation_top_address(isolate());
33753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  const int kMementoMapOffset = JSArray::kSize - kHeapObjectTag;
33763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  const int kMementoEndOffset = kMementoMapOffset + AllocationMemento::kSize;
33773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
33783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Bail out if the object is not in new space.
33793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  JumpIfNotInNewSpace(receiver_reg, scratch_reg, no_memento_found);
33803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // If the object is in new space, we need to check whether it is on the same
33813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // page as the current top.
33823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  lea(scratch_reg, Operand(receiver_reg, kMementoEndOffset));
33833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  xor_(scratch_reg, Operand::StaticVariable(new_space_allocation_top));
33843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test(scratch_reg, Immediate(~Page::kPageAlignmentMask));
33853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  j(zero, &top_check);
33863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // The object is on a different page than allocation top. Bail out if the
33873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // object sits on the page boundary as no memento can follow and we cannot
33883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // touch the memory following it.
33893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  lea(scratch_reg, Operand(receiver_reg, kMementoEndOffset));
33903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  xor_(scratch_reg, receiver_reg);
33913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test(scratch_reg, Immediate(~Page::kPageAlignmentMask));
33923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  j(not_zero, no_memento_found);
33933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Continue with the actual map check.
33943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  jmp(&map_check);
33953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // If top is on the same page as the current object, we need to check whether
33963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // we are below top.
33973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&top_check);
33983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  lea(scratch_reg, Operand(receiver_reg, kMementoEndOffset));
3399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(scratch_reg, Operand::StaticVariable(new_space_allocation_top));
3400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(greater, no_memento_found);
34013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Memento map check.
34023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&map_check);
34033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(scratch_reg, Operand(receiver_reg, kMementoMapOffset));
34043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  cmp(scratch_reg, Immediate(isolate()->factory()->allocation_memento_map()));
3405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfDictionaryInPrototypeChain(
3409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register object,
3410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch0,
3411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch1,
3412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label* found) {
3413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!scratch1.is(scratch0));
3414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Factory* factory = isolate()->factory();
3415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register current = scratch0;
3416014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label loop_again, end;
3417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // scratch contained elements pointer.
3419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(current, object);
3420014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(current, FieldOperand(current, HeapObject::kMapOffset));
3421014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(current, FieldOperand(current, Map::kPrototypeOffset));
3422014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  cmp(current, Immediate(factory->null_value()));
3423014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(equal, &end);
3424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Loop based on the map going up the prototype chain.
3426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&loop_again);
3427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(current, FieldOperand(current, HeapObject::kMapOffset));
3428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(JS_PROXY_TYPE < JS_OBJECT_TYPE);
3429014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(JS_VALUE_TYPE < JS_OBJECT_TYPE);
3430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CmpInstanceType(current, JS_OBJECT_TYPE);
3431014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(below, found);
3432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(scratch1, FieldOperand(current, Map::kBitField2Offset));
3433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DecodeField<Map::ElementsKindBits>(scratch1);
3434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(scratch1, Immediate(DICTIONARY_ELEMENTS));
3435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(equal, found);
3436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(current, FieldOperand(current, Map::kPrototypeOffset));
3437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(current, Immediate(factory->null_value()));
3438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(not_equal, &loop_again);
3439014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3440014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&end);
3441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TruncatingDiv(Register dividend, int32_t divisor) {
3445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dividend.is(eax));
3446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dividend.is(edx));
3447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::MagicNumbersForDivision<uint32_t> mag =
3448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      base::SignedDivisionByConstant(static_cast<uint32_t>(divisor));
3449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(eax, Immediate(mag.multiplier));
3450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  imul(dividend);
3451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool neg = (mag.multiplier & (static_cast<uint32_t>(1) << 31)) != 0;
3452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor > 0 && neg) add(edx, dividend);
3453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor < 0 && !neg && mag.multiplier > 0) sub(edx, dividend);
3454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (mag.shift > 0) sar(edx, mag.shift);
3455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(eax, dividend);
3456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shr(eax, 31);
3457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  add(edx, eax);
3458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3461014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
3462014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
3463f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3464f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_IA32
3465