13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_IA32
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/bits.h"
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/division-by-constant.h"
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/bootstrapper.h"
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h"
11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/debug/debug.h"
12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/ia32/frames-ia32.h"
13014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/ia32/macro-assembler-ia32.h"
14958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/runtime/runtime.h"
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -------------------------------------------------------------------------
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// MacroAssembler implementation.
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochMacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size,
23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                               CodeObjectRequired create_code_object)
248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    : Assembler(arg_isolate, buffer, size),
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      generating_stub_(false),
263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      has_frame_(false) {
27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (create_code_object == CodeObjectRequired::kYes) {
28014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    code_object_ =
29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Handle<Object>::New(isolate()->heap()->undefined_value(), isolate());
308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Load(Register dst, const Operand& src, Representation r) {
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!r.IsDouble());
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (r.IsInteger8()) {
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movsx_b(dst, src);
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsUInteger8()) {
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movzx_b(dst, src);
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsInteger16()) {
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movsx_w(dst, src);
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsUInteger16()) {
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movzx_w(dst, src);
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(dst, src);
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Store(Register src, const Operand& dst, Representation r) {
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!r.IsDouble());
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (r.IsInteger8() || r.IsUInteger8()) {
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov_b(dst, src);
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsInteger16() || r.IsUInteger16()) {
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov_w(dst, src);
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (r.IsHeapObject()) {
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AssertNotSmi(src);
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (r.IsSmi()) {
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AssertSmi(src);
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(dst, src);
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index) {
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (isolate()->heap()->RootCanBeTreatedAsConstant(index)) {
69014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mov(destination, isolate()->heap()->root_handle(index));
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference roots_array_start =
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::roots_array_start(isolate());
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(destination, Immediate(index));
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(destination, Operand::StaticArray(destination,
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        times_pointer_size,
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        roots_array_start));
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::StoreRoot(Register source,
82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Register scratch,
83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Heap::RootListIndex index) {
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(Heap::RootCanBeWrittenAfterInitialization(index));
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference roots_array_start =
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::roots_array_start(isolate());
87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(scratch, Immediate(index));
88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(Operand::StaticArray(scratch, times_pointer_size, roots_array_start),
89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      source);
90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CompareRoot(Register with,
94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Register scratch,
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Heap::RootListIndex index) {
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference roots_array_start =
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::roots_array_start(isolate());
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(scratch, Immediate(index));
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(with, Operand::StaticArray(scratch,
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                times_pointer_size,
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                roots_array_start));
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) {
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(isolate()->heap()->RootCanBeTreatedAsConstant(index));
107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  cmp(with, isolate()->heap()->root_handle(index));
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CompareRoot(const Operand& with,
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Heap::RootListIndex index) {
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(isolate()->heap()->RootCanBeTreatedAsConstant(index));
114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  cmp(with, isolate()->heap()->root_handle(index));
115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::PushRoot(Heap::RootListIndex index) {
119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(isolate()->heap()->RootCanBeTreatedAsConstant(index));
120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Push(isolate()->heap()->root_handle(index));
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
123109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#define REG(Name) \
124109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  { Register::kCode_##Name }
125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
126109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochstatic const Register saved_regs[] = {REG(eax), REG(ecx), REG(edx)};
127109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
128109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#undef REG
129109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
130109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochstatic const int kNumberOfSavedRegs = sizeof(saved_regs) / sizeof(Register);
131109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
132109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::PushCallerSaved(SaveFPRegsMode fp_mode,
133109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                     Register exclusion1, Register exclusion2,
134109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                     Register exclusion3) {
135109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // We don't allow a GC during a store buffer overflow so there is no need to
136109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // store the registers in any particular way, but we do have to store and
137109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // restore them.
138109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  for (int i = 0; i < kNumberOfSavedRegs; i++) {
139109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Register reg = saved_regs[i];
140109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    if (!reg.is(exclusion1) && !reg.is(exclusion2) && !reg.is(exclusion3)) {
141109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      push(reg);
142109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
143109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
144109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (fp_mode == kSaveFPRegs) {
145109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    sub(esp, Immediate(kDoubleSize * (XMMRegister::kMaxNumRegisters - 1)));
146109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // Save all XMM registers except XMM0.
147109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    for (int i = XMMRegister::kMaxNumRegisters - 1; i > 0; i--) {
148109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      XMMRegister reg = XMMRegister::from_code(i);
149109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      movsd(Operand(esp, (i - 1) * kDoubleSize), reg);
150109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
151109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
152109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
153109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
154109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
155109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                    Register exclusion2, Register exclusion3) {
156109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (fp_mode == kSaveFPRegs) {
157109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // Restore all XMM registers except XMM0.
158109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    for (int i = XMMRegister::kMaxNumRegisters - 1; i > 0; i--) {
159109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      XMMRegister reg = XMMRegister::from_code(i);
160109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      movsd(reg, Operand(esp, (i - 1) * kDoubleSize));
161109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
162109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    add(esp, Immediate(kDoubleSize * (XMMRegister::kMaxNumRegisters - 1)));
163109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
164109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
165109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  for (int i = kNumberOfSavedRegs - 1; i >= 0; i--) {
166109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Register reg = saved_regs[i];
167109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    if (!reg.is(exclusion1) && !reg.is(exclusion2) && !reg.is(exclusion3)) {
168109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      pop(reg);
169109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
1706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
171109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
172109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
173109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::InNewSpace(Register object, Register scratch, Condition cc,
174109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                Label* condition_met,
175109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                Label::Distance distance) {
176f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  CheckPageFlag(object, scratch, MemoryChunk::kIsInNewSpaceMask, cc,
177f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                condition_met, distance);
1783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::RememberedSetHelper(
1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register object,  // Only used for debug checks.
1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register addr,
1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch,
1853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SaveFPRegsMode save_fp,
1863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MacroAssembler::RememberedSetFinalAction and_then) {
1873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
1893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label ok;
1903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JumpIfNotInNewSpace(object, scratch, &ok, Label::kNear);
1913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int3();
1923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&ok);
1933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load store buffer top.
1953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExternalReference store_buffer =
1963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ExternalReference::store_buffer_top(isolate());
1973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(scratch, Operand::StaticVariable(store_buffer));
1983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Store pointer to buffer.
1993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(Operand(scratch, 0), addr);
2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Increment buffer top.
2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(scratch, Immediate(kPointerSize));
2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Write back new top of buffer.
2033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(Operand::StaticVariable(store_buffer), scratch);
2043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Call stub on end of buffer.
2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for end of buffer.
2063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test(scratch, Immediate(StoreBuffer::kStoreBufferMask));
2073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (and_then == kReturnAtEnd) {
2083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label buffer_overflowed;
2093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    j(equal, &buffer_overflowed, Label::kNear);
2103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ret(0);
2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&buffer_overflowed);
2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(and_then == kFallThroughAtEnd);
2143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    j(not_equal, &done, Label::kNear);
2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StoreBufferOverflowStub store_buffer_overflow(isolate(), save_fp);
2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallStub(&store_buffer_overflow);
2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (and_then == kReturnAtEnd) {
2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ret(0);
2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(and_then == kFallThroughAtEnd);
2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&done);
2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::ClampDoubleToUint8(XMMRegister input_reg,
228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                        XMMRegister scratch_reg,
229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                        Register result_reg) {
230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label conv_failure;
232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  xorps(scratch_reg, scratch_reg);
233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cvtsd2si(result_reg, input_reg);
234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  test(result_reg, Immediate(0xFFFFFF00));
235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(zero, &done, Label::kNear);
236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(result_reg, Immediate(0x1));
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(overflow, &conv_failure, Label::kNear);
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(result_reg, Immediate(0));
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  setcc(sign, result_reg);
240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  sub(result_reg, Immediate(1));
241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  and_(result_reg, Immediate(255));
242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  jmp(&done, Label::kNear);
243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&conv_failure);
244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Move(result_reg, Immediate(0));
245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ucomisd(input_reg, scratch_reg);
246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(below, &done, Label::kNear);
247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Move(result_reg, Immediate(255));
248257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&done);
249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::ClampUint8(Register reg) {
253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  test(reg, Immediate(0xFFFFFF00));
255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(zero, &done, Label::kNear);
256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  setcc(negative, reg);  // 1 if negative, 0 if positive.
257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  dec_b(reg);  // 0 if negative, 255 if positive.
258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&done);
259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::SlowTruncateToI(Register result_reg,
263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     Register input_reg,
264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     int offset) {
265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleToIStub stub(isolate(), input_reg, result_reg, offset, true);
266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  call(stub.GetCode(), RelocInfo::CODE_TARGET);
267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TruncateDoubleToI(Register result_reg,
271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       XMMRegister input_reg) {
272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cvttsd2si(result_reg, Operand(input_reg));
274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(result_reg, 0x1);
275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(no_overflow, &done, Label::kNear);
276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  sub(esp, Immediate(kDoubleSize));
278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movsd(MemOperand(esp, 0), input_reg);
279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SlowTruncateToI(result_reg, esp, 0);
280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  add(esp, Immediate(kDoubleSize));
281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::DoubleToI(Register result_reg, XMMRegister input_reg,
286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               XMMRegister scratch,
287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               MinusZeroMode minus_zero_mode,
288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Label* lost_precision, Label* is_nan,
289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Label* minus_zero, Label::Distance dst) {
290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!input_reg.is(scratch));
291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cvttsd2si(result_reg, Operand(input_reg));
292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Cvtsi2sd(scratch, Operand(result_reg));
293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ucomisd(scratch, input_reg);
294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(not_equal, lost_precision, dst);
295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(parity_even, is_nan, dst);
296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (minus_zero_mode == FAIL_ON_MINUS_ZERO) {
297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label done;
298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // The integer converted back is equal to the original. We
299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // only have to test if we got -0 as an input.
300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(result_reg, Operand(result_reg));
301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(not_zero, &done, Label::kNear);
302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movmskpd(result_reg, input_reg);
303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Bit 0 contains the sign of the double in input_reg.
304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If input was positive, we are ok and return 0, otherwise
305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // jump to minus_zero.
306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    and_(result_reg, 1);
307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(not_zero, minus_zero, dst);
308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&done);
309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TruncateHeapNumberToI(Register result_reg,
314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register input_reg) {
315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done, slow_case;
316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (CpuFeatures::IsSupported(SSE3)) {
318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CpuFeatureScope scope(this, SSE3);
319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label convert;
320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Use more powerful conversion when sse3 is available.
321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Load x87 register with heap number.
322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Get exponent alone and check for too-big exponent.
324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(result_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset));
325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    and_(result_reg, HeapNumber::kExponentMask);
326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const uint32_t kTooBigExponent =
327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift;
328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(Operand(result_reg), Immediate(kTooBigExponent));
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(greater_equal, &slow_case, Label::kNear);
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Reserve space for 64 bit answer.
332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sub(Operand(esp), Immediate(kDoubleSize));
333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Do conversion, which cannot fail because we checked the exponent.
334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    fisttp_d(Operand(esp, 0));
335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(result_reg, Operand(esp, 0));  // Low word of answer is the result.
336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    add(Operand(esp), Immediate(kDoubleSize));
337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    jmp(&done, Label::kNear);
338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Slow case.
340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&slow_case);
341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (input_reg.is(result_reg)) {
342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Input is clobbered. Restore number from fpu stack
343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      sub(Operand(esp), Immediate(kDoubleSize));
344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      fstp_d(Operand(esp, 0));
345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SlowTruncateToI(result_reg, esp, 0);
346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      add(esp, Immediate(kDoubleSize));
347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      fstp(0);
349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SlowTruncateToI(result_reg, input_reg);
350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cvttsd2si(result_reg, Operand(xmm0));
354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(result_reg, 0x1);
355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(no_overflow, &done, Label::kNear);
356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Check if the input was 0x8000000 (kMinInt).
357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If no, then we got an overflow and we deoptimize.
358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ExternalReference min_int = ExternalReference::address_of_min_int();
359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ucomisd(xmm0, Operand::StaticVariable(min_int));
360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(not_equal, &slow_case, Label::kNear);
361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(parity_even, &slow_case, Label::kNear);  // NaN.
362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    jmp(&done, Label::kNear);
363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Slow case.
365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&slow_case);
366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (input_reg.is(result_reg)) {
367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Input is clobbered. Restore number from double scratch.
368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      sub(esp, Immediate(kDoubleSize));
369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movsd(MemOperand(esp, 0), xmm0);
370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SlowTruncateToI(result_reg, esp, 0);
371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      add(esp, Immediate(kDoubleSize));
372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SlowTruncateToI(result_reg, input_reg);
374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
380958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::LoadUint32(XMMRegister dst, const Operand& src) {
381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(src, Immediate(0));
383958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ExternalReference uint32_bias = ExternalReference::address_of_uint32_bias();
384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Cvtsi2sd(dst, src);
385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(not_sign, &done, Label::kNear);
386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  addsd(dst, Operand::StaticVariable(uint32_bias));
387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::RecordWriteArray(
392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register object,
393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register value,
394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register index,
395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SaveFPRegsMode save_fp,
396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RememberedSetAction remembered_set_action,
397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiCheck smi_check,
398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PointersToHereCheck pointers_to_here_check_for_value) {
3993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // First, check if a write barrier is even needed. The tests below
4003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // catch stores of Smis.
4013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Skip barrier if writing a smi.
4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (smi_check == INLINE_SMI_CHECK) {
405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_EQ(0, kSmiTag);
4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    test(value, Immediate(kSmiTagMask));
4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(zero, &done);
4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Array access: calculate the destination address in the same manner as
4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // KeyedStoreIC::GenerateGeneric.  Multiply a smi by 2 to get an offset
4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // into an array of words.
4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register dst = index;
4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lea(dst, Operand(object, index, times_half_pointer_size,
4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   FixedArray::kHeaderSize - kHeapObjectTag));
4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordWrite(object, dst, value, save_fp, remembered_set_action,
418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              OMIT_SMI_CHECK, pointers_to_here_check_for_value);
4193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&done);
4213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Clobber clobbered input registers when running with the debug-code flag
4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // turned on to provoke errors.
4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (emit_debug_code()) {
425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(value, Immediate(bit_cast<int32_t>(kZapValue)));
426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(index, Immediate(bit_cast<int32_t>(kZapValue)));
427257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::RecordWriteField(
4323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register object,
4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int offset,
4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register value,
4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register dst,
4363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SaveFPRegsMode save_fp,
4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RememberedSetAction remembered_set_action,
438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiCheck smi_check,
439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PointersToHereCheck pointers_to_here_check_for_value) {
4407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // First, check if a write barrier is even needed. The tests below
4413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // catch stores of Smis.
442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Skip barrier if writing a smi.
4453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (smi_check == INLINE_SMI_CHECK) {
4463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JumpIfSmi(value, &done, Label::kNear);
4473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Although the object register is tagged, the offset is relative to the start
4503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // of the object, so so offset must be a multiple of kPointerSize.
451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsAligned(offset, kPointerSize));
452592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
4533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lea(dst, FieldOperand(object, offset));
4543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (emit_debug_code()) {
4553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label ok;
4563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    test_b(dst, Immediate((1 << kPointerSizeLog2) - 1));
4573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(zero, &ok, Label::kNear);
4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int3();
4593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&ok);
46085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  }
4613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordWrite(object, dst, value, save_fp, remembered_set_action,
463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              OMIT_SMI_CHECK, pointers_to_here_check_for_value);
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&done);
4664515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Clobber clobbered input registers when running with the debug-code flag
4684515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // turned on to provoke errors.
46944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(value, Immediate(bit_cast<int32_t>(kZapValue)));
471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(dst, Immediate(bit_cast<int32_t>(kZapValue)));
4724515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::RecordWriteForMap(
477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register object,
478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Map> map,
479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch1,
480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch2,
481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SaveFPRegsMode save_fp) {
482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register address = scratch1;
485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register value = scratch2;
4863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (emit_debug_code()) {
487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label ok;
488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    lea(address, FieldOperand(object, HeapObject::kMapOffset));
4893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    test_b(address, Immediate((1 << kPointerSizeLog2) - 1));
490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(zero, &ok, Label::kNear);
491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int3();
492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&ok);
493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!object.is(value));
496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!object.is(address));
497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!value.is(address));
498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertNotSmi(object);
499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!FLAG_incremental_marking) {
501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Compute the address.
505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lea(address, FieldOperand(object, HeapObject::kMapOffset));
506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // A single check of the map's pages interesting flag suffices, since it is
508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // only set during incremental collection, and then it's also guaranteed that
509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the from object's page's interesting flag is also set.  This optimization
510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // relies on the fact that maps can never be in new space.
511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!isolate()->heap()->InNewSpace(*map));
512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckPageFlagForMap(map,
513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      MemoryChunk::kPointersToHereAreInterestingMask,
514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      zero,
515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      &done,
516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      Label::kNear);
517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordWriteStub stub(isolate(), object, value, address, OMIT_REMEMBERED_SET,
519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       save_fp);
520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallStub(&stub);
521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Count number of write barriers in generated code.
525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate()->counters()->write_barriers_static()->Increment();
526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1);
527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Clobber clobbered input registers when running with the debug-code flag
529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // turned on to provoke errors.
530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(value, Immediate(bit_cast<int32_t>(kZapValue)));
532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(scratch1, Immediate(bit_cast<int32_t>(kZapValue)));
533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(scratch2, Immediate(bit_cast<int32_t>(kZapValue)));
534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::RecordWrite(
539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register object,
540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register address,
541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register value,
542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SaveFPRegsMode fp_mode,
543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RememberedSetAction remembered_set_action,
544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiCheck smi_check,
545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PointersToHereCheck pointers_to_here_check_for_value) {
546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!object.is(value));
547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!object.is(address));
548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!value.is(address));
549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertNotSmi(object);
550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (remembered_set_action == OMIT_REMEMBERED_SET &&
5523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      !FLAG_incremental_marking) {
5533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return;
5543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
5573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label ok;
5583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    cmp(value, Operand(address, 0));
5593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(equal, &ok, Label::kNear);
5603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int3();
5613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&ok);
5623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5648defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // First, check if a write barrier is even needed. The tests below
5658defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // catch stores of Smis and stores into young gen.
5668defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Label done;
5678defd9ff6930b4e24729971a61cf7469daf119beSteve Block
5683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (smi_check == INLINE_SMI_CHECK) {
5693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Skip barrier if writing a smi.
5703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JumpIfSmi(value, &done, Label::kNear);
5713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (pointers_to_here_check_for_value != kPointersToHereAreAlwaysInteresting) {
574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CheckPageFlag(value,
575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  value,  // Used as scratch.
576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  MemoryChunk::kPointersToHereAreInterestingMask,
577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  zero,
578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  &done,
579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  Label::kNear);
580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPageFlag(object,
5823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                value,  // Used as scratch.
5833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                MemoryChunk::kPointersFromHereAreInterestingMask,
5843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                zero,
5853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                &done,
5863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                Label::kNear);
5873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordWriteStub stub(isolate(), object, value, address, remembered_set_action,
589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       fp_mode);
5903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallStub(&stub);
5918defd9ff6930b4e24729971a61cf7469daf119beSteve Block
5928defd9ff6930b4e24729971a61cf7469daf119beSteve Block  bind(&done);
5938defd9ff6930b4e24729971a61cf7469daf119beSteve Block
594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Count number of write barriers in generated code.
595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate()->counters()->write_barriers_static()->Increment();
596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1);
597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Clobber clobbered registers when running with the debug-code flag
5998defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // turned on to provoke errors.
60044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(address, Immediate(bit_cast<int32_t>(kZapValue)));
602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(value, Immediate(bit_cast<int32_t>(kZapValue)));
6038defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
6048defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
6058defd9ff6930b4e24729971a61cf7469daf119beSteve Block
606109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::RecordWriteCodeEntryField(Register js_function,
607109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                               Register code_entry,
608109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                               Register scratch) {
609109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  const int offset = JSFunction::kCodeEntryOffset;
610109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
611109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Since a code entry (value) is always in old space, we don't need to update
612109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // remembered set. If incremental marking is off, there is nothing for us to
613109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // do.
614109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (!FLAG_incremental_marking) return;
615109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
616109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(!js_function.is(code_entry));
617109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(!js_function.is(scratch));
618109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(!code_entry.is(scratch));
619109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  AssertNotSmi(js_function);
620109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
621109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (emit_debug_code()) {
622109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Label ok;
623109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    lea(scratch, FieldOperand(js_function, offset));
624109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    cmp(code_entry, Operand(scratch, 0));
625109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    j(equal, &ok, Label::kNear);
626109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    int3();
627109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    bind(&ok);
628109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
629109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
630109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // First, check if a write barrier is even needed. The tests below
631109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // catch stores of Smis and stores into young gen.
632109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Label done;
633109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
634109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  CheckPageFlag(code_entry, scratch,
635109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                MemoryChunk::kPointersToHereAreInterestingMask, zero, &done,
636109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                Label::kNear);
637109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  CheckPageFlag(js_function, scratch,
638109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                MemoryChunk::kPointersFromHereAreInterestingMask, zero, &done,
639109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                Label::kNear);
640109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
641109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Save input registers.
642109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  push(js_function);
643109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  push(code_entry);
644109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
645109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  const Register dst = scratch;
646109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  lea(dst, FieldOperand(js_function, offset));
647109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
648109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Save caller-saved registers.
649109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PushCallerSaved(kDontSaveFPRegs, js_function, code_entry);
650109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
651109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  int argument_count = 3;
652109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PrepareCallCFunction(argument_count, code_entry);
653109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  mov(Operand(esp, 0 * kPointerSize), js_function);
654109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  mov(Operand(esp, 1 * kPointerSize), dst);  // Slot.
655109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  mov(Operand(esp, 2 * kPointerSize),
656109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      Immediate(ExternalReference::isolate_address(isolate())));
657109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
658109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  {
659109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    AllowExternalCallThatCantCauseGC scope(this);
660109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    CallCFunction(
661109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        ExternalReference::incremental_marking_record_write_code_entry_function(
662109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch            isolate()),
663109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        argument_count);
664109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
665109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
666109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Restore caller-saved registers.
667109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PopCallerSaved(kDontSaveFPRegs, js_function, code_entry);
668109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
669109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Restore input registers.
670109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  pop(code_entry);
671109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  pop(js_function);
672109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
673109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  bind(&done);
674109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
6758defd9ff6930b4e24729971a61cf7469daf119beSteve Block
676402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::DebugBreak() {
677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Move(eax, Immediate(0));
678014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(ebx, Immediate(ExternalReference(Runtime::kHandleDebuggerStatement,
679014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                       isolate())));
680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CEntryStub ces(isolate(), 1);
681014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  call(ces.GetCode(), RelocInfo::DEBUGGER_STATEMENT);
682402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Cvtsi2sd(XMMRegister dst, const Operand& src) {
685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  xorps(dst, dst);
686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cvtsi2sd(dst, src);
687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
690109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::Cvtui2ss(XMMRegister dst, Register src, Register tmp) {
691109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Label msb_set_src;
692109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Label jmp_return;
693109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  test(src, src);
694109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  j(sign, &msb_set_src, Label::kNear);
695109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  cvtsi2ss(dst, src);
696109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  jmp(&jmp_return, Label::kNear);
697109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  bind(&msb_set_src);
698109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  mov(tmp, src);
699109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  shr(src, 1);
700109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Recover the least significant bit to avoid rounding errors.
701109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  and_(tmp, Immediate(1));
702109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  or_(src, tmp);
703109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  cvtsi2ss(dst, src);
704109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  addss(dst, dst);
705109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  bind(&jmp_return);
706109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
707109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
7083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::ShlPair(Register high, Register low, uint8_t shift) {
7093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (shift >= 32) {
7103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    mov(high, low);
7113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shl(high, shift - 32);
7123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    xor_(low, low);
7133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
7143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shld(high, low, shift);
7153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shl(low, shift);
7163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
7173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
7183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
7193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::ShlPair_cl(Register high, Register low) {
7203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  shld_cl(high, low);
7213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  shl_cl(low);
7223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label done;
7233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test(ecx, Immediate(0x20));
7243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  j(equal, &done, Label::kNear);
7253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(high, low);
7263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  xor_(low, low);
7273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&done);
7283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
7293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
7303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::ShrPair(Register high, Register low, uint8_t shift) {
7313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (shift >= 32) {
7323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    mov(low, high);
7333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shr(low, shift - 32);
7343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    xor_(high, high);
7353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
7363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shrd(high, low, shift);
7373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shr(high, shift);
7383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
7393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
7403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
7413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::ShrPair_cl(Register high, Register low) {
7423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  shrd_cl(low, high);
7433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  shr_cl(high);
7443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label done;
7453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test(ecx, Immediate(0x20));
7463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  j(equal, &done, Label::kNear);
7473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(low, high);
7483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  xor_(high, high);
7493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&done);
7503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
7513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
7523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::SarPair(Register high, Register low, uint8_t shift) {
7533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (shift >= 32) {
7543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    mov(low, high);
7553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    sar(low, shift - 32);
7563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    sar(high, 31);
7573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
7583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shrd(high, low, shift);
7593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    sar(high, shift);
7603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
7613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
7623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
7633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::SarPair_cl(Register high, Register low) {
7643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  shrd_cl(low, high);
7653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  sar_cl(high);
7663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label done;
7673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test(ecx, Immediate(0x20));
7683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  j(equal, &done, Label::kNear);
7693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(low, high);
7703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  sar(high, 31);
7713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&done);
7723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
773109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
774053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Blockbool MacroAssembler::IsUnsafeImmediate(const Immediate& x) {
775053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  static const int kMaxImmediateBits = 17;
776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!RelocInfo::IsNone(x.rmode_)) return false;
777053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  return !is_intn(x.x_, kMaxImmediateBits);
778053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block}
779053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
780053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::SafeMove(Register dst, const Immediate& x) {
782053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  if (IsUnsafeImmediate(x) && jit_cookie() != 0) {
783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(dst, Immediate(x.x_ ^ jit_cookie()));
784053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block    xor_(dst, jit_cookie());
785053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  } else {
786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(dst, x);
787053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  }
788053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block}
789053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
790053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
791053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Blockvoid MacroAssembler::SafePush(const Immediate& x) {
792053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  if (IsUnsafeImmediate(x) && jit_cookie() != 0) {
793053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block    push(Immediate(x.x_ ^ jit_cookie()));
794053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block    xor_(Operand(esp, 0), Immediate(jit_cookie()));
795053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  } else {
796053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block    push(x);
797053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  }
798053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block}
799053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
800053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpObjectType(Register heap_object,
802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   InstanceType type,
803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   Register map) {
804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(map, FieldOperand(heap_object, HeapObject::kMapOffset));
805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CmpInstanceType(map, type);
806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpInstanceType(Register map, InstanceType type) {
8103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  cmpb(FieldOperand(map, Map::kInstanceTypeOffset), Immediate(type));
811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckFastObjectElements(Register map,
8143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Label* fail,
8153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Label::Distance distance) {
816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_ELEMENTS == 2);
819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
8203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmpb(FieldOperand(map, Map::kBitField2Offset),
8213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch       Immediate(Map::kMaximumBitField2FastHoleySmiElementValue));
8223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(below_equal, fail, distance);
8233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  cmpb(FieldOperand(map, Map::kBitField2Offset),
8243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch       Immediate(Map::kMaximumBitField2FastHoleyElementValue));
8253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  j(above, fail, distance);
8263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
8273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
8283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CheckFastSmiElements(Register map,
830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          Label* fail,
831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          Label::Distance distance) {
832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
8343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmpb(FieldOperand(map, Map::kBitField2Offset),
8353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch       Immediate(Map::kMaximumBitField2FastHoleySmiElementValue));
8363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(above, fail, distance);
8373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
8383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::StoreNumberToDoubleElements(
8413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register maybe_number,
8423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register elements,
8433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register key,
8443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch1,
8453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    XMMRegister scratch2,
8463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* fail,
847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int elements_offset) {
848014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label smi_value, done;
8493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpIfSmi(maybe_number, &smi_value, Label::kNear);
8503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckMap(maybe_number,
8523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           isolate()->factory()->heap_number_map(),
8533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           fail,
8543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           DONT_DO_SMI_CHECK);
8553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
856014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Double value, turn potential sNaN into qNaN.
857014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Move(scratch2, 1.0);
858014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mulsd(scratch2, FieldOperand(maybe_number, HeapNumber::kValueOffset));
859014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  jmp(&done, Label::kNear);
8603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&smi_value);
8623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Value is a smi. Convert to a double and store.
8633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Preserve original value.
8643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(scratch1, maybe_number);
8653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SmiUntag(scratch1);
866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Cvtsi2sd(scratch2, scratch1);
867014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&done);
868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movsd(FieldOperand(elements, key, times_4,
869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     FixedDoubleArray::kHeaderSize - elements_offset),
870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        scratch2);
8713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
8723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CompareMap(Register obj, Handle<Map> map) {
8753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmp(FieldOperand(obj, HeapObject::kMapOffset), map);
8763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
8773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::CheckMap(Register obj,
8803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Handle<Map> map,
8813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Label* fail,
882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              SmiCheckType smi_check_type) {
883257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (smi_check_type == DO_SMI_CHECK) {
884257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    JumpIfSmi(obj, fail);
8853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
8863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompareMap(obj, map);
8883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  j(not_equal, fail);
8893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
8903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
8913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
892958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::DispatchWeakMap(Register obj, Register scratch1,
893958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                     Register scratch2, Handle<WeakCell> cell,
894958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                     Handle<Code> success,
895958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                     SmiCheckType smi_check_type) {
896257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label fail;
897257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (smi_check_type == DO_SMI_CHECK) {
898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    JumpIfSmi(obj, &fail);
899257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
900958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  mov(scratch1, FieldOperand(obj, HeapObject::kMapOffset));
901958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CmpWeakValue(scratch1, cell, scratch2);
902257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(equal, success);
903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
904257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&fail);
905257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
906257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
907257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
908e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeCondition MacroAssembler::IsObjectStringType(Register heap_object,
909e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                             Register map,
910e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                             Register instance_type) {
911e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  mov(map, FieldOperand(heap_object, HeapObject::kMapOffset));
912e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
91369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kNotStringTag != 0);
914e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  test(instance_type, Immediate(kIsNotStringMask));
915e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  return zero;
916e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
917e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
918e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochCondition MacroAssembler::IsObjectNameType(Register heap_object,
920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register map,
921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register instance_type) {
922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(map, FieldOperand(heap_object, HeapObject::kMapOffset));
923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
9243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  cmpb(instance_type, Immediate(LAST_NAME_TYPE));
925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return below_equal;
926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::FCmp() {
930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fucomip();
931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fstp(0);
932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertNumber(Register object) {
936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label ok;
938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    JumpIfSmi(object, &ok);
939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(FieldOperand(object, HeapObject::kMapOffset),
940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate()->factory()->heap_number_map());
941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, kOperandNotANumber);
942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&ok);
9433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::AssertNotNumber(Register object) {
9473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (emit_debug_code()) {
9483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    test(object, Immediate(kSmiTagMask));
9493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Check(not_equal, kOperandIsANumber);
9503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    cmp(FieldOperand(object, HeapObject::kMapOffset),
9513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        isolate()->factory()->heap_number_map());
9523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Check(not_equal, kOperandIsANumber);
9533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
9543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertSmi(Register object) {
957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(object, Immediate(kSmiTagMask));
959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, kOperandIsNotASmi);
960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertString(Register object) {
965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(object, Immediate(kSmiTagMask));
967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kOperandIsASmiAndNotAString);
968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    push(object);
969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(object, FieldOperand(object, HeapObject::kMapOffset));
970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CmpInstanceType(object, FIRST_NONSTRING_TYPE);
971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    pop(object);
972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(below, kOperandIsNotAString);
973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertName(Register object) {
978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(object, Immediate(kSmiTagMask));
980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kOperandIsASmiAndNotAName);
981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    push(object);
982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(object, FieldOperand(object, HeapObject::kMapOffset));
983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CmpInstanceType(object, LAST_NAME_TYPE);
984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    pop(object);
985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(below_equal, kOperandIsNotAName);
986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
990014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::AssertFunction(Register object) {
991014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (emit_debug_code()) {
992014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    test(object, Immediate(kSmiTagMask));
993014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(not_equal, kOperandIsASmiAndNotAFunction);
994014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(object);
995014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CmpObjectType(object, JS_FUNCTION_TYPE, object);
996014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Pop(object);
997014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(equal, kOperandIsNotAFunction);
998014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
999014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1000014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1001014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1002014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::AssertBoundFunction(Register object) {
1003014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (emit_debug_code()) {
1004014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    test(object, Immediate(kSmiTagMask));
1005014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(not_equal, kOperandIsASmiAndNotABoundFunction);
1006014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(object);
1007014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CmpObjectType(object, JS_BOUND_FUNCTION_TYPE, object);
1008014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Pop(object);
1009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(equal, kOperandIsNotABoundFunction);
1010014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1011014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1012014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1013bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::AssertGeneratorObject(Register object) {
1014bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (emit_debug_code()) {
1015bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    test(object, Immediate(kSmiTagMask));
1016bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Check(not_equal, kOperandIsASmiAndNotAGeneratorObject);
1017bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Push(object);
1018bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    CmpObjectType(object, JS_GENERATOR_OBJECT_TYPE, object);
1019bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Pop(object);
1020bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Check(equal, kOperandIsNotAGeneratorObject);
1021bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1022bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1023014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1024109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::AssertReceiver(Register object) {
1025109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (emit_debug_code()) {
1026109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    test(object, Immediate(kSmiTagMask));
1027109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Check(not_equal, kOperandIsASmiAndNotAReceiver);
1028109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Push(object);
1029109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
1030109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    CmpObjectType(object, FIRST_JS_RECEIVER_TYPE, object);
1031109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Pop(object);
1032109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Check(above_equal, kOperandIsNotAReceiver);
1033109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
1034109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
1035109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1036109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertUndefinedOrAllocationSite(Register object) {
1038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
1039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label done_checking;
1040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AssertNotSmi(object);
1041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(object, isolate()->factory()->undefined_value());
1042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(equal, &done_checking);
1043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(FieldOperand(object, 0),
1044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Immediate(isolate()->factory()->allocation_site_map()));
1045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Assert(equal, kExpectedUndefinedOrCell);
1046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&done_checking);
1047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1048402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
1049402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1050402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertNotSmi(Register object) {
1052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
1053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(object, Immediate(kSmiTagMask));
1054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kOperandIsASmi);
1055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1056756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
1057756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
10583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::StubPrologue(StackFrame::Type type) {
1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  push(ebp);  // Caller's frame pointer.
1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(ebp, esp);
10613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  push(Immediate(Smi::FromInt(type)));
106280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
106380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Prologue(bool code_pre_aging) {
1065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PredictableCodeSizeScope predictible_code_size_scope(this,
1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kNoCodeAgeSequenceLength);
1067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (code_pre_aging) {
1068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Pre-age the code.
1069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    call(isolate()->builtins()->MarkCodeAsExecutedOnce(),
1070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        RelocInfo::CODE_AGE_SEQUENCE);
1071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Nop(kNoCodeAgeSequenceLength - Assembler::kCallInstructionLength);
1072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    push(ebp);  // Caller's frame pointer.
1074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(ebp, esp);
1075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    push(esi);  // Callee's context.
1076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    push(edi);  // Callee's JS function.
1077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
10786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
10796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1081014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::EmitLoadTypeFeedbackVector(Register vector) {
1082014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(vector, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
108313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  mov(vector, FieldOperand(vector, JSFunction::kLiteralsOffset));
108413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  mov(vector, FieldOperand(vector, LiteralsArray::kFeedbackVectorOffset));
1085014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1086014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1087014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1088958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::EnterFrame(StackFrame::Type type,
1089958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                bool load_constant_pool_pointer_reg) {
1090958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Out-of-line constant pool not implemented on ia32.
1091958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  UNREACHABLE();
1092958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1093958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1094958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::EnterFrame(StackFrame::Type type) {
1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(ebp);
10973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(ebp, esp);
1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(Immediate(Smi::FromInt(type)));
10993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (type == StackFrame::INTERNAL) {
11003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    push(Immediate(CodeObject()));
11013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
110244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
110344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    cmp(Operand(esp, 0), Immediate(isolate()->factory()->undefined_value()));
1104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kCodeObjectNotProperlyPatched);
1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LeaveFrame(StackFrame::Type type) {
111044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
11113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    cmp(Operand(ebp, CommonFrameConstants::kContextOrFrameTypeOffset),
1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Immediate(Smi::FromInt(type)));
1113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, kStackFrameTypesMustMatch);
1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  leave();
1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1118f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MacroAssembler::EnterBuiltinFrame(Register context, Register target,
1119f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                       Register argc) {
1120f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Push(ebp);
1121f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Move(ebp, esp);
1122f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Push(context);
1123f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Push(target);
1124f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Push(argc);
1125f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
1126f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1127f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MacroAssembler::LeaveBuiltinFrame(Register context, Register target,
1128f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                       Register argc) {
1129f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Pop(argc);
1130f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Pop(target);
1131f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Pop(context);
1132f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  leave();
1133f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
1134f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1135f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MacroAssembler::EnterExitFramePrologue(StackFrame::Type frame_type) {
1136f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(frame_type == StackFrame::EXIT ||
1137f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch         frame_type == StackFrame::BUILTIN_EXIT);
113880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
11393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up the frame structure on the stack.
11403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(+2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement);
11413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(+1 * kPointerSize, ExitFrameConstants::kCallerPCOffset);
11423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset);
1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(ebp);
11443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(ebp, esp);
1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
114680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Reserve room for entry stack pointer and push the code object.
1147f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  push(Immediate(Smi::FromInt(frame_type)));
11483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(-2 * kPointerSize, ExitFrameConstants::kSPOffset);
1149402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  push(Immediate(0));  // Saved entry sp, patched before call.
11503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(-3 * kPointerSize, ExitFrameConstants::kCodeOffset);
1151402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  push(Immediate(CodeObject()));  // Accessed from ExitFrame::code_slot.
1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Save the frame pointer and the context in top.
1154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress, isolate());
1155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference context_address(Isolate::kContextAddress, isolate());
1156958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ExternalReference c_function_address(Isolate::kCFunctionAddress, isolate());
1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(Operand::StaticVariable(c_entry_fp_address), ebp);
1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(Operand::StaticVariable(context_address), esi);
1159958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  mov(Operand::StaticVariable(c_function_address), ebx);
1160d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid MacroAssembler::EnterExitFrameEpilogue(int argc, bool save_doubles) {
1164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Optionally save all XMM registers.
1165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (save_doubles) {
1166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int space = XMMRegister::kMaxNumRegisters * kDoubleSize +
1167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                argc * kPointerSize;
11683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sub(esp, Immediate(space));
11693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    const int offset = -ExitFrameConstants::kFixedFrameSizeFromFp;
1170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
1171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      XMMRegister reg = XMMRegister::from_code(i);
1172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movsd(Operand(ebp, offset - ((i + 1) * kDoubleSize)), reg);
1173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
11753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sub(esp, Immediate(argc * kPointerSize));
1176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the required frame alignment for the OS.
1179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kFrameAlignment = base::OS::ActivationFrameAlignment();
1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (kFrameAlignment > 0) {
1181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(base::bits::IsPowerOfTwo32(kFrameAlignment));
1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    and_(esp, -kFrameAlignment);
1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the saved entry sp.
1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(Operand(ebp, ExitFrameConstants::kSPOffset), esp);
1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1189f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MacroAssembler::EnterExitFrame(int argc, bool save_doubles,
1190f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                    StackFrame::Type frame_type) {
1191f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  EnterExitFramePrologue(frame_type);
1192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
11933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up argc and argv in callee-saved registers.
1194d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
11953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(edi, eax);
1196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  lea(esi, Operand(ebp, eax, times_4, offset));
1197d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
119844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Reserve space for argc, argv and isolate.
1199109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  EnterExitFrameEpilogue(argc, save_doubles);
1200d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1201d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1202d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
12038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid MacroAssembler::EnterApiExitFrame(int argc) {
1204f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  EnterExitFramePrologue(StackFrame::EXIT);
1205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  EnterExitFrameEpilogue(argc, false);
1206d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1207d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1208d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LeaveExitFrame(bool save_doubles, bool pop_arguments) {
1210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Optionally restore all XMM registers.
1211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (save_doubles) {
12123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    const int offset = -ExitFrameConstants::kFixedFrameSizeFromFp;
1213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
1214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      XMMRegister reg = XMMRegister::from_code(i);
1215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movsd(reg, Operand(ebp, offset - ((i + 1) * kDoubleSize)));
1216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (pop_arguments) {
1220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Get the return address from the stack and restore the frame pointer.
1221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mov(ecx, Operand(ebp, 1 * kPointerSize));
1222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mov(ebp, Operand(ebp, 0 * kPointerSize));
1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Pop the arguments and the receiver from the caller stack.
1225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    lea(esp, Operand(esi, 1 * kPointerSize));
1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Push the return address to get ready to return.
1228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    push(ecx);
1229014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
1230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Otherwise just leave the exit frame.
1231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    leave();
1232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
12338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LeaveExitFrameEpilogue(true);
12358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
12368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::LeaveExitFrameEpilogue(bool restore_context) {
1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Restore current context from top and clear it in debug mode.
1240589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ExternalReference context_address(Isolate::kContextAddress, isolate());
1241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (restore_context) {
1242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(esi, Operand::StaticVariable(context_address));
1243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(Operand::StaticVariable(context_address), Immediate(0));
1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clear the top frame.
1249589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress,
125044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       isolate());
1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(Operand::StaticVariable(c_entry_fp_address), Immediate(0));
1252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::LeaveApiExitFrame(bool restore_context) {
12563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(esp, ebp);
12578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  pop(ebp);
12588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LeaveExitFrameEpilogue(restore_context);
12608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
12618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
12628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::PushStackHandler() {
1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Adjust this code if not the case.
1265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(StackHandlerConstants::kSize == 1 * kPointerSize);
126669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
12673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Link the current handler as the next handler.
12693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
12703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  push(Operand::StaticVariable(handler_address));
1271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
12723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set this new handler as the current one.
12733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(Operand::StaticVariable(handler_address), esp);
1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::PopStackHandler() {
127869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
12793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
12803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  pop(Operand::StaticVariable(handler_address));
12813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(esp, Immediate(StackHandlerConstants::kSize - kPointerSize));
12823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
12833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Compute the hash code from the untagged key.  This must be kept in sync with
1286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ComputeIntegerHash in utils.h and KeyedLoadGenericStub in
1287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// code-stub-hydrogen.cc
1288c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch//
1289c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch// Note: r0 will contain hash code
1290c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdochvoid MacroAssembler::GetNumberHash(Register r0, Register scratch) {
1291c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // Xor original key with a seed.
1292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (serializer_enabled()) {
12933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ExternalReference roots_array_start =
12943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ExternalReference::roots_array_start(isolate());
1295c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    mov(scratch, Immediate(Heap::kHashSeedRootIndex));
12963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(scratch,
12973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Operand::StaticArray(scratch, times_pointer_size, roots_array_start));
1298c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    SmiUntag(scratch);
12993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    xor_(r0, scratch);
1300c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  } else {
1301c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    int32_t seed = isolate()->heap()->HashSeed();
13023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    xor_(r0, Immediate(seed));
1303c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  }
1304c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
1305c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = ~hash + (hash << 15);
1306c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  mov(scratch, r0);
1307c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  not_(r0);
1308c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  shl(scratch, 15);
13093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(r0, scratch);
1310c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash ^ (hash >> 12);
1311c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  mov(scratch, r0);
1312c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  shr(scratch, 12);
13133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  xor_(r0, scratch);
1314c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash + (hash << 2);
1315c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  lea(r0, Operand(r0, r0, times_4, 0));
1316c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash ^ (hash >> 4);
1317c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  mov(scratch, r0);
1318c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  shr(scratch, 4);
13193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  xor_(r0, scratch);
1320c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash * 2057;
1321c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  imul(r0, r0, 2057);
1322c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash ^ (hash >> 16);
1323c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  mov(scratch, r0);
1324c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  shr(scratch, 16);
13253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  xor_(r0, scratch);
1326014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  and_(r0, 0x3fffffff);
1327c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch}
1328c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LoadAllocationTopHelper(Register result,
1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register scratch,
1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             AllocationFlags flags) {
1332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_top =
1333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationTopReference(isolate(), flags);
1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Just return if allocation top is already known.
1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((flags & RESULT_CONTAINS_TOP) != 0) {
1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // No use of scratch if allocation top is provided.
1338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(scratch.is(no_reg));
1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Assert that result actually contains top on entry.
1341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmp(result, Operand::StaticVariable(allocation_top));
1342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, kUnexpectedAllocationTop);
1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Move address of new object to result. Use scratch register if available.
1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (scratch.is(no_reg)) {
1349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(result, Operand::StaticVariable(allocation_top));
1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(scratch, Immediate(allocation_top));
1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(result, Operand(scratch, 0));
1353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::UpdateAllocationTopHelper(Register result_end,
1358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register scratch,
1359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               AllocationFlags flags) {
136044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
1361d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    test(result_end, Immediate(kObjectAlignmentMask));
1362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(zero, kUnalignedAllocationInNewSpace);
1363d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1364d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_top =
1366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationTopReference(isolate(), flags);
1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update new top. Use scratch if available.
1369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (scratch.is(no_reg)) {
1370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(Operand::StaticVariable(allocation_top), result_end);
1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(Operand(scratch, 0), result_end);
1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Allocate(int object_size,
1378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result,
1379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result_end,
1380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register scratch,
1381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Label* gc_required,
1382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              AllocationFlags flags) {
1383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0);
1384f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(object_size <= kMaxRegularHeapObjectSize);
1385bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK((flags & ALLOCATION_FOLDED) == 0);
13865913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  if (!FLAG_inline_new) {
138744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (emit_debug_code()) {
13885913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // Trash the registers to simulate an allocation failure.
13895913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      mov(result, Immediate(0x7091));
13905913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (result_end.is_valid()) {
13915913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        mov(result_end, Immediate(0x7191));
13925913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
13935913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (scratch.is_valid()) {
13945913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        mov(scratch, Immediate(0x7291));
13955913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
13965913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    }
13975913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    jmp(gc_required);
13985913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    return;
13995913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
1400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result.is(result_end));
1401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load address of new object into result.
14038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LoadAllocationTopHelper(result, scratch, flags);
1404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_limit =
1406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationLimitReference(isolate(), flags);
1407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Align the next allocation. Storing the filler map without checking top is
1409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // safe in new-space because the limit of the heap is aligned there.
1410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
1411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
1412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label aligned;
1413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(result, Immediate(kDoubleAlignmentMask));
1414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(zero, &aligned, Label::kNear);
1415014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if ((flags & PRETENURE) != 0) {
1416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cmp(result, Operand::StaticVariable(allocation_limit));
1417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      j(above_equal, gc_required);
1418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(Operand(result, 0),
1420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Immediate(isolate()->factory()->one_pointer_filler_map()));
1421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    add(result, Immediate(kDoubleSize / 2));
1422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&aligned);
1423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Calculate new top and bail out if space is exhausted.
1426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register top_reg = result_end.is_valid() ? result_end : result;
1427bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
14281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (!top_reg.is(result)) {
14291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    mov(top_reg, result);
1430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
14313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(top_reg, Immediate(object_size));
1432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(top_reg, Operand::StaticVariable(allocation_limit));
1433257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(above, gc_required);
1434e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1435bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
1436bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // The top pointer is not updated for allocation folding dominators.
1437bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    UpdateAllocationTopHelper(top_reg, scratch, flags);
1438bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1439bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1440bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (top_reg.is(result)) {
1441bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    sub(result, Immediate(object_size - kHeapObjectTag));
1442bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  } else {
1443bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // Tag the result.
1444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kHeapObjectTag == 1);
1445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    inc(result);
1446bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
1447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Allocate(int header_size,
1451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              ScaleFactor element_size,
1452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register element_count,
1453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              RegisterValueType element_count_type,
1454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result,
1455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result_end,
1456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register scratch,
1457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Label* gc_required,
1458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              AllocationFlags flags) {
1459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((flags & SIZE_IN_WORDS) == 0);
1460bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK((flags & ALLOCATION_FOLDING_DOMINATOR) == 0);
1461bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK((flags & ALLOCATION_FOLDED) == 0);
14625913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  if (!FLAG_inline_new) {
146344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (emit_debug_code()) {
14645913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // Trash the registers to simulate an allocation failure.
14655913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      mov(result, Immediate(0x7091));
14665913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      mov(result_end, Immediate(0x7191));
14675913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (scratch.is_valid()) {
14685913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        mov(scratch, Immediate(0x7291));
14695913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
14705913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // Register element_count is not modified by the function.
14715913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    }
14725913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    jmp(gc_required);
14735913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    return;
14745913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
1475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result.is(result_end));
1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load address of new object into result.
14788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LoadAllocationTopHelper(result, scratch, flags);
1479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_limit =
1481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationLimitReference(isolate(), flags);
1482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Align the next allocation. Storing the filler map without checking top is
1484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // safe in new-space because the limit of the heap is aligned there.
1485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
1486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
1487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label aligned;
1488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(result, Immediate(kDoubleAlignmentMask));
1489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(zero, &aligned, Label::kNear);
1490014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if ((flags & PRETENURE) != 0) {
1491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cmp(result, Operand::StaticVariable(allocation_limit));
1492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      j(above_equal, gc_required);
1493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(Operand(result, 0),
1495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Immediate(isolate()->factory()->one_pointer_filler_map()));
1496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    add(result, Immediate(kDoubleSize / 2));
1497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&aligned);
1498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
14991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Calculate new top and bail out if space is exhausted.
15011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // We assume that element_count*element_size + header_size does not
15021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // overflow.
1503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (element_count_type == REGISTER_VALUE_IS_SMI) {
1504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(static_cast<ScaleFactor>(times_2 - 1) == times_1);
1505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(static_cast<ScaleFactor>(times_4 - 1) == times_2);
1506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(static_cast<ScaleFactor>(times_8 - 1) == times_4);
1507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(element_size >= times_2);
1508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kSmiTagSize == 1);
1509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    element_size = static_cast<ScaleFactor>(element_size - 1);
1510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(element_count_type == REGISTER_VALUE_IS_INT32);
1512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1513bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
15141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  lea(result_end, Operand(element_count, element_size, header_size));
15153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(result_end, result);
1516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(result_end, Operand::StaticVariable(allocation_limit));
1517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(above, gc_required);
1518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1519bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Tag result.
1520bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(kHeapObjectTag == 1);
1521bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  inc(result);
1522e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UpdateAllocationTopHelper(result_end, scratch, flags);
1524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Allocate(Register object_size,
1528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result,
1529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result_end,
1530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register scratch,
1531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Label* gc_required,
1532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              AllocationFlags flags) {
1533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0);
1534bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK((flags & ALLOCATION_FOLDED) == 0);
15355913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  if (!FLAG_inline_new) {
153644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (emit_debug_code()) {
15375913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // Trash the registers to simulate an allocation failure.
15385913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      mov(result, Immediate(0x7091));
15395913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      mov(result_end, Immediate(0x7191));
15405913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (scratch.is_valid()) {
15415913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        mov(scratch, Immediate(0x7291));
15425913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
15435913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // object_size is left unchanged by this function.
15445913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    }
15455913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    jmp(gc_required);
15465913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    return;
15475913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
1548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result.is(result_end));
1549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load address of new object into result.
15518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LoadAllocationTopHelper(result, scratch, flags);
1552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_limit =
1554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationLimitReference(isolate(), flags);
1555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Align the next allocation. Storing the filler map without checking top is
1557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // safe in new-space because the limit of the heap is aligned there.
1558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
1559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
1560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label aligned;
1561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(result, Immediate(kDoubleAlignmentMask));
1562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(zero, &aligned, Label::kNear);
1563014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if ((flags & PRETENURE) != 0) {
1564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cmp(result, Operand::StaticVariable(allocation_limit));
1565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      j(above_equal, gc_required);
1566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(Operand(result, 0),
1568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Immediate(isolate()->factory()->one_pointer_filler_map()));
1569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    add(result, Immediate(kDoubleSize / 2));
1570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&aligned);
1571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Calculate new top and bail out if space is exhausted.
1574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!object_size.is(result_end)) {
1575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(result_end, object_size);
1576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
15773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(result_end, result);
1578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(result_end, Operand::StaticVariable(allocation_limit));
1579257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(above, gc_required);
1580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1581bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Tag result.
1582bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(kHeapObjectTag == 1);
1583bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  inc(result);
1584bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1585bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
1586bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // The top pointer is not updated for allocation folding dominators.
1587bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    UpdateAllocationTopHelper(result_end, scratch, flags);
1588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1589bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1590e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1591bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::FastAllocate(int object_size, Register result,
1592bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                  Register result_end, AllocationFlags flags) {
1593bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!result.is(result_end));
1594bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Load address of new object into result.
1595bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  LoadAllocationTopHelper(result, no_reg, flags);
1596bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1597bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
1598bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
1599bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Label aligned;
1600bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    test(result, Immediate(kDoubleAlignmentMask));
1601bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    j(zero, &aligned, Label::kNear);
1602bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    mov(Operand(result, 0),
1603bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        Immediate(isolate()->factory()->one_pointer_filler_map()));
1604bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    add(result, Immediate(kDoubleSize / 2));
1605bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    bind(&aligned);
1606bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1607bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1608bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  lea(result_end, Operand(result, object_size));
1609bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  UpdateAllocationTopHelper(result_end, no_reg, flags);
1610bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1611bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(kHeapObjectTag == 1);
1612bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  inc(result);
1613bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1614bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1615bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::FastAllocate(Register object_size, Register result,
1616bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                  Register result_end, AllocationFlags flags) {
1617bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!result.is(result_end));
1618bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Load address of new object into result.
1619bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  LoadAllocationTopHelper(result, no_reg, flags);
1620bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1621bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
1622bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
1623bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Label aligned;
1624bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    test(result, Immediate(kDoubleAlignmentMask));
1625bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    j(zero, &aligned, Label::kNear);
1626bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    mov(Operand(result, 0),
1627bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        Immediate(isolate()->factory()->one_pointer_filler_map()));
1628bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    add(result, Immediate(kDoubleSize / 2));
1629bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    bind(&aligned);
1630bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1631bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1632bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  lea(result_end, Operand(result, object_size, times_1, 0));
1633bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  UpdateAllocationTopHelper(result_end, no_reg, flags);
1634bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1635bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(kHeapObjectTag == 1);
1636bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  inc(result);
1637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::AllocateHeapNumber(Register result,
16413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                        Register scratch1,
16423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                        Register scratch2,
1643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        Label* gc_required,
1644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        MutableMode mode) {
16453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Allocate heap number in new space.
1646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(HeapNumber::kSize, result, scratch1, scratch2, gc_required,
1647bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
1648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Map> map = mode == MUTABLE
1650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ? isolate()->factory()->mutable_heap_number_map()
1651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : isolate()->factory()->heap_number_map();
16523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Set the map.
1654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(FieldOperand(result, HeapObject::kMapOffset), Immediate(map));
16553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
16563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1658d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::AllocateTwoByteString(Register result,
1659d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                           Register length,
1660d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                           Register scratch1,
1661d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                           Register scratch2,
1662d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                           Register scratch3,
1663d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                           Label* gc_required) {
1664d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Calculate the number of bytes needed for the characters in the string while
1665d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // observing object alignment.
1666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
1667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(kShortSize == 2);
1668e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // scratch1 = length * 2 + kObjectAlignmentMask.
1669e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  lea(scratch1, Operand(length, length, times_1, kObjectAlignmentMask));
16703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(scratch1, Immediate(~kObjectAlignmentMask));
1671d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1672d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Allocate two byte string in new space.
1673bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Allocate(SeqTwoByteString::kHeaderSize, times_1, scratch1,
1674bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           REGISTER_VALUE_IS_INT32, result, scratch2, scratch3, gc_required,
1675bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
1676d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1677d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Set the map, length and hash field.
1678d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  mov(FieldOperand(result, HeapObject::kMapOffset),
167944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Immediate(isolate()->factory()->string_map()));
16806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  mov(scratch1, length);
16816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  SmiTag(scratch1);
16826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  mov(FieldOperand(result, String::kLengthOffset), scratch1);
1683d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  mov(FieldOperand(result, String::kHashFieldOffset),
1684d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Immediate(String::kEmptyHashField));
1685d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1686d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1687d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AllocateOneByteString(Register result, Register length,
1689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register scratch1, Register scratch2,
1690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register scratch3,
1691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Label* gc_required) {
1692d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Calculate the number of bytes needed for the characters in the string while
1693d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // observing object alignment.
1694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0);
1695d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  mov(scratch1, length);
1696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(kCharSize == 1);
16973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(scratch1, Immediate(kObjectAlignmentMask));
16983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(scratch1, Immediate(~kObjectAlignmentMask));
1699d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Allocate one-byte string in new space.
1701bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Allocate(SeqOneByteString::kHeaderSize, times_1, scratch1,
1702bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           REGISTER_VALUE_IS_INT32, result, scratch2, scratch3, gc_required,
1703bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
1704d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1705d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Set the map, length and hash field.
1706d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  mov(FieldOperand(result, HeapObject::kMapOffset),
1707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Immediate(isolate()->factory()->one_byte_string_map()));
17086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  mov(scratch1, length);
17096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  SmiTag(scratch1);
17106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  mov(FieldOperand(result, String::kLengthOffset), scratch1);
1711d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  mov(FieldOperand(result, String::kHashFieldOffset),
1712d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Immediate(String::kEmptyHashField));
1713d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1714d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1715d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AllocateOneByteString(Register result, int length,
1717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register scratch1, Register scratch2,
1718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Label* gc_required) {
1719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(length > 0);
17209ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick
1721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Allocate one-byte string in new space.
1722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(SeqOneByteString::SizeFor(length), result, scratch1, scratch2,
1723bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           gc_required, NO_ALLOCATION_FLAGS);
17249ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick
17259ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  // Set the map, length and hash field.
17269ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  mov(FieldOperand(result, HeapObject::kMapOffset),
1727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Immediate(isolate()->factory()->one_byte_string_map()));
17289ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  mov(FieldOperand(result, String::kLengthOffset),
17299ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick      Immediate(Smi::FromInt(length)));
17309ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  mov(FieldOperand(result, String::kHashFieldOffset),
17319ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick      Immediate(String::kEmptyHashField));
17329ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick}
17339ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick
17349ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick
1735589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid MacroAssembler::AllocateTwoByteConsString(Register result,
1736d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                        Register scratch1,
1737d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                        Register scratch2,
1738d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                        Label* gc_required) {
1739d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Allocate heap number in new space.
1740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
1741bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
1742d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1743d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Set the map. The other fields are left uninitialized.
1744d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  mov(FieldOperand(result, HeapObject::kMapOffset),
174544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Immediate(isolate()->factory()->cons_string_map()));
1746d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1747d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1748d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AllocateOneByteConsString(Register result,
1750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register scratch1,
1751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register scratch2,
1752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Label* gc_required) {
1753bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
1754bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
1755d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1756d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Set the map. The other fields are left uninitialized.
1757d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  mov(FieldOperand(result, HeapObject::kMapOffset),
1758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Immediate(isolate()->factory()->cons_one_byte_string_map()));
1759d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1760d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1761b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1762589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid MacroAssembler::AllocateTwoByteSlicedString(Register result,
176369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                          Register scratch1,
176469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                          Register scratch2,
176569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                          Label* gc_required) {
176669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Allocate heap number in new space.
1767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
1768bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
176969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
177069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Set the map. The other fields are left uninitialized.
177169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  mov(FieldOperand(result, HeapObject::kMapOffset),
177269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      Immediate(isolate()->factory()->sliced_string_map()));
177369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
177469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
177569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
1776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AllocateOneByteSlicedString(Register result,
1777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                 Register scratch1,
1778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                 Register scratch2,
1779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                 Label* gc_required) {
178069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Allocate heap number in new space.
1781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
1782bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
178369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
178469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Set the map. The other fields are left uninitialized.
178569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  mov(FieldOperand(result, HeapObject::kMapOffset),
1786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Immediate(isolate()->factory()->sliced_one_byte_string_map()));
178769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
178869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
178969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
1790014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::AllocateJSValue(Register result, Register constructor,
1791014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                     Register value, Register scratch,
1792014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                     Label* gc_required) {
1793014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!result.is(constructor));
1794014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!result.is(scratch));
1795014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!result.is(value));
1796014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1797014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Allocate JSValue in new space.
1798bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Allocate(JSValue::kSize, result, scratch, no_reg, gc_required,
1799bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
1800014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1801014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Initialize the JSValue.
1802014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LoadGlobalFunctionInitialMap(constructor, scratch);
1803014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(FieldOperand(result, HeapObject::kMapOffset), scratch);
1804014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LoadRoot(scratch, Heap::kEmptyFixedArrayRootIndex);
1805014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(FieldOperand(result, JSObject::kPropertiesOffset), scratch);
1806014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(FieldOperand(result, JSObject::kElementsOffset), scratch);
1807014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(FieldOperand(result, JSValue::kValueOffset), value);
1808014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
1809014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1810014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1811014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::InitializeFieldsWithFiller(Register current_address,
1812014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                Register end_address,
18133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Register filler) {
18143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label loop, entry;
1815109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  jmp(&entry, Label::kNear);
18163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&loop);
1817014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(Operand(current_address, 0), filler);
1818014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  add(current_address, Immediate(kPointerSize));
18193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&entry);
1820014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  cmp(current_address, end_address);
1821109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  j(below, &loop, Label::kNear);
18223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
18233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::BooleanBitTest(Register object,
18263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    int field_offset,
18273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    int bit_index) {
18283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bit_index += kSmiTagSize + kSmiShiftSize;
1829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(base::bits::IsPowerOfTwo32(kBitsPerByte));
18303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int byte_index = bit_index / kBitsPerByte;
18313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int byte_bit_index = bit_index & (kBitsPerByte - 1);
18323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test_b(FieldOperand(object, field_offset + byte_index),
18333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch         Immediate(1 << byte_bit_index));
18343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
18353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::NegativeZeroTest(Register result,
1839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register op,
1840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Label* then_label) {
1841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label ok;
18423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(result, result);
1843109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  j(not_zero, &ok, Label::kNear);
18443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(op, op);
1845109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  j(sign, then_label, Label::kNear);
1846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&ok);
1847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::NegativeZeroTest(Register result,
1851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register op1,
1852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register op2,
1853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register scratch,
1854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Label* then_label) {
1855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label ok;
18563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(result, result);
1857109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  j(not_zero, &ok, Label::kNear);
18583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(scratch, op1);
18593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  or_(scratch, op2);
1860109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  j(sign, then_label, Label::kNear);
1861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&ok);
1862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1865014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::GetMapConstructor(Register result, Register map,
1866014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                       Register temp) {
1867014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label done, loop;
1868014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(result, FieldOperand(map, Map::kConstructorOrBackPointerOffset));
1869014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&loop);
1870014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  JumpIfSmi(result, &done, Label::kNear);
1871014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CmpObjectType(result, MAP_TYPE, temp);
1872014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_equal, &done, Label::kNear);
1873014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(result, FieldOperand(result, Map::kConstructorOrBackPointerOffset));
1874014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  jmp(&loop);
1875014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&done);
1876014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
18773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1879014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::TryGetFunctionPrototype(Register function, Register result,
1880014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                             Register scratch, Label* miss) {
1881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the prototype or initial map from the function.
1882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(result,
1883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
1884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the prototype or initial map is the hole, don't return it and
1886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // simply miss the cache instead. This will allow us to allocate a
1887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // prototype object on-demand in the runtime system.
18883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmp(result, Immediate(isolate()->factory()->the_hole_value()));
1889257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(equal, miss);
1890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the function does not have an initial map, we're done.
1892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label done;
1893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CmpObjectType(result, MAP_TYPE, scratch);
1894014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_equal, &done, Label::kNear);
1895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the prototype from the initial map.
1897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(result, FieldOperand(result, Map::kPrototypeOffset));
1898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // All done.
1900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&done);
1901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CallStub(CodeStub* stub, TypeFeedbackId ast_id) {
1905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(AllowThisStubCall(stub));  // Calls are not allowed in some stubs.
1906257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id);
1907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1910d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::TailCallStub(CodeStub* stub) {
1911d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  jmp(stub->GetCode(), RelocInfo::CODE_TARGET);
1912d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1913d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1914d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
191585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochvoid MacroAssembler::StubReturn(int argc) {
1916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(argc >= 1 && generating_stub());
191785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  ret((argc - 1) * kPointerSize);
1918592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch}
1919592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1920592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
19213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
1922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return has_frame_ || !stub->SometimesSetsUpAFrame();
1923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
192544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CallRuntime(const Runtime::Function* f,
1926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 int num_arguments,
1927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 SaveFPRegsMode save_doubles) {
1928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the expected number of arguments of the runtime function is
1929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // constant, we check that the actual number of arguments match the
1930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // expectation.
1931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(f->nargs < 0 || f->nargs == num_arguments);
1932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19334515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // TODO(1236192): Most runtime routines don't need the number of
19344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // arguments passed in because it is constant. At some point we
19354515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // should remove this need and make the runtime routine entry code
19364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // smarter.
1937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Move(eax, Immediate(num_arguments));
193844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  mov(ebx, Immediate(ExternalReference(f, isolate())));
1939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CEntryStub ces(isolate(), 1, save_doubles);
19404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  CallStub(&ces);
1941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1944bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid MacroAssembler::CallExternalReference(ExternalReference ref,
1945bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                           int num_arguments) {
1946bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  mov(eax, Immediate(num_arguments));
1947bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  mov(ebx, Immediate(ref));
1948bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CEntryStub stub(isolate(), 1);
1950bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  CallStub(&stub);
1951bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
1952bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1953bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1954014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::TailCallRuntime(Runtime::FunctionId fid) {
1955014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // ----------- S t a t e -------------
1956014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  -- esp[0]                 : return address
1957014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  -- esp[8]                 : argument num_arguments - 1
1958014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  ...
1959014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  -- esp[8 * num_arguments] : argument 0 (receiver)
1960014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //
1961014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  For runtime functions with variable arguments:
1962014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  -- eax                    : number of  arguments
1963014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // -----------------------------------
19643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1965014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const Runtime::Function* function = Runtime::FunctionForId(fid);
1966014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(1, function->result_size);
1967014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (function->nargs >= 0) {
1968014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // TODO(1236192): Most runtime routines don't need the number of
1969014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // arguments passed in because it is constant. At some point we
1970014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // should remove this need and make the runtime routine entry code
1971014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // smarter.
1972014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mov(eax, Immediate(function->nargs));
1973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  JumpToExternalReference(ExternalReference(fid, isolate()));
1975d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1976d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1977f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MacroAssembler::JumpToExternalReference(const ExternalReference& ext,
1978f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                             bool builtin_exit_frame) {
1979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set the entry point and jump to the C entry runtime stub.
1980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(ebx, Immediate(ext));
1981f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  CEntryStub ces(isolate(), 1, kDontSaveFPRegs, kArgvOnStack,
1982f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                 builtin_exit_frame);
1983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  jmp(ces.GetCode(), RelocInfo::CODE_TARGET);
1984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::PrepareForTailCall(
19873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    const ParameterCount& callee_args_count, Register caller_args_count_reg,
19883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Register scratch0, Register scratch1, ReturnAddressState ra_state,
19893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    int number_of_temp_values_after_return_address) {
19903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#if DEBUG
19913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (callee_args_count.is_reg()) {
19923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(!AreAliased(callee_args_count.reg(), caller_args_count_reg, scratch0,
19933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                       scratch1));
19943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
19953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(!AreAliased(caller_args_count_reg, scratch0, scratch1));
19963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
19973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK(ra_state != ReturnAddressState::kNotOnStack ||
19983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch         number_of_temp_values_after_return_address == 0);
19993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#endif
20003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
20013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Calculate the destination address where we will put the return address
20023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // after we drop current frame.
20033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Register new_sp_reg = scratch0;
20043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (callee_args_count.is_reg()) {
20053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    sub(caller_args_count_reg, callee_args_count.reg());
20063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    lea(new_sp_reg,
20073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Operand(ebp, caller_args_count_reg, times_pointer_size,
20083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                StandardFrameConstants::kCallerPCOffset -
20093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                    number_of_temp_values_after_return_address * kPointerSize));
20103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
20113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    lea(new_sp_reg, Operand(ebp, caller_args_count_reg, times_pointer_size,
20123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                            StandardFrameConstants::kCallerPCOffset -
20133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                (callee_args_count.immediate() +
20143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                 number_of_temp_values_after_return_address) *
20153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                    kPointerSize));
20163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
20173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
20183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (FLAG_debug_code) {
20193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    cmp(esp, new_sp_reg);
20203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Check(below, kStackAccessBelowStackPointer);
20213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
20223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
20233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Copy return address from caller's frame to current frame's return address
20243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // to avoid its trashing and let the following loop copy it to the right
20253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // place.
20263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Register tmp_reg = scratch1;
20273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (ra_state == ReturnAddressState::kOnStack) {
20283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    mov(tmp_reg, Operand(ebp, StandardFrameConstants::kCallerPCOffset));
20293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    mov(Operand(esp, number_of_temp_values_after_return_address * kPointerSize),
20303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        tmp_reg);
20313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
20323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(ReturnAddressState::kNotOnStack == ra_state);
20333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK_EQ(0, number_of_temp_values_after_return_address);
20343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Push(Operand(ebp, StandardFrameConstants::kCallerPCOffset));
20353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
20363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
20373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Restore caller's frame pointer now as it could be overwritten by
20383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // the copying loop.
20393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(ebp, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
20403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
20413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // +2 here is to copy both receiver and return address.
20423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Register count_reg = caller_args_count_reg;
20433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (callee_args_count.is_reg()) {
20443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    lea(count_reg, Operand(callee_args_count.reg(),
20453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                           2 + number_of_temp_values_after_return_address));
20463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
20473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    mov(count_reg, Immediate(callee_args_count.immediate() + 2 +
20483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                             number_of_temp_values_after_return_address));
20493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // TODO(ishell): Unroll copying loop for small immediate values.
20503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
20513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
20523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Now copy callee arguments to the caller frame going backwards to avoid
20533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // callee arguments corruption (source and destination areas could overlap).
20543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label loop, entry;
20553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  jmp(&entry, Label::kNear);
20563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&loop);
20573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  dec(count_reg);
20583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(tmp_reg, Operand(esp, count_reg, times_pointer_size, 0));
20593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(Operand(new_sp_reg, count_reg, times_pointer_size, 0), tmp_reg);
20603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&entry);
20613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  cmp(count_reg, Immediate(0));
20623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  j(not_equal, &loop, Label::kNear);
20633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
20643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Leave current frame.
20653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(esp, new_sp_reg);
20663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
2067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokePrologue(const ParameterCount& expected,
2069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    const ParameterCount& actual,
2070257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Label* done,
20713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    bool* definitely_mismatches,
2072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                    InvokeFlag flag,
2073257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Label::Distance done_near,
2074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const CallWrapper& call_wrapper) {
2075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool definitely_matches = false;
20763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  *definitely_mismatches = false;
2077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label invoke;
2078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (expected.is_immediate()) {
2079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(actual.is_immediate());
2080014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mov(eax, actual.immediate());
2081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (expected.immediate() == actual.immediate()) {
2082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      definitely_matches = true;
2083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
2084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel;
2085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (expected.immediate() == sentinel) {
2086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Don't worry about adapting arguments for builtins that
2087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // don't want that done. Skip adaption code by making it look
2088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // like we have a match between expected and actual number of
2089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // arguments.
2090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        definitely_matches = true;
2091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
20923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        *definitely_mismatches = true;
2093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mov(ebx, expected.immediate());
2094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
2095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (actual.is_immediate()) {
2098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Expected is in register, actual is immediate. This is the
2099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // case when we invoke function values without going through the
2100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // IC mechanism.
2101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      mov(eax, actual.immediate());
2102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      cmp(expected.reg(), actual.immediate());
2103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      j(equal, &invoke);
2104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(expected.reg().is(ebx));
2105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else if (!expected.reg().is(actual.reg())) {
2106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Both expected and actual are in (different) registers. This
2107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // is the case when we invoke functions using call and apply.
21083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      cmp(expected.reg(), actual.reg());
2109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      j(equal, &invoke);
2110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(actual.reg().is(eax));
2111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(expected.reg().is(ebx));
2112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
2113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Move(eax, actual.reg());
2114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!definitely_matches) {
2118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Handle<Code> adaptor =
211944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        isolate()->builtins()->ArgumentsAdaptorTrampoline();
2120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (flag == CALL_FUNCTION) {
2121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      call_wrapper.BeforeCall(CallSize(adaptor, RelocInfo::CODE_TARGET));
2122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      call(adaptor, RelocInfo::CODE_TARGET);
2123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      call_wrapper.AfterCall();
21243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (!*definitely_mismatches) {
21253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        jmp(done, done_near);
21263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
2127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
2128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      jmp(adaptor, RelocInfo::CODE_TARGET);
2129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bind(&invoke);
2131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::FloodFunctionIfStepping(Register fun, Register new_target,
2136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                             const ParameterCount& expected,
2137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                             const ParameterCount& actual) {
2138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label skip_flooding;
213913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ExternalReference last_step_action =
214013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      ExternalReference::debug_last_step_action_address(isolate());
214113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  STATIC_ASSERT(StepFrame > StepIn);
214213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  cmpb(Operand::StaticVariable(last_step_action), Immediate(StepIn));
214313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  j(less, &skip_flooding);
2144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  {
2145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    FrameScope frame(this,
2146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     has_frame() ? StackFrame::NONE : StackFrame::INTERNAL);
2147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (expected.is_reg()) {
2148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SmiTag(expected.reg());
2149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Push(expected.reg());
2150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
2151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (actual.is_reg()) {
2152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SmiTag(actual.reg());
2153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Push(actual.reg());
2154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
2155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (new_target.is_valid()) {
2156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Push(new_target);
2157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
2158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(fun);
2159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(fun);
2160109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    CallRuntime(Runtime::kDebugPrepareStepInIfStepping);
2161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Pop(fun);
2162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (new_target.is_valid()) {
2163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pop(new_target);
2164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
2165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (actual.is_reg()) {
2166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pop(actual.reg());
2167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SmiUntag(actual.reg());
2168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
2169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (expected.is_reg()) {
2170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pop(expected.reg());
2171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SmiUntag(expected.reg());
2172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
2173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&skip_flooding);
2175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::InvokeFunctionCode(Register function, Register new_target,
2179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        const ParameterCount& expected,
2180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        const ParameterCount& actual,
2181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        InvokeFlag flag,
2182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        const CallWrapper& call_wrapper) {
21833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a function without a valid frame.
2184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(flag == JUMP_FUNCTION || has_frame());
2185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(function.is(edi));
2186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_IMPLIES(new_target.is_valid(), new_target.is(edx));
2187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (call_wrapper.NeedsDebugStepCheck()) {
2189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    FloodFunctionIfStepping(function, new_target, expected, actual);
2190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Clear the new.target register if not given.
2193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!new_target.is_valid()) {
2194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mov(edx, isolate()->factory()->undefined_value());
2195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
21963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
21983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool definitely_mismatches = false;
2199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InvokePrologue(expected, actual, &done, &definitely_mismatches, flag,
2200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 Label::kNear, call_wrapper);
22013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!definitely_mismatches) {
2202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // We call indirectly through the code field in the function to
2203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // allow recompilation to take effect without changing any of the
2204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // call sites.
2205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Operand code = FieldOperand(function, JSFunction::kCodeEntryOffset);
22063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (flag == CALL_FUNCTION) {
22073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call_wrapper.BeforeCall(CallSize(code));
22083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call(code);
22093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call_wrapper.AfterCall();
22103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
2211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(flag == JUMP_FUNCTION);
22123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      jmp(code);
22133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
22143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&done);
2215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeFunction(Register fun,
2220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    Register new_target,
2221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    const ParameterCount& actual,
2222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                    InvokeFlag flag,
2223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const CallWrapper& call_wrapper) {
22243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a function without a valid frame.
2225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(flag == JUMP_FUNCTION || has_frame());
22263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(fun.is(edi));
2228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
2229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
2230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kFormalParameterCountOffset));
22317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  SmiUntag(ebx);
2232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ParameterCount expected(ebx);
2234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InvokeFunctionCode(edi, new_target, expected, actual, flag, call_wrapper);
2235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::InvokeFunction(Register fun,
2239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const ParameterCount& expected,
2240402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                    const ParameterCount& actual,
2241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                    InvokeFlag flag,
2242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const CallWrapper& call_wrapper) {
22433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a function without a valid frame.
2244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(flag == JUMP_FUNCTION || has_frame());
22453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(fun.is(edi));
2247402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
2248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InvokeFunctionCode(edi, no_reg, expected, actual, flag, call_wrapper);
2250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::InvokeFunction(Handle<JSFunction> function,
2254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const ParameterCount& expected,
2255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const ParameterCount& actual,
2256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    InvokeFlag flag,
2257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const CallWrapper& call_wrapper) {
2258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LoadHeapObject(edi, function);
2259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InvokeFunction(edi, expected, actual, flag, call_wrapper);
2260402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
2261402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2263d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::LoadContext(Register dst, int context_chain_length) {
2264d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (context_chain_length > 0) {
2265d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Move up the chain of contexts to the context containing the slot.
22663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    mov(dst, Operand(esi, Context::SlotOffset(Context::PREVIOUS_INDEX)));
2267d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    for (int i = 1; i < context_chain_length; i++) {
22683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      mov(dst, Operand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX)));
2269d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
22701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
22711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Slot is in the current function context.  Move it into the
22721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // destination register in case we store into it (the write barrier
22731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // cannot be allowed to destroy the context in esi).
22741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    mov(dst, esi);
22751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
22761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
22773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // We should not have found a with context by walking the context chain
22781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // (i.e., the static scope chain and runtime context chain do not agree).
22791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // A variable occurring in such a scope should have slot type LOOKUP and
22801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // not CONTEXT.
228144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
22823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    cmp(FieldOperand(dst, HeapObject::kMapOffset),
22833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        isolate()->factory()->with_context_map());
2284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kVariableResolvedToWithContext);
2285d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2286d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2287d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2288d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LoadGlobalProxy(Register dst) {
2290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(dst, NativeContextOperand());
2291014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(dst, ContextOperand(dst, Context::GLOBAL_PROXY_INDEX));
2292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
22953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::LoadTransitionedArrayMapConditional(
22963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ElementsKind expected_kind,
22973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ElementsKind transitioned_kind,
22983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register map_in_out,
22993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch,
23003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* no_map_match) {
2301014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsFastElementsKind(expected_kind));
2302014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsFastElementsKind(transitioned_kind));
23033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check that the function's map is the same as the expected cached map.
2305014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(scratch, NativeContextOperand());
2306014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  cmp(map_in_out,
2307014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ContextOperand(scratch, Context::ArrayMapIndex(expected_kind)));
23083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_equal, no_map_match);
23093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Use the transitioned cached map.
2311014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(map_in_out,
2312014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ContextOperand(scratch, Context::ArrayMapIndex(transitioned_kind)));
23133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
23143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
231680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::LoadGlobalFunction(int index, Register function) {
2317014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Load the native context from the current context.
2318014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(function, NativeContextOperand());
2319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the function from the native context.
2320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(function, ContextOperand(function, index));
232180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
232280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
232380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
232480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
232580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                                  Register map) {
232680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Load the initial map.  The global functions all have initial maps.
232780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  mov(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
232844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
232980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Label ok, fail;
2330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CheckMap(map, isolate()->factory()->meta_map(), &fail, DO_SMI_CHECK);
233180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    jmp(&ok);
233280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    bind(&fail);
2333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Abort(kGlobalFunctionsMustHaveInitialMap);
233480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    bind(&ok);
233580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
233680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
233780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2338d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2339e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Store the value in register src in the safepoint register stack
2340e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// slot for register dst.
2341e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Register src) {
2342e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  mov(SafepointRegisterSlot(dst), src);
2343e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2344e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2345e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2346e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Immediate src) {
2347e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  mov(SafepointRegisterSlot(dst), src);
2348e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2349e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2350e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2351e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) {
2352e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  mov(dst, SafepointRegisterSlot(src));
2353e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2354e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2355e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2356e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochOperand MacroAssembler::SafepointRegisterSlot(Register reg) {
2357e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return Operand(esp, SafepointRegisterStackIndex(reg.code()) * kPointerSize);
2358e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2359e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2360e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochint MacroAssembler::SafepointRegisterStackIndex(int reg_code) {
2362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The registers are pushed starting with the lowest encoding,
2363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // which means that lowest encodings are furthest away from
2364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // the stack pointer.
2365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(reg_code >= 0 && reg_code < kNumSafepointRegisters);
2366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return kNumSafepointRegisters - reg_code - 1;
2367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
23703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::LoadHeapObject(Register result,
23713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    Handle<HeapObject> object) {
2372f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  mov(result, object);
23733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
23743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CmpHeapObject(Register reg, Handle<HeapObject> object) {
2377f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  cmp(reg, object);
23783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
23793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2380f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MacroAssembler::PushHeapObject(Handle<HeapObject> object) { Push(object); }
23813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2382958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::CmpWeakValue(Register value, Handle<WeakCell> cell,
2383958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                  Register scratch) {
2384958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  mov(scratch, cell);
2385958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  cmp(value, FieldOperand(scratch, WeakCell::kValueOffset));
2386958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2387958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2388958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2389014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::GetWeakValue(Register value, Handle<WeakCell> cell) {
2390958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  mov(value, cell);
2391958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  mov(value, FieldOperand(value, WeakCell::kValueOffset));
2392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2394014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2395014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LoadWeakValue(Register value, Handle<WeakCell> cell,
2396014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                   Label* miss) {
2397014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GetWeakValue(value, cell);
2398958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  JumpIfSmi(value, miss);
2399958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2400958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2401958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Ret() {
2403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ret(0);
2404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::Ret(int bytes_dropped, Register scratch) {
24081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (is_uint16(bytes_dropped)) {
24091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ret(bytes_dropped);
24101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
24111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    pop(scratch);
24123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    add(esp, Immediate(bytes_dropped));
24131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    push(scratch);
24141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ret(0);
24151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
24161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
24171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
24181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2419e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::Drop(int stack_elements) {
2420e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (stack_elements > 0) {
24213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    add(esp, Immediate(stack_elements * kPointerSize));
2422e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2423e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
2424e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2425e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
24260d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::Move(Register dst, Register src) {
24270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (!dst.is(src)) {
24280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    mov(dst, src);
24290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
24300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
24310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
24320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
2433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Move(Register dst, const Immediate& x) {
243413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (x.is_zero() && RelocInfo::IsNone(x.rmode_)) {
2435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    xor_(dst, dst);  // Shorter than mov of 32-bit immediate 0.
2436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(dst, x);
2438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Move(const Operand& dst, const Immediate& x) {
2443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(dst, x);
2444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2447958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::Move(XMMRegister dst, uint32_t src) {
2448958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (src == 0) {
2449958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    pxor(dst, dst);
2450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2451958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    unsigned cnt = base::bits::CountPopulation32(src);
2452958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    unsigned nlz = base::bits::CountLeadingZeros32(src);
2453958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    unsigned ntz = base::bits::CountTrailingZeros32(src);
2454958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (nlz + cnt + ntz == 32) {
2455958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      pcmpeqd(dst, dst);
2456958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (ntz == 0) {
2457958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        psrld(dst, 32 - cnt);
2458958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      } else {
2459958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        pslld(dst, 32 - cnt);
2460958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        if (nlz != 0) psrld(dst, nlz);
2461958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
2462958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
2463958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      push(eax);
2464958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      mov(eax, Immediate(src));
2465958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      movd(dst, Operand(eax));
2466958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      pop(eax);
2467958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
2468958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
2469958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2470958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2471958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2472958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::Move(XMMRegister dst, uint64_t src) {
2473014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (src == 0) {
2474014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    pxor(dst, dst);
2475958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
2476014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    uint32_t lower = static_cast<uint32_t>(src);
2477014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    uint32_t upper = static_cast<uint32_t>(src >> 32);
2478958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    unsigned cnt = base::bits::CountPopulation64(src);
2479958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    unsigned nlz = base::bits::CountLeadingZeros64(src);
2480958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    unsigned ntz = base::bits::CountTrailingZeros64(src);
2481958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (nlz + cnt + ntz == 64) {
2482958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      pcmpeqd(dst, dst);
2483958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (ntz == 0) {
2484958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        psrlq(dst, 64 - cnt);
2485958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      } else {
2486958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        psllq(dst, 64 - cnt);
2487958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        if (nlz != 0) psrlq(dst, nlz);
2488958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
2489958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else if (lower == 0) {
2490958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Move(dst, upper);
2491958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      psllq(dst, 32);
2492958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else if (CpuFeatures::IsSupported(SSE4_1)) {
2493958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      CpuFeatureScope scope(this, SSE4_1);
2494958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      push(eax);
2495958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Move(eax, Immediate(lower));
2496958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      movd(dst, Operand(eax));
2497958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Move(eax, Immediate(upper));
2498958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      pinsrd(dst, Operand(eax), 1);
2499958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      pop(eax);
2500958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
2501958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      push(Immediate(upper));
2502958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      push(Immediate(lower));
2503958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      movsd(dst, Operand(esp, 0));
2504958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      add(esp, Immediate(kDoubleSize));
2505958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
2506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2510014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Pextrd(Register dst, XMMRegister src, int8_t imm8) {
2511014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (imm8 == 0) {
2512014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movd(dst, src);
2513014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
2514014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2515014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(1, imm8);
2516014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(SSE4_1)) {
2517014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope sse_scope(this, SSE4_1);
2518014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    pextrd(dst, src, imm8);
2519014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
2520014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2521014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  pshufd(xmm0, src, 1);
2522014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movd(dst, xmm0);
2523014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2524014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2525014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2526014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Pinsrd(XMMRegister dst, const Operand& src, int8_t imm8) {
2527014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(imm8 == 0 || imm8 == 1);
2528014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(SSE4_1)) {
2529014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope sse_scope(this, SSE4_1);
2530014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    pinsrd(dst, src, imm8);
2531014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
2532014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2533014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movd(xmm0, src);
2534014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (imm8 == 1) {
2535014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    punpckldq(dst, xmm0);
2536014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2537014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK_EQ(0, imm8);
2538014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    psrlq(dst, 32);
2539014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    punpckldq(xmm0, dst);
2540014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movaps(dst, xmm0);
2541014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2542014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2543014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2544014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2545014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Lzcnt(Register dst, const Operand& src) {
2546014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(LZCNT)) {
2547014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, LZCNT);
2548014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    lzcnt(dst, src);
2549014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
2550014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2551014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label not_zero_src;
2552014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bsr(dst, src);
2553014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_zero, &not_zero_src, Label::kNear);
2554014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Move(dst, Immediate(63));  // 63^31 == 32
2555014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&not_zero_src);
2556014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  xor_(dst, Immediate(31));  // for x in [0..31], 31^x == 31-x.
2557014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2558014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2559014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2560014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Tzcnt(Register dst, const Operand& src) {
2561014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(BMI1)) {
2562014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, BMI1);
2563014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    tzcnt(dst, src);
2564014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
2565014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2566014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label not_zero_src;
2567014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bsf(dst, src);
2568014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_zero, &not_zero_src, Label::kNear);
2569014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Move(dst, Immediate(32));  // The result of tzcnt is 32 if src = 0.
2570014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&not_zero_src);
2571014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2572014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2573014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2574014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Popcnt(Register dst, const Operand& src) {
2575014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(POPCNT)) {
2576014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, POPCNT);
2577014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    popcnt(dst, src);
2578014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
2579014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2580014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  UNREACHABLE();
2581014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2582014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2583014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SetCounter(StatsCounter* counter, int value) {
2585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
2586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(Operand::StaticVariable(ExternalReference(counter)), Immediate(value));
2587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::IncrementCounter(StatsCounter* counter, int value) {
2592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(value > 0);
2593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
2594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Operand operand = Operand::StaticVariable(ExternalReference(counter));
2595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (value == 1) {
2596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      inc(operand);
2597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
2598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      add(operand, Immediate(value));
2599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::DecrementCounter(StatsCounter* counter, int value) {
2605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(value > 0);
2606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
2607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Operand operand = Operand::StaticVariable(ExternalReference(counter));
2608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (value == 1) {
2609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      dec(operand);
2610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
2611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      sub(operand, Immediate(value));
2612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2617d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid MacroAssembler::IncrementCounter(Condition cc,
2618d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                      StatsCounter* counter,
2619d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                      int value) {
2620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(value > 0);
2621d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (FLAG_native_code_counters && counter->Enabled()) {
2622d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Label skip;
2623d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    j(NegateCondition(cc), &skip);
2624d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    pushfd();
2625d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    IncrementCounter(counter, value);
2626d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    popfd();
2627d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    bind(&skip);
2628d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
2629d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
2630d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2631d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2632d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid MacroAssembler::DecrementCounter(Condition cc,
2633d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                      StatsCounter* counter,
2634d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                      int value) {
2635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(value > 0);
2636d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (FLAG_native_code_counters && counter->Enabled()) {
2637d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Label skip;
2638d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    j(NegateCondition(cc), &skip);
2639d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    pushfd();
2640d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    DecrementCounter(counter, value);
2641d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    popfd();
2642d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    bind(&skip);
2643d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
2644d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
2645d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2646d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Assert(Condition cc, BailoutReason reason) {
2648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) Check(cc, reason);
2649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2652756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid MacroAssembler::AssertFastElements(Register elements) {
265344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
265444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Factory* factory = isolate()->factory();
2655756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Label ok;
2656756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    cmp(FieldOperand(elements, HeapObject::kMapOffset),
265744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Immediate(factory->fixed_array_map()));
2658756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    j(equal, &ok);
2659756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    cmp(FieldOperand(elements, HeapObject::kMapOffset),
26603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        Immediate(factory->fixed_double_array_map()));
26613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    j(equal, &ok);
26623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    cmp(FieldOperand(elements, HeapObject::kMapOffset),
266344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Immediate(factory->fixed_cow_array_map()));
2664756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    j(equal, &ok);
2665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Abort(kJSObjectWithFastElementsMapHasSlowElements);
2666756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    bind(&ok);
2667756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
2668756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
2669756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2670756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Check(Condition cc, BailoutReason reason) {
2672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label L;
2673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(cc, &L);
2674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Abort(reason);
2675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // will not return here
2676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&L);
2677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26806ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::CheckStackAlignment() {
2681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int frame_alignment = base::OS::ActivationFrameAlignment();
26826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int frame_alignment_mask = frame_alignment - 1;
26836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (frame_alignment > kPointerSize) {
2684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
26856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Label alignment_as_expected;
26866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    test(esp, Immediate(frame_alignment_mask));
26876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    j(zero, &alignment_as_expected);
26886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Abort if stack is not aligned.
26896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int3();
26906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    bind(&alignment_as_expected);
26916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
26926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
26936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
26946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Abort(BailoutReason reason) {
2696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* msg = GetBailoutReason(reason);
2698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (msg != NULL) {
2699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RecordComment("Abort message: ");
2700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RecordComment(msg);
2701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_trap_on_abort) {
2704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int3();
2705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
2706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2708d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2709f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Check if Abort() has already been initialized.
2710f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(isolate()->builtins()->Abort()->IsHeapObject());
2711f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2712f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Move(edx, Smi::FromInt(static_cast<int>(reason)));
2713f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
27143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Disable stub call restrictions to always allow calls to abort.
27153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!has_frame_) {
27163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // We don't actually want to generate a pile of code for this, so just
27173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // claim there is a stack frame, without generating one.
27183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(this, StackFrame::NONE);
2719f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Call(isolate()->builtins()->Abort(), RelocInfo::CODE_TARGET);
27203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
2721f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Call(isolate()->builtins()->Abort(), RelocInfo::CODE_TARGET);
27223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // will not return here
2724d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int3();
2725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::LoadInstanceDescriptors(Register map,
2729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Register descriptors) {
2730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(descriptors, FieldOperand(map, Map::kDescriptorsOffset));
2731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) {
2735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(dst, FieldOperand(map, Map::kBitField3Offset));
2736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DecodeField<Map::NumberOfOwnDescriptorsBits>(dst);
2737756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
2738756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2739756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2740014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LoadAccessor(Register dst, Register holder,
2741014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  int accessor_index,
2742014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  AccessorComponent accessor) {
2743014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(dst, FieldOperand(holder, HeapObject::kMapOffset));
2744014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LoadInstanceDescriptors(dst, dst);
2745014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(dst, FieldOperand(dst, DescriptorArray::GetValueOffset(accessor_index)));
2746014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int offset = accessor == ACCESSOR_GETTER ? AccessorPair::kGetterOffset
2747014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                           : AccessorPair::kSetterOffset;
2748014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(dst, FieldOperand(dst, offset));
2749014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2750014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2751014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
27520d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::LoadPowerOf2(XMMRegister dst,
27530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                  Register scratch,
27540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                  int power) {
2755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uintn(power + HeapNumber::kExponentBias,
27560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                  HeapNumber::kExponentBits));
27570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  mov(scratch, Immediate(power + HeapNumber::kExponentBias));
27583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movd(dst, scratch);
27590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  psllq(dst, HeapNumber::kMantissaBits);
27600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
27610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
27620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
2763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfInstanceTypeIsNotSequentialOneByte(
2764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register instance_type, Register scratch, Label* failure) {
2765402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (!scratch.is(instance_type)) {
2766402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    mov(scratch, instance_type);
2767402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
2768402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  and_(scratch,
2769402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu       kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask);
2770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(scratch, kStringTag | kSeqStringTag | kOneByteStringTag);
2771402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  j(not_equal, failure);
2772402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
2773402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2774402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfNotBothSequentialOneByteStrings(Register object1,
2776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                           Register object2,
2777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                           Register scratch1,
2778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                           Register scratch2,
2779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                           Label* failure) {
2780d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Check that both objects are not smis.
278169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
27823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(scratch1, object1);
27833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(scratch1, object2);
27843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  JumpIfSmi(scratch1, failure);
2785d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2786d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Load instance type for both strings.
2787d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  mov(scratch1, FieldOperand(object1, HeapObject::kMapOffset));
2788d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  mov(scratch2, FieldOperand(object2, HeapObject::kMapOffset));
2789d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  movzx_b(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset));
2790d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  movzx_b(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset));
2791d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that both are flat one-byte strings.
2793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kFlatOneByteStringMask =
2794d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
2795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kFlatOneByteStringTag =
2796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kStringTag | kOneByteStringTag | kSeqStringTag;
2797d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Interleave bits from both instance types and compare them in one check.
2798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0, kFlatOneByteStringMask & (kFlatOneByteStringMask << 3));
2799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  and_(scratch1, kFlatOneByteStringMask);
2800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  and_(scratch2, kFlatOneByteStringMask);
2801d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  lea(scratch1, Operand(scratch1, scratch2, times_8, 0));
2802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(scratch1, kFlatOneByteStringTag | (kFlatOneByteStringTag << 3));
2803d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  j(not_equal, failure);
2804d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
2805d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2806d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfNotUniqueNameInstanceType(Operand operand,
2808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                     Label* not_unique_name,
2809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                     Label::Distance distance) {
2810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
2811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label succeed;
2812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  test(operand, Immediate(kIsNotStringMask | kIsNotInternalizedMask));
2813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(zero, &succeed);
28143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  cmpb(operand, Immediate(SYMBOL_TYPE));
2815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(not_equal, not_unique_name, distance);
2816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&succeed);
2818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::EmitSeqStringSetCharCheck(Register string,
2822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register index,
2823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register value,
2824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               uint32_t encoding_mask) {
2825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label is_object;
2826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JumpIfNotSmi(string, &is_object, Label::kNear);
2827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Abort(kNonObject);
2828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&is_object);
2829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  push(value);
2831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(value, FieldOperand(string, HeapObject::kMapOffset));
2832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movzx_b(value, FieldOperand(value, Map::kInstanceTypeOffset));
2833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  and_(value, Immediate(kStringRepresentationMask | kStringEncodingMask));
2835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(value, Immediate(encoding_mask));
2836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pop(value);
2837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(equal, kUnexpectedStringType);
2838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The index is assumed to be untagged coming in, tag it to compare with the
2840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // string length without using a temp register, it is restored at the end of
2841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // this function.
2842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiTag(index);
2843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(no_overflow, kIndexIsTooLarge);
2844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(index, FieldOperand(string, String::kLengthOffset));
2846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(less, kIndexIsTooLarge);
2847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2848c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  cmp(index, Immediate(Smi::kZero));
2849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(greater_equal, kIndexIsNegative);
2850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Restore the index
2852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiUntag(index);
2853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
28566ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::PrepareCallCFunction(int num_arguments, Register scratch) {
2857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int frame_alignment = base::OS::ActivationFrameAlignment();
28588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (frame_alignment != 0) {
28596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Make stack end at alignment and make room for num_arguments words
28606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // and the original value of esp.
28616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    mov(scratch, esp);
28623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sub(esp, Immediate((num_arguments + 1) * kPointerSize));
2863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
28648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    and_(esp, -frame_alignment);
28656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    mov(Operand(esp, num_arguments * kPointerSize), scratch);
28666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
28673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sub(esp, Immediate(num_arguments * kPointerSize));
28686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
28696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
28706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
28716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
28726ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::CallCFunction(ExternalReference function,
28736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                   int num_arguments) {
28746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Trashing eax is ok as it will be the return value.
28753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(eax, Immediate(function));
28766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CallCFunction(eax, num_arguments);
28776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
28786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
28796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
28806ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::CallCFunction(Register function,
28816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                   int num_arguments) {
2882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(has_frame());
28836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check stack alignment.
288444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
28856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CheckStackAlignment();
28866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
28876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
28883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  call(function);
2889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (base::OS::ActivationFrameAlignment() != 0) {
28906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    mov(esp, Operand(esp, num_arguments * kPointerSize));
28916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
28923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    add(esp, Immediate(num_arguments * kPointerSize));
28936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
28946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
28956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
28966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
2898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool AreAliased(Register reg1,
2899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg2,
2900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg3,
2901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg4,
2902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg5,
2903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg6,
2904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg7,
2905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg8) {
2906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int n_of_valid_regs = reg1.is_valid() + reg2.is_valid() +
2907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reg3.is_valid() + reg4.is_valid() + reg5.is_valid() + reg6.is_valid() +
2908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reg7.is_valid() + reg8.is_valid();
2909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RegList regs = 0;
2911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg1.is_valid()) regs |= reg1.bit();
2912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg2.is_valid()) regs |= reg2.bit();
2913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg3.is_valid()) regs |= reg3.bit();
2914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg4.is_valid()) regs |= reg4.bit();
2915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg5.is_valid()) regs |= reg5.bit();
2916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg6.is_valid()) regs |= reg6.bit();
2917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg7.is_valid()) regs |= reg7.bit();
2918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg8.is_valid()) regs |= reg8.bit();
2919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int n_of_non_aliasing_regs = NumRegs(regs);
2920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return n_of_valid_regs != n_of_non_aliasing_regs;
29223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
2923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
29243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2926014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochCodePatcher::CodePatcher(Isolate* isolate, byte* address, int size)
29278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    : address_(address),
29288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      size_(size),
2929014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      masm_(isolate, address, size + Assembler::kGap, CodeObjectRequired::kNo) {
2930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a new macro assembler pointing to the address of the code to patch.
2931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The size is adjusted with kGap on order for the assembler to generate size
2932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // bytes of instructions without failing with buffer size constraints.
2933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
2934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCodePatcher::~CodePatcher() {
2938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Indicate that code has changed.
2939014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Assembler::FlushICache(masm_.isolate(), address_, size_);
2940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the code was patched as expected.
2942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(masm_.pc_ == address_ + size_);
2943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
2944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckPageFlag(
29483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register object,
29493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch,
29503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int mask,
29513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Condition cc,
29523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* condition_met,
29533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label::Distance condition_met_distance) {
2954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(cc == zero || cc == not_zero);
29553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (scratch.is(object)) {
29563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    and_(scratch, Immediate(~Page::kPageAlignmentMask));
29573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
29583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(scratch, Immediate(~Page::kPageAlignmentMask));
29593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    and_(scratch, object);
29603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
29613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (mask < (1 << kBitsPerByte)) {
29623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    test_b(Operand(scratch, MemoryChunk::kFlagsOffset), Immediate(mask));
29633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
29643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    test(Operand(scratch, MemoryChunk::kFlagsOffset), Immediate(mask));
29653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
29663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(cc, condition_met, condition_met_distance);
29673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
29683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CheckPageFlagForMap(
2971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Map> map,
2972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int mask,
2973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Condition cc,
2974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label* condition_met,
2975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label::Distance condition_met_distance) {
2976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(cc == zero || cc == not_zero);
2977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Page* page = Page::FromAddress(map->address());
2978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!serializer_enabled());  // Serializer cannot match page_flags.
2979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference reference(ExternalReference::page_flags(page));
2980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The inlined static address check of the page's flags relies
2981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // on maps never being compacted.
2982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!isolate()->heap()->mark_compact_collector()->
2983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         IsOnEvacuationCandidate(*map));
2984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (mask < (1 << kBitsPerByte)) {
29853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    test_b(Operand::StaticVariable(reference), Immediate(mask));
2986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test(Operand::StaticVariable(reference), Immediate(mask));
2988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(cc, condition_met, condition_met_distance);
2990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
29933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::JumpIfBlack(Register object,
29943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register scratch0,
29953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register scratch1,
29963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Label* on_black,
29973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Label::Distance on_black_near) {
2998014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  HasColor(object, scratch0, scratch1, on_black, on_black_near, 1,
2999014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch           1);  // kBlackBitPattern.
3000014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0);
30013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
30023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::HasColor(Register object,
30053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Register bitmap_scratch,
30063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Register mask_scratch,
30073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Label* has_color,
30083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Label::Distance has_color_distance,
30093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              int first_bit,
30103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              int second_bit) {
3011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(object, bitmap_scratch, mask_scratch, ecx));
30123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GetMarkBits(object, bitmap_scratch, mask_scratch);
30143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label other_color, word_boundary;
30163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
30173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(first_bit == 1 ? zero : not_zero, &other_color, Label::kNear);
30183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(mask_scratch, mask_scratch);  // Shift left 1 by adding.
30193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(zero, &word_boundary, Label::kNear);
30203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
30213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(second_bit == 1 ? not_zero : zero, has_color, has_color_distance);
30223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  jmp(&other_color, Label::kNear);
30233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&word_boundary);
30253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test_b(Operand(bitmap_scratch, MemoryChunk::kHeaderSize + kPointerSize),
30263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch         Immediate(1));
30273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(second_bit == 1 ? not_zero : zero, has_color, has_color_distance);
30293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&other_color);
30303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
30313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::GetMarkBits(Register addr_reg,
30343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register bitmap_reg,
30353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register mask_reg) {
3036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(addr_reg, mask_reg, bitmap_reg, ecx));
30373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(bitmap_reg, Immediate(~Page::kPageAlignmentMask));
30383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(bitmap_reg, addr_reg);
30393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(ecx, addr_reg);
30403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int shift =
30413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Bitmap::kBitsPerCellLog2 + kPointerSizeLog2 - Bitmap::kBytesPerCellLog2;
30423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  shr(ecx, shift);
30433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(ecx,
30443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       (Page::kPageAlignmentMask >> shift) & ~(Bitmap::kBytesPerCell - 1));
30453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(bitmap_reg, ecx);
30473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(ecx, addr_reg);
30483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  shr(ecx, kPointerSizeLog2);
30493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(ecx, (1 << Bitmap::kBitsPerCellLog2) - 1);
30503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(mask_reg, Immediate(1));
30513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  shl_cl(mask_reg);
30523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
30533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3055014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::JumpIfWhite(Register value, Register bitmap_scratch,
3056014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 Register mask_scratch, Label* value_is_white,
3057014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 Label::Distance distance) {
3058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(value, bitmap_scratch, mask_scratch, ecx));
30593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GetMarkBits(value, bitmap_scratch, mask_scratch);
30603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If the value is black or grey we don't need to do anything.
3062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0);
3063014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0);
3064014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(strcmp(Marking::kGreyBitPattern, "10") == 0);
3065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0);
30663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Since both black and grey have a 1 in the first position and white does
30683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // not have a 1 there we only need to check one bit.
30693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
3070014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(zero, value_is_white, Label::kNear);
30713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
30723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::EnumLength(Register dst, Register map) {
3075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(Map::EnumLengthBits::kShift == 0);
3076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(dst, FieldOperand(map, Map::kBitField3Offset));
3077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  and_(dst, Immediate(Map::EnumLengthBits::kMask));
3078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiTag(dst);
3079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
30823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckEnumCache(Label* call_runtime) {
3083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label next, start;
30843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(ecx, eax);
3085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check if the enum length field is properly initialized, indicating that
3087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // there is an enum cache.
3088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset));
3089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EnumLength(edx, ebx);
3091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(edx, Immediate(Smi::FromInt(kInvalidEnumCacheSentinel)));
3092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(equal, call_runtime);
3093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  jmp(&start);
3095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
30963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&next);
3097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset));
30983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // For all objects but the receiver, check that the cache is empty.
3100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EnumLength(edx, ebx);
3101c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  cmp(edx, Immediate(Smi::kZero));
31023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_equal, call_runtime);
31033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&start);
31053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that there are no elements. Register rcx contains the current JS
3107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // object we've reached through the prototype chain.
3108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label no_elements;
3109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset));
3110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(ecx, isolate()->factory()->empty_fixed_array());
3111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(equal, &no_elements);
31123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Second chance, the object may be using the empty slow element dictionary.
3114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(ecx, isolate()->factory()->empty_slow_element_dictionary());
31153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_equal, call_runtime);
31163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&no_elements);
31183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset));
31193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmp(ecx, isolate()->factory()->null_value());
31203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_equal, &next);
31213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
31223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TestJSArrayForAllocationMemento(
3125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register receiver_reg,
3126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch_reg,
3127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label* no_memento_found) {
31283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label map_check;
31293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label top_check;
3130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference new_space_allocation_top =
3131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::new_space_allocation_top_address(isolate());
31323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  const int kMementoMapOffset = JSArray::kSize - kHeapObjectTag;
3133c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  const int kMementoLastWordOffset =
3134c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      kMementoMapOffset + AllocationMemento::kSize - kPointerSize;
31353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
31363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Bail out if the object is not in new space.
31373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  JumpIfNotInNewSpace(receiver_reg, scratch_reg, no_memento_found);
31383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // If the object is in new space, we need to check whether it is on the same
31393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // page as the current top.
3140c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  lea(scratch_reg, Operand(receiver_reg, kMementoLastWordOffset));
31413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  xor_(scratch_reg, Operand::StaticVariable(new_space_allocation_top));
31423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test(scratch_reg, Immediate(~Page::kPageAlignmentMask));
31433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  j(zero, &top_check);
31443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // The object is on a different page than allocation top. Bail out if the
31453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // object sits on the page boundary as no memento can follow and we cannot
31463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // touch the memory following it.
3147c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  lea(scratch_reg, Operand(receiver_reg, kMementoLastWordOffset));
31483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  xor_(scratch_reg, receiver_reg);
31493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  test(scratch_reg, Immediate(~Page::kPageAlignmentMask));
31503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  j(not_zero, no_memento_found);
31513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Continue with the actual map check.
31523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  jmp(&map_check);
31533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // If top is on the same page as the current object, we need to check whether
31543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // we are below top.
31553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&top_check);
3156c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  lea(scratch_reg, Operand(receiver_reg, kMementoLastWordOffset));
3157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(scratch_reg, Operand::StaticVariable(new_space_allocation_top));
3158c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  j(greater_equal, no_memento_found);
31593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Memento map check.
31603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&map_check);
31613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(scratch_reg, Operand(receiver_reg, kMementoMapOffset));
31623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  cmp(scratch_reg, Immediate(isolate()->factory()->allocation_memento_map()));
3163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfDictionaryInPrototypeChain(
3167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register object,
3168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch0,
3169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch1,
3170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label* found) {
3171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!scratch1.is(scratch0));
3172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Factory* factory = isolate()->factory();
3173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register current = scratch0;
3174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label loop_again, end;
3175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // scratch contained elements pointer.
3177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(current, object);
3178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(current, FieldOperand(current, HeapObject::kMapOffset));
3179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mov(current, FieldOperand(current, Map::kPrototypeOffset));
3180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  cmp(current, Immediate(factory->null_value()));
3181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(equal, &end);
3182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Loop based on the map going up the prototype chain.
3184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&loop_again);
3185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(current, FieldOperand(current, HeapObject::kMapOffset));
3186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(JS_PROXY_TYPE < JS_OBJECT_TYPE);
3187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(JS_VALUE_TYPE < JS_OBJECT_TYPE);
3188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CmpInstanceType(current, JS_OBJECT_TYPE);
3189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(below, found);
3190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(scratch1, FieldOperand(current, Map::kBitField2Offset));
3191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DecodeField<Map::ElementsKindBits>(scratch1);
3192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(scratch1, Immediate(DICTIONARY_ELEMENTS));
3193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(equal, found);
3194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(current, FieldOperand(current, Map::kPrototypeOffset));
3195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmp(current, Immediate(factory->null_value()));
3196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(not_equal, &loop_again);
3197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&end);
3199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TruncatingDiv(Register dividend, int32_t divisor) {
3203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dividend.is(eax));
3204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dividend.is(edx));
3205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::MagicNumbersForDivision<uint32_t> mag =
3206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      base::SignedDivisionByConstant(static_cast<uint32_t>(divisor));
3207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(eax, Immediate(mag.multiplier));
3208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  imul(dividend);
3209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool neg = (mag.multiplier & (static_cast<uint32_t>(1) << 31)) != 0;
3210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor > 0 && neg) add(edx, dividend);
3211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor < 0 && !neg && mag.multiplier > 0) sub(edx, dividend);
3212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (mag.shift > 0) sar(edx, mag.shift);
3213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(eax, dividend);
3214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shr(eax, 31);
3215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  add(edx, eax);
3216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
3220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
3221f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3222f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_IA32
3223