13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h"
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_X64)
31f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "bootstrapper.h"
338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "codegen.h"
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "assembler-x64.h"
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "macro-assembler-x64.h"
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "serialize.h"
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "debug.h"
389dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen#include "heap.h"
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
438b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochMacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size)
448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    : Assembler(arg_isolate, buffer, size),
453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      generating_stub_(false),
463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      allow_stub_calls_(true),
473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      has_frame_(false),
488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      root_array_available_(true) {
498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (isolate() != NULL) {
508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    code_object_ = Handle<Object>(isolate()->heap()->undefined_value(),
518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                  isolate());
528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
5344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
5444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic intptr_t RootRegisterDelta(ExternalReference other, Isolate* isolate) {
5744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Address roots_register_value = kRootRegisterBias +
583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      reinterpret_cast<Address>(isolate->heap()->roots_array_start());
5944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  intptr_t delta = other.address() - roots_register_value;
6044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return delta;
6144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
6244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6444f0eee88ff00398ff7f715fab053374d808c90dSteve BlockOperand MacroAssembler::ExternalOperand(ExternalReference target,
6544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                        Register scratch) {
6644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (root_array_available_ && !Serializer::enabled()) {
6744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    intptr_t delta = RootRegisterDelta(target, isolate());
6844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (is_int32(delta)) {
6944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Serializer::TooLateToEnableNow();
7044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      return Operand(kRootRegister, static_cast<int32_t>(delta));
7144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
7244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
7344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  movq(scratch, target);
7444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return Operand(scratch, 0);
7544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
7644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
7744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
7844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::Load(Register destination, ExternalReference source) {
7944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (root_array_available_ && !Serializer::enabled()) {
8044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    intptr_t delta = RootRegisterDelta(source, isolate());
8144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (is_int32(delta)) {
8244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Serializer::TooLateToEnableNow();
8344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      movq(destination, Operand(kRootRegister, static_cast<int32_t>(delta)));
8444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      return;
8544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
8644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
8744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Safe code.
8844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (destination.is(rax)) {
8944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    load_rax(source);
9044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
9144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    movq(kScratchRegister, source);
9244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    movq(destination, Operand(kScratchRegister, 0));
9344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
9444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
9544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
9644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
9744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::Store(ExternalReference destination, Register source) {
9844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (root_array_available_ && !Serializer::enabled()) {
9944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    intptr_t delta = RootRegisterDelta(destination, isolate());
10044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (is_int32(delta)) {
10144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Serializer::TooLateToEnableNow();
10244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      movq(Operand(kRootRegister, static_cast<int32_t>(delta)), source);
10344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      return;
10444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
10544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
10644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Safe code.
10744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (source.is(rax)) {
10844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    store_rax(destination);
10944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
11044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    movq(kScratchRegister, destination);
11144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    movq(Operand(kScratchRegister, 0), source);
11244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
11344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
11444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
11544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
11644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::LoadAddress(Register destination,
11744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                 ExternalReference source) {
11844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (root_array_available_ && !Serializer::enabled()) {
11944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    intptr_t delta = RootRegisterDelta(source, isolate());
12044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (is_int32(delta)) {
12144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Serializer::TooLateToEnableNow();
12244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      lea(destination, Operand(kRootRegister, static_cast<int32_t>(delta)));
12344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      return;
12444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
12544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
12644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Safe code.
12744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  movq(destination, source);
12844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
12944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
13044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
13144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint MacroAssembler::LoadAddressSize(ExternalReference source) {
13244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (root_array_available_ && !Serializer::enabled()) {
13344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // This calculation depends on the internals of LoadAddress.
13444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // It's correctness is ensured by the asserts in the Call
13544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // instruction below.
13644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    intptr_t delta = RootRegisterDelta(source, isolate());
13744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (is_int32(delta)) {
13844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Serializer::TooLateToEnableNow();
13944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Operand is lea(scratch, Operand(kRootRegister, delta));
14044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Opcodes : REX.W 8D ModRM Disp8/Disp32  - 4 or 7.
14144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      int size = 4;
14244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (!is_int8(static_cast<int32_t>(delta))) {
14344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        size += 3;  // Need full four-byte displacement in lea.
14444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
14544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      return size;
14644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
14744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
14844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Size of movq(destination, src);
14944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return 10;
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index) {
15444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(root_array_available_);
155e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  movq(destination, Operand(kRootRegister,
156e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                            (index << kPointerSizeLog2) - kRootRegisterBias));
157e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
158e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
159e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
160e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::LoadRootIndexed(Register destination,
161e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                     Register variable_offset,
162e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                     int fixed_offset) {
16344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(root_array_available_);
164e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  movq(destination,
165e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch       Operand(kRootRegister,
166e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch               variable_offset, times_pointer_size,
167e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch               (fixed_offset << kPointerSizeLog2) - kRootRegisterBias));
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsenvoid MacroAssembler::StoreRoot(Register source, Heap::RootListIndex index) {
17244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(root_array_available_);
173e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  movq(Operand(kRootRegister, (index << kPointerSizeLog2) - kRootRegisterBias),
174e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch       source);
17525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen}
17625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
17725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::PushRoot(Heap::RootListIndex index) {
17944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(root_array_available_);
180e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  push(Operand(kRootRegister, (index << kPointerSizeLog2) - kRootRegisterBias));
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) {
18544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(root_array_available_);
186e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  cmpq(with, Operand(kRootRegister,
187e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                     (index << kPointerSizeLog2) - kRootRegisterBias));
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::CompareRoot(const Operand& with,
1921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                 Heap::RootListIndex index) {
19344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(root_array_available_);
1941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(!with.AddressUsesRegister(kScratchRegister));
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LoadRoot(kScratchRegister, index);
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cmpq(with, kScratchRegister);
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::RememberedSetHelper(Register object,  // For debug tests.
2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Register addr,
2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Register scratch,
2033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         SaveFPRegsMode save_fp,
2043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         RememberedSetFinalAction and_then) {
2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_debug_code) {
2063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label ok;
2073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JumpIfNotInNewSpace(object, scratch, &ok, Label::kNear);
2083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int3();
2093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&ok);
2103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load store buffer top.
2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LoadRoot(scratch, Heap::kStoreBufferTopRootIndex);
2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Store pointer to buffer.
2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movq(Operand(scratch, 0), addr);
2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Increment buffer top.
2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  addq(scratch, Immediate(kPointerSize));
2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Write back new top of buffer.
2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StoreRoot(scratch, Heap::kStoreBufferTopRootIndex);
2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Call stub on end of buffer.
2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for end of buffer.
2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  testq(scratch, Immediate(StoreBuffer::kStoreBufferOverflowBit));
2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (and_then == kReturnAtEnd) {
2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label buffer_overflowed;
2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(not_equal, &buffer_overflowed, Label::kNear);
2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ret(0);
2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&buffer_overflowed);
2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
2293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(and_then == kFallThroughAtEnd);
2303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(equal, &done, Label::kNear);
2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StoreBufferOverflowStub store_buffer_overflow =
2333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      StoreBufferOverflowStub(save_fp);
2343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallStub(&store_buffer_overflow);
2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (and_then == kReturnAtEnd) {
2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ret(0);
2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(and_then == kFallThroughAtEnd);
2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&done);
2406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::InNewSpace(Register object,
245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Register scratch,
246257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Condition cc,
247257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Label* branch,
2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                Label::Distance distance) {
249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (Serializer::enabled()) {
250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Can't do arithmetic on external references if it might get serialized.
251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // The mask isn't really an address.  We load it as an external reference in
252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // case the size of the new space is different between the snapshot maker
253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // and the running system.
254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (scratch.is(object)) {
255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      movq(kScratchRegister, ExternalReference::new_space_mask(isolate()));
256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      and_(scratch, kScratchRegister);
257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      movq(scratch, ExternalReference::new_space_mask(isolate()));
259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      and_(scratch, object);
260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(kScratchRegister, ExternalReference::new_space_start(isolate()));
262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    cmpq(scratch, kScratchRegister);
2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(cc, branch, distance);
264257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
265257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(is_int32(static_cast<int64_t>(HEAP->NewSpaceMask())));
266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    intptr_t new_space_start =
267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        reinterpret_cast<intptr_t>(HEAP->NewSpaceStart());
268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(kScratchRegister, -new_space_start, RelocInfo::NONE);
269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (scratch.is(object)) {
270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      addq(scratch, kScratchRegister);
271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      lea(scratch, Operand(object, kScratchRegister, times_1, 0));
273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    and_(scratch, Immediate(static_cast<int32_t>(HEAP->NewSpaceMask())));
2753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(cc, branch, distance);
276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::RecordWriteField(
2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register object,
2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int offset,
2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register value,
2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register dst,
2853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SaveFPRegsMode save_fp,
2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RememberedSetAction remembered_set_action,
2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SmiCheck smi_check) {
2884515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // The compiled code assumes that record write doesn't change the
2894515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // context register, so we check that none of the clobbered
2904515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // registers are rsi.
2913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!value.is(rsi) && !dst.is(rsi));
2924515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
2937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // First, check if a write barrier is even needed. The tests below
2943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // catch stores of Smis.
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label done;
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Skip barrier if writing a smi.
2983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (smi_check == INLINE_SMI_CHECK) {
2993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JumpIfSmi(value, &done);
3003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Although the object register is tagged, the offset is relative to the start
3033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // of the object, so so offset must be a multiple of kPointerSize.
3043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(IsAligned(offset, kPointerSize));
3053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lea(dst, FieldOperand(object, offset));
3073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (emit_debug_code()) {
3083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label ok;
3093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    testb(dst, Immediate((1 << kPointerSizeLog2) - 1));
3103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(zero, &ok, Label::kNear);
3113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int3();
3123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&ok);
3133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordWrite(
3163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      object, dst, value, save_fp, remembered_set_action, OMIT_SMI_CHECK);
3173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bind(&done);
3194515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
3203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Clobber clobbered input registers when running with the debug-code flag
3213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // turned on to provoke errors.
32244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
3236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
3243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    movq(dst, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
3254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
3263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
3273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::RecordWriteArray(Register object,
3303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Register value,
3313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Register index,
3323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      SaveFPRegsMode save_fp,
3333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      RememberedSetAction remembered_set_action,
3343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      SmiCheck smi_check) {
3358defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // First, check if a write barrier is even needed. The tests below
3363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // catch stores of Smis.
3378defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Label done;
3388defd9ff6930b4e24729971a61cf7469daf119beSteve Block
3393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Skip barrier if writing a smi.
3403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (smi_check == INLINE_SMI_CHECK) {
3413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JumpIfSmi(value, &done);
3423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3438defd9ff6930b4e24729971a61cf7469daf119beSteve Block
3443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Array access: calculate the destination address. Index is not a smi.
3453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register dst = index;
3463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lea(dst, Operand(object, index, times_pointer_size,
3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   FixedArray::kHeaderSize - kHeapObjectTag));
3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordWrite(
3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      object, dst, value, save_fp, remembered_set_action, OMIT_SMI_CHECK);
3518defd9ff6930b4e24729971a61cf7469daf119beSteve Block
3528defd9ff6930b4e24729971a61cf7469daf119beSteve Block  bind(&done);
3538defd9ff6930b4e24729971a61cf7469daf119beSteve Block
3543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Clobber clobbered input registers when running with the debug-code flag
3558defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // turned on to provoke errors.
35644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
3578defd9ff6930b4e24729971a61cf7469daf119beSteve Block    movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    movq(index, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
3598defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
3608defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
3618defd9ff6930b4e24729971a61cf7469daf119beSteve Block
3628defd9ff6930b4e24729971a61cf7469daf119beSteve Block
3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::RecordWrite(Register object,
3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register address,
3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register value,
3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 SaveFPRegsMode fp_mode,
3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 RememberedSetAction remembered_set_action,
3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 SmiCheck smi_check) {
3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The compiled code assumes that record write doesn't change the
3703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // context register, so we check that none of the clobbered
3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // registers are rsi.
3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!value.is(rsi) && !address.is(rsi));
3734515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
3743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!object.is(value));
3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!object.is(address));
3763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!value.is(address));
37744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    AbortIfSmi(object);
3794515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
3804515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
3813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (remembered_set_action == OMIT_REMEMBERED_SET &&
3823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      !FLAG_incremental_marking) {
3833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return;
3843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_debug_code) {
3873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label ok;
3883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    cmpq(value, Operand(address, 0));
3893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(equal, &ok, Label::kNear);
3903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int3();
3913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&ok);
3923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // First, check if a write barrier is even needed. The tests below
3953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // catch stores of smis and stores into the young generation.
3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (smi_check == INLINE_SMI_CHECK) {
3993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Skip barrier if writing a smi.
4003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JumpIfSmi(value, &done);
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPageFlag(value,
4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                value,  // Used as scratch.
4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                MemoryChunk::kPointersToHereAreInterestingMask,
4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                zero,
4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                &done,
4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                Label::kNear);
4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPageFlag(object,
4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                value,  // Used as scratch.
4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                MemoryChunk::kPointersFromHereAreInterestingMask,
4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                zero,
4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                &done,
4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                Label::kNear);
4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordWriteStub stub(object, value, address, remembered_set_action, fp_mode);
4183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallStub(&stub);
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&done);
4214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Clobber clobbered registers when running with the debug-code flag
4234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // turned on to provoke errors.
42444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
4253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    movq(address, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
4263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
4276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
4296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Assert(Condition cc, const char* msg) {
43244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) Check(cc, msg);
433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
436756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid MacroAssembler::AssertFastElements(Register elements) {
43744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label ok;
439756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
440756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                Heap::kFixedArrayMapRootIndex);
441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(equal, &ok, Label::kNear);
442756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
4433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                Heap::kFixedDoubleArrayMapRootIndex);
4443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    j(equal, &ok, Label::kNear);
4453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
446756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                Heap::kFixedCOWArrayMapRootIndex);
447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(equal, &ok, Label::kNear);
448756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Abort("JSObject with fast elements map has slow elements");
449756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    bind(&ok);
450756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
451756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
452756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
453756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Check(Condition cc, const char* msg) {
455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label L;
456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(cc, &L, Label::kNear);
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Abort(msg);
4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Control will not return here.
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&L);
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4636ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::CheckStackAlignment() {
4646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int frame_alignment = OS::ActivationFrameAlignment();
4656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int frame_alignment_mask = frame_alignment - 1;
4666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (frame_alignment > kPointerSize) {
4676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(IsPowerOf2(frame_alignment));
468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label alignment_as_expected;
4696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    testq(rsp, Immediate(frame_alignment_mask));
470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(zero, &alignment_as_expected, Label::kNear);
4716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Abort if stack is not aligned.
4726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int3();
4736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    bind(&alignment_as_expected);
4746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
4766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::NegativeZeroTest(Register result,
479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register op,
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Label* then_label) {
481257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label ok;
482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  testl(result, result);
483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_zero, &ok, Label::kNear);
484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  testl(op, op);
485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(sign, then_label);
486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&ok);
487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Abort(const char* msg) {
491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // We want to pass the msg string like a smi to avoid GC
492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // problems, however msg is not guaranteed to be aligned
493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // properly. Instead, we pass an aligned pointer that is
494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // a proper v8 smi, but also pass the alignment difference
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // from the real pointer as a smi.
496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  intptr_t p1 = reinterpret_cast<intptr_t>(msg);
497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  intptr_t p0 = (p1 & ~kSmiTagMask) + kSmiTag;
4983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Note: p0 might not be a valid Smi _value_, but it has a valid Smi tag.
499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(reinterpret_cast<Object*>(p0)->IsSmi());
500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (msg != NULL) {
502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RecordComment("Abort message: ");
503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RecordComment(msg);
504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(rax);
507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister, p0, RelocInfo::NONE);
508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(kScratchRegister);
509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister,
510d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block       reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(p1 - p0))),
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       RelocInfo::NONE);
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(kScratchRegister);
5133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!has_frame_) {
5153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // We don't actually want to generate a pile of code for this, so just
5163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // claim there is a stack frame, without generating one.
5173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(this, StackFrame::NONE);
5183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallRuntime(Runtime::kAbort, 2);
5193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
5203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallRuntime(Runtime::kAbort, 2);
5213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Control will not return here.
523d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int3();
524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
527257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::CallStub(CodeStub* stub, unsigned ast_id) {
5283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(AllowThisStubCall(stub));  // Calls are not allowed in some stubs
529257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id);
530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
533e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::TailCallStub(CodeStub* stub) {
5343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe());
535e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Jump(stub->GetCode(), RelocInfo::CODE_TARGET);
536e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
537e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
538e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
53985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochvoid MacroAssembler::StubReturn(int argc) {
54085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  ASSERT(argc >= 1 && generating_stub());
54185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  ret((argc - 1) * kPointerSize);
542592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch}
543592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
544592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
5453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
5463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!has_frame_ && stub->SometimesSetsUpAFrame()) return false;
5473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe();
5483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
5493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::IllegalOperation(int num_arguments) {
552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (num_arguments > 0) {
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    addq(rsp, Immediate(num_arguments * kPointerSize));
554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LoadRoot(rax, Heap::kUndefinedValueRootIndex);
556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
55980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::IndexFromHash(Register hash, Register index) {
56080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // The assert checks that the constants for the maximum number of digits
56180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // for an array index cached in the hash field and the number of bits
56280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // reserved for it does not conflict.
56380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
56480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen         (1 << String::kArrayIndexValueBits));
56580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // We want the smi-tagged index in key. Even if we subsequently go to
56680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // the slow case, converting the key to a smi is always valid.
56780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // key: string key
56880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // hash: key's hash field, including its array index value.
56980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  and_(hash, Immediate(String::kArrayIndexValueMask));
57080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  shr(hash, Immediate(String::kHashShift));
57180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Here we actually clobber the key which will be used if calling into
57280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // runtime later. However as the new key is the numeric value of a string key
57380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // there is no difference in using either key.
57480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Integer32ToSmi(index, hash);
57580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
57680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
57780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CallRuntime(Runtime::FunctionId id, int num_arguments) {
579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CallRuntime(Runtime::FunctionForId(id), num_arguments);
580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::CallRuntimeSaveDoubles(Runtime::FunctionId id) {
58444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const Runtime::Function* function = Runtime::FunctionForId(id);
5851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Set(rax, function->nargs);
58644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(rbx, ExternalReference(function, isolate()));
5873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CEntryStub ces(1, kSaveFPRegs);
5881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CallStub(&ces);
5891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
5901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
59244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CallRuntime(const Runtime::Function* f,
59344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                 int num_arguments) {
594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the expected number of arguments of the runtime function is
595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // constant, we check that the actual number of arguments match the
596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // expectation.
597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (f->nargs >= 0 && f->nargs != num_arguments) {
598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    IllegalOperation(num_arguments);
599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6024515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // TODO(1236192): Most runtime routines don't need the number of
6034515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // arguments passed in because it is constant. At some point we
6044515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // should remove this need and make the runtime routine entry code
6054515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // smarter.
6068defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Set(rax, num_arguments);
60744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(rbx, ExternalReference(f, isolate()));
6084515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  CEntryStub ces(f->result_size);
6094515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  CallStub(&ces);
610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
613402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::CallExternalReference(const ExternalReference& ext,
614402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                           int num_arguments) {
6158defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Set(rax, num_arguments);
61644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(rbx, ext);
617402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
618402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CEntryStub stub(1);
619402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CallStub(&stub);
620402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
621402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
622402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6236ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::TailCallExternalReference(const ExternalReference& ext,
6246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                               int num_arguments,
6256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                               int result_size) {
626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0] : return address
628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[8] : argument num_arguments - 1
629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  ...
630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[8 * num_arguments] : argument 0 (receiver)
631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // TODO(1236192): Most runtime routines don't need the number of
634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // arguments passed in because it is constant. At some point we
635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // should remove this need and make the runtime routine entry code
636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // smarter.
6378defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Set(rax, num_arguments);
6386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  JumpToExternalReference(ext, result_size);
639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6426ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::TailCallRuntime(Runtime::FunctionId fid,
6436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                     int num_arguments,
6446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                     int result_size) {
64544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  TailCallExternalReference(ExternalReference(fid, isolate()),
64644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                            num_arguments,
64744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                            result_size);
6486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
6496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
651bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochstatic int Offset(ExternalReference ref0, ExternalReference ref1) {
652bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  int64_t offset = (ref0.address() - ref1.address());
653bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Check that fits into int.
654bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ASSERT(static_cast<int>(offset) == offset);
655bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  return static_cast<int>(offset);
656bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
657bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
658bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
6598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid MacroAssembler::PrepareCallApiFunction(int arg_stack_space) {
6608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang#ifdef _WIN64
6618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // We need to prepare a slot for result handle on stack and put
6628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // a pointer to it into 1st arg register.
6638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  EnterApiExitFrame(arg_stack_space + 1);
6648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
6658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // rcx must be used to pass the pointer to the return value slot.
6668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  lea(rcx, StackSpaceOperand(arg_stack_space));
6678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang#else
6688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  EnterApiExitFrame(arg_stack_space);
6698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang#endif
670bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
671bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
672bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
6733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CallApiFunctionAndReturn(Address function_address,
6743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              int stack_space) {
6755913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Label empty_result;
6765913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Label prologue;
6775913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Label promote_scheduled_exception;
6785913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Label delete_allocated_handles;
6795913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Label leave_exit_frame;
680bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Label write_back;
681bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
682257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Factory* factory = isolate()->factory();
6835913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  ExternalReference next_address =
6845913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      ExternalReference::handle_scope_next_address();
6855913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  const int kNextOffset = 0;
6865913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  const int kLimitOffset = Offset(
6875913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      ExternalReference::handle_scope_limit_address(),
6885913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      next_address);
6895913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  const int kLevelOffset = Offset(
6905913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      ExternalReference::handle_scope_level_address(),
6915913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      next_address);
6925913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  ExternalReference scheduled_exception_address =
69344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::scheduled_exception_address(isolate());
6945913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck
6955913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  // Allocate HandleScope in callee-save registers.
6965913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Register prev_next_address_reg = r14;
6975913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Register prev_limit_reg = rbx;
69844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register base_reg = r15;
6995913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  movq(base_reg, next_address);
7005913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  movq(prev_next_address_reg, Operand(base_reg, kNextOffset));
7015913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  movq(prev_limit_reg, Operand(base_reg, kLimitOffset));
7025913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  addl(Operand(base_reg, kLevelOffset), Immediate(1));
7035913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  // Call the api function!
7043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movq(rax, reinterpret_cast<int64_t>(function_address),
7055913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck       RelocInfo::RUNTIME_ENTRY);
7065913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  call(rax);
707bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
7085913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck#ifdef _WIN64
7095913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  // rax keeps a pointer to v8::Handle, unpack it.
7105913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  movq(rax, Operand(rax, 0));
7115913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck#endif
7125913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  // Check if the result handle holds 0.
7135913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  testq(rax, rax);
7145913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  j(zero, &empty_result);
7155913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  // It was non-zero.  Dereference to get the result value.
7165913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  movq(rax, Operand(rax, 0));
7175913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  bind(&prologue);
7185913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck
7195913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  // No more valid handles (the result handle was the last one). Restore
7205913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  // previous handle scope.
7215913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  subl(Operand(base_reg, kLevelOffset), Immediate(1));
7225913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  movq(Operand(base_reg, kNextOffset), prev_next_address_reg);
7235913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  cmpq(prev_limit_reg, Operand(base_reg, kLimitOffset));
7245913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  j(not_equal, &delete_allocated_handles);
7255913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  bind(&leave_exit_frame);
7265913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck
7275913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  // Check if the function scheduled an exception.
7285913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  movq(rsi, scheduled_exception_address);
729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Cmp(Operand(rsi, 0), factory->the_hole_value());
7305913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  j(not_equal, &promote_scheduled_exception);
7315913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck
7328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LeaveApiExitFrame();
7338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  ret(stack_space * kPointerSize);
734bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
7355913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  bind(&promote_scheduled_exception);
7363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  TailCallRuntime(Runtime::kPromoteScheduledException, 0, 1);
737bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
7385913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  bind(&empty_result);
7395913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  // It was zero; the result is undefined.
740257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Move(rax, factory->undefined_value());
7415913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  jmp(&prologue);
742bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
7435913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  // HandleScope limit has changed. Delete allocated extensions.
7445913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  bind(&delete_allocated_handles);
7455913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  movq(Operand(base_reg, kLimitOffset), prev_limit_reg);
7465913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  movq(prev_limit_reg, rax);
74744f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef _WIN64
74844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(rcx, ExternalReference::isolate_address());
74944f0eee88ff00398ff7f715fab053374d808c90dSteve Block#else
75044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(rdi, ExternalReference::isolate_address());
75144f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
75244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(rax,
75344f0eee88ff00398ff7f715fab053374d808c90dSteve Block              ExternalReference::delete_handle_scope_extensions(isolate()));
7545913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  call(rax);
7555913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  movq(rax, prev_limit_reg);
7565913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  jmp(&leave_exit_frame);
757bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
758bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
759bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
7606ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::JumpToExternalReference(const ExternalReference& ext,
7616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                             int result_size) {
762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set the entry point and jump to the C entry runtime stub.
76344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(rbx, ext);
764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CEntryStub ces(result_size);
7653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  jmp(ces.GetCode(), RelocInfo::CODE_TARGET);
766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
769e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
770e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   InvokeFlag flag,
771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   const CallWrapper& call_wrapper) {
7723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a builtin without a valid frame.
7733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(flag == JUMP_FUNCTION || has_frame());
774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
775402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Rely on the assertion to check that the number of provided
776402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // arguments match the expected number of arguments. Fake a
777402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // parameter count to avoid emitting code to do the check.
778402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ParameterCount expected(0);
779402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GetBuiltinEntry(rdx, id);
780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  InvokeCode(rdx, expected, expected, flag, call_wrapper, CALL_AS_METHOD);
781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
783402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
784791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockvoid MacroAssembler::GetBuiltinFunction(Register target,
785791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                                        Builtins::JavaScript id) {
7866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Load the builtins object into target register.
7876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  movq(target, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
7886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  movq(target, FieldOperand(target, GlobalObject::kBuiltinsOffset));
789791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  movq(target, FieldOperand(target,
790791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                            JSBuiltinsObject::OffsetOfFunctionWithId(id)));
791791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block}
7926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
794791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockvoid MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
795791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  ASSERT(!target.is(rdi));
796791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  // Load the JavaScript builtin function from the builtins object.
797791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  GetBuiltinFunction(rdi, id);
798791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  movq(target, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#define REG(Name) { kRegister_ ## Name ## _Code }
8033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const Register saved_regs[] = {
8053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  REG(rax), REG(rcx), REG(rdx), REG(rbx), REG(rbp), REG(rsi), REG(rdi), REG(r8),
8063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  REG(r9), REG(r10), REG(r11)
8073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
8083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#undef REG
8103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const int kNumberOfSavedRegs = sizeof(saved_regs) / sizeof(Register);
8123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::PushCallerSaved(SaveFPRegsMode fp_mode,
8153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Register exclusion1,
8163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Register exclusion2,
8173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Register exclusion3) {
8183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We don't allow a GC during a store buffer overflow so there is no need to
8193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // store the registers in any particular way, but we do have to store and
8203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // restore them.
8213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < kNumberOfSavedRegs; i++) {
8223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register reg = saved_regs[i];
8233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!reg.is(exclusion1) && !reg.is(exclusion2) && !reg.is(exclusion3)) {
8243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      push(reg);
8253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
8263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
8273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // R12 to r15 are callee save on all platforms.
8283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (fp_mode == kSaveFPRegs) {
8293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CpuFeatures::Scope scope(SSE2);
8303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    subq(rsp, Immediate(kDoubleSize * XMMRegister::kNumRegisters));
8313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int i = 0; i < XMMRegister::kNumRegisters; i++) {
8323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      XMMRegister reg = XMMRegister::from_code(i);
8333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      movsd(Operand(rsp, i * kDoubleSize), reg);
8343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
8353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
8363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
8373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::PopCallerSaved(SaveFPRegsMode fp_mode,
8403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    Register exclusion1,
8413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    Register exclusion2,
8423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    Register exclusion3) {
8433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (fp_mode == kSaveFPRegs) {
8443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CpuFeatures::Scope scope(SSE2);
8453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int i = 0; i < XMMRegister::kNumRegisters; i++) {
8463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      XMMRegister reg = XMMRegister::from_code(i);
8473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      movsd(reg, Operand(rsp, i * kDoubleSize));
8483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
8493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    addq(rsp, Immediate(kDoubleSize * XMMRegister::kNumRegisters));
8503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
8513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = kNumberOfSavedRegs - 1; i >= 0; i--) {
8523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register reg = saved_regs[i];
8533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!reg.is(exclusion1) && !reg.is(exclusion2) && !reg.is(exclusion3)) {
8543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      pop(reg);
8553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
8563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
8573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
8583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Set(Register dst, int64_t x) {
861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (x == 0) {
8628defd9ff6930b4e24729971a61cf7469daf119beSteve Block    xorl(dst, dst);
863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (is_uint32(x)) {
864d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    movl(dst, Immediate(static_cast<uint32_t>(x)));
8658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } else if (is_int32(x)) {
8668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    movq(dst, Immediate(static_cast<int32_t>(x)));
867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(dst, x, RelocInfo::NONE);
869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Set(const Operand& dst, int64_t x) {
8739dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  if (is_int32(x)) {
874d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    movq(dst, Immediate(static_cast<int32_t>(x)));
875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
8768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Set(kScratchRegister, x);
877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(dst, kScratchRegister);
878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------
882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Smi tagging, untagging and tag detection.
883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8848defd9ff6930b4e24729971a61cf7469daf119beSteve BlockRegister MacroAssembler::GetSmiConstant(Smi* source) {
8858defd9ff6930b4e24729971a61cf7469daf119beSteve Block  int value = source->value();
8868defd9ff6930b4e24729971a61cf7469daf119beSteve Block  if (value == 0) {
8878defd9ff6930b4e24729971a61cf7469daf119beSteve Block    xorl(kScratchRegister, kScratchRegister);
8888defd9ff6930b4e24729971a61cf7469daf119beSteve Block    return kScratchRegister;
8898defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
8908defd9ff6930b4e24729971a61cf7469daf119beSteve Block  if (value == 1) {
8918defd9ff6930b4e24729971a61cf7469daf119beSteve Block    return kSmiConstantRegister;
8928defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
8938defd9ff6930b4e24729971a61cf7469daf119beSteve Block  LoadSmiConstant(kScratchRegister, source);
8948defd9ff6930b4e24729971a61cf7469daf119beSteve Block  return kScratchRegister;
8958defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
8968defd9ff6930b4e24729971a61cf7469daf119beSteve Block
8978defd9ff6930b4e24729971a61cf7469daf119beSteve Blockvoid MacroAssembler::LoadSmiConstant(Register dst, Smi* source) {
89844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
8998defd9ff6930b4e24729971a61cf7469daf119beSteve Block    movq(dst,
9008defd9ff6930b4e24729971a61cf7469daf119beSteve Block         reinterpret_cast<uint64_t>(Smi::FromInt(kSmiConstantRegisterValue)),
9018defd9ff6930b4e24729971a61cf7469daf119beSteve Block         RelocInfo::NONE);
9028defd9ff6930b4e24729971a61cf7469daf119beSteve Block    cmpq(dst, kSmiConstantRegister);
9038defd9ff6930b4e24729971a61cf7469daf119beSteve Block    if (allow_stub_calls()) {
9048defd9ff6930b4e24729971a61cf7469daf119beSteve Block      Assert(equal, "Uninitialized kSmiConstantRegister");
9058defd9ff6930b4e24729971a61cf7469daf119beSteve Block    } else {
906257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Label ok;
907257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      j(equal, &ok, Label::kNear);
9088defd9ff6930b4e24729971a61cf7469daf119beSteve Block      int3();
9098defd9ff6930b4e24729971a61cf7469daf119beSteve Block      bind(&ok);
9108defd9ff6930b4e24729971a61cf7469daf119beSteve Block    }
9118defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
91244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int value = source->value();
91344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (value == 0) {
9148defd9ff6930b4e24729971a61cf7469daf119beSteve Block    xorl(dst, dst);
9158defd9ff6930b4e24729971a61cf7469daf119beSteve Block    return;
9168defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
9178defd9ff6930b4e24729971a61cf7469daf119beSteve Block  bool negative = value < 0;
9188defd9ff6930b4e24729971a61cf7469daf119beSteve Block  unsigned int uvalue = negative ? -value : value;
9198defd9ff6930b4e24729971a61cf7469daf119beSteve Block
9208defd9ff6930b4e24729971a61cf7469daf119beSteve Block  switch (uvalue) {
9218defd9ff6930b4e24729971a61cf7469daf119beSteve Block    case 9:
9228defd9ff6930b4e24729971a61cf7469daf119beSteve Block      lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_8, 0));
9238defd9ff6930b4e24729971a61cf7469daf119beSteve Block      break;
9248defd9ff6930b4e24729971a61cf7469daf119beSteve Block    case 8:
9258defd9ff6930b4e24729971a61cf7469daf119beSteve Block      xorl(dst, dst);
9268defd9ff6930b4e24729971a61cf7469daf119beSteve Block      lea(dst, Operand(dst, kSmiConstantRegister, times_8, 0));
9278defd9ff6930b4e24729971a61cf7469daf119beSteve Block      break;
9288defd9ff6930b4e24729971a61cf7469daf119beSteve Block    case 4:
9298defd9ff6930b4e24729971a61cf7469daf119beSteve Block      xorl(dst, dst);
9308defd9ff6930b4e24729971a61cf7469daf119beSteve Block      lea(dst, Operand(dst, kSmiConstantRegister, times_4, 0));
9318defd9ff6930b4e24729971a61cf7469daf119beSteve Block      break;
9328defd9ff6930b4e24729971a61cf7469daf119beSteve Block    case 5:
9338defd9ff6930b4e24729971a61cf7469daf119beSteve Block      lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_4, 0));
9348defd9ff6930b4e24729971a61cf7469daf119beSteve Block      break;
9358defd9ff6930b4e24729971a61cf7469daf119beSteve Block    case 3:
9368defd9ff6930b4e24729971a61cf7469daf119beSteve Block      lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_2, 0));
9378defd9ff6930b4e24729971a61cf7469daf119beSteve Block      break;
9388defd9ff6930b4e24729971a61cf7469daf119beSteve Block    case 2:
9398defd9ff6930b4e24729971a61cf7469daf119beSteve Block      lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_1, 0));
9408defd9ff6930b4e24729971a61cf7469daf119beSteve Block      break;
9418defd9ff6930b4e24729971a61cf7469daf119beSteve Block    case 1:
9428defd9ff6930b4e24729971a61cf7469daf119beSteve Block      movq(dst, kSmiConstantRegister);
9438defd9ff6930b4e24729971a61cf7469daf119beSteve Block      break;
9448defd9ff6930b4e24729971a61cf7469daf119beSteve Block    case 0:
9458defd9ff6930b4e24729971a61cf7469daf119beSteve Block      UNREACHABLE();
9468defd9ff6930b4e24729971a61cf7469daf119beSteve Block      return;
9478defd9ff6930b4e24729971a61cf7469daf119beSteve Block    default:
9488defd9ff6930b4e24729971a61cf7469daf119beSteve Block      movq(dst, reinterpret_cast<uint64_t>(source), RelocInfo::NONE);
9498defd9ff6930b4e24729971a61cf7469daf119beSteve Block      return;
9508defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
9518defd9ff6930b4e24729971a61cf7469daf119beSteve Block  if (negative) {
9528defd9ff6930b4e24729971a61cf7469daf119beSteve Block    neg(dst);
9538defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
9548defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
9558defd9ff6930b4e24729971a61cf7469daf119beSteve Block
956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9570d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::Integer32ToSmi(Register dst, Register src) {
95869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!dst.is(src)) {
960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movl(dst, src);
961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
9623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  shl(dst, Immediate(kSmiShift));
963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9669dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::Integer32ToSmiField(const Operand& dst, Register src) {
96744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
9689dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    testb(dst, Immediate(0x01));
969257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label ok;
970257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(zero, &ok, Label::kNear);
9719dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    if (allow_stub_calls()) {
9729dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      Abort("Integer32ToSmiField writing to non-smi location");
9739dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    } else {
9749dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      int3();
9759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    }
9769dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    bind(&ok);
9779dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
9789dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  ASSERT(kSmiShift % kBitsPerByte == 0);
9799dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  movl(Operand(dst, kSmiShift / kBitsPerByte), src);
9809dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
9819dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
9829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
9833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::Integer64PlusConstantToSmi(Register dst,
9843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                Register src,
9853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                int constant) {
9863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (dst.is(src)) {
98744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    addl(dst, Immediate(constant));
9883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
98944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    leal(dst, Operand(src, constant));
9903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
9913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  shl(dst, Immediate(kSmiShift));
992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiToInteger32(Register dst, Register src) {
99669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!dst.is(src)) {
9983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src);
999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
10003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  shr(dst, Immediate(kSmiShift));
1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid MacroAssembler::SmiToInteger32(Register dst, const Operand& src) {
10057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  movl(dst, Operand(src, kSmiShift / kBitsPerByte));
10067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
10077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
10087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiToInteger64(Register dst, Register src) {
101069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
10113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src)) {
10123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src);
1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
10143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  sar(dst, Immediate(kSmiShift));
1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10189dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::SmiToInteger64(Register dst, const Operand& src) {
10199dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  movsxlq(dst, Operand(src, kSmiShift / kBitsPerByte));
10209dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
10219dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
10229dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
10233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiTest(Register src) {
10243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  testq(src, src);
1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
102844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::SmiCompare(Register smi1, Register smi2) {
102944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
103044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    AbortIfNotSmi(smi1);
103144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    AbortIfNotSmi(smi2);
103244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
103344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  cmpq(smi1, smi2);
1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(Register dst, Smi* src) {
103844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
103944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    AbortIfNotSmi(dst);
104044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
104144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Cmp(dst, src);
104244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
104344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
104444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
104544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::Cmp(Register dst, Smi* src) {
10463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!dst.is(kScratchRegister));
10473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (src->value() == 0) {
10483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    testq(dst, dst);
10493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
1050756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Register constant_reg = GetSmiConstant(src);
1051756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    cmpq(dst, constant_reg);
1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1056f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid MacroAssembler::SmiCompare(Register dst, const Operand& src) {
105744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
105844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    AbortIfNotSmi(dst);
105944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    AbortIfNotSmi(src);
106044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
10616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  cmpq(dst, src);
10626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
10636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(const Operand& dst, Register src) {
106644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
106744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    AbortIfNotSmi(dst);
106844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    AbortIfNotSmi(src);
106944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
10703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  cmpq(dst, src);
1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(const Operand& dst, Smi* src) {
107544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
107644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    AbortIfNotSmi(dst);
107744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
10787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  cmpl(Operand(dst, kSmiShift / kBitsPerByte), Immediate(src->value()));
1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
108244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::Cmp(const Operand& dst, Smi* src) {
108344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // The Operand cannot use the smi register.
108444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register smi_reg = GetSmiConstant(src);
108544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!dst.AddressUsesRegister(smi_reg));
108644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  cmpq(dst, smi_reg);
108744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
108844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
108944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
10909dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::SmiCompareInteger32(const Operand& dst, Register src) {
10919dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  cmpl(Operand(dst, kSmiShift / kBitsPerByte), src);
10929dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
10939dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
10949dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
10953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::PositiveSmiTimesPowerOfTwoToInteger64(Register dst,
10963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                           Register src,
10973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                           int power) {
10983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(power >= 0);
10993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(power < 64);
11003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (power == 0) {
11013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    SmiToInteger64(dst, src);
11023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    return;
11033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
11043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src)) {
11053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src);
11063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
11073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (power < kSmiShift) {
11083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    sar(dst, Immediate(kSmiShift - power));
11093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (power > kSmiShift) {
11103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    shl(dst, Immediate(power - kSmiShift));
11113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid MacroAssembler::PositiveSmiDivPowerOfTwoToInteger32(Register dst,
11167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                                         Register src,
11177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                                         int power) {
11187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT((0 <= power) && (power < 32));
11197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (dst.is(src)) {
11207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    shr(dst, Immediate(power + kSmiShift));
11217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  } else {
11227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    UNIMPLEMENTED();  // Not used.
11237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
11247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
11257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiOrIfSmis(Register dst, Register src1, Register src2,
1128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Label* on_not_smis,
1129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Label::Distance near_jump) {
1130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (dst.is(src1) || dst.is(src2)) {
1131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(!src1.is(kScratchRegister));
1132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(!src2.is(kScratchRegister));
1133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(kScratchRegister, src1);
1134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    or_(kScratchRegister, src2);
1135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    JumpIfNotSmi(kScratchRegister, on_not_smis, near_jump);
1136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(dst, kScratchRegister);
1137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(dst, src1);
1139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    or_(dst, src2);
1140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    JumpIfNotSmi(dst, on_not_smis, near_jump);
1141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
11453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockCondition MacroAssembler::CheckSmi(Register src) {
114669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  testb(src, Immediate(kSmiTagMask));
11483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  return zero;
1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11521e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockCondition MacroAssembler::CheckSmi(const Operand& src) {
115369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
11541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  testb(src, Immediate(kSmiTagMask));
11551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return zero;
11561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
11571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
11581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1159f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochCondition MacroAssembler::CheckNonNegativeSmi(Register src) {
116069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
1161e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Test that both bits of the mask 0x8000000000000001 are zero.
11623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  movq(kScratchRegister, src);
11633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  rol(kScratchRegister, Immediate(1));
11648defd9ff6930b4e24729971a61cf7469daf119beSteve Block  testb(kScratchRegister, Immediate(3));
1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return zero;
1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCondition MacroAssembler::CheckBothSmi(Register first, Register second) {
1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (first.is(second)) {
1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return CheckSmi(first);
1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
117369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0 && kHeapObjectTag == 1 && kHeapObjectTagMask == 3);
11748defd9ff6930b4e24729971a61cf7469daf119beSteve Block  leal(kScratchRegister, Operand(first, second, times_1, 0));
11758defd9ff6930b4e24729971a61cf7469daf119beSteve Block  testb(kScratchRegister, Immediate(0x03));
11763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  return zero;
1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1180f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochCondition MacroAssembler::CheckBothNonNegativeSmi(Register first,
1181f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch                                                  Register second) {
1182d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (first.is(second)) {
1183f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    return CheckNonNegativeSmi(first);
1184d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
11858defd9ff6930b4e24729971a61cf7469daf119beSteve Block  movq(kScratchRegister, first);
11868defd9ff6930b4e24729971a61cf7469daf119beSteve Block  or_(kScratchRegister, second);
1187d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  rol(kScratchRegister, Immediate(1));
1188f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  testl(kScratchRegister, Immediate(3));
1189d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  return zero;
1190d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1191d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1192d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1193bb769b257e753aafcbd96767abb2abc645eaa20cBen MurdochCondition MacroAssembler::CheckEitherSmi(Register first,
1194bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                         Register second,
1195bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                         Register scratch) {
1196e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (first.is(second)) {
1197e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    return CheckSmi(first);
1198e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
1199bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (scratch.is(second)) {
1200bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    andl(scratch, first);
1201bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  } else {
1202bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    if (!scratch.is(first)) {
1203bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      movl(scratch, first);
1204bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    }
1205bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    andl(scratch, second);
1206bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
1207bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  testb(scratch, Immediate(kSmiTagMask));
1208e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  return zero;
1209e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1210e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1211e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCondition MacroAssembler::CheckIsMinSmi(Register src) {
12138defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ASSERT(!src.is(kScratchRegister));
12148defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // If we overflow by subtracting one, it's the minimal smi value.
12158defd9ff6930b4e24729971a61cf7469daf119beSteve Block  cmpq(src, kSmiConstantRegister);
12168defd9ff6930b4e24729971a61cf7469daf119beSteve Block  return overflow;
1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockCondition MacroAssembler::CheckInteger32ValidSmiValue(Register src) {
12213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // A 32-bit integer value can always be converted to a smi.
12223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  return always;
1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockCondition MacroAssembler::CheckUInteger32ValidSmiValue(Register src) {
12273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // An unsigned 32-bit integer value is valid as long as the high bit
12283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // is not set.
12298defd9ff6930b4e24729971a61cf7469daf119beSteve Block  testl(src, src);
12308defd9ff6930b4e24729971a61cf7469daf119beSteve Block  return positive;
1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::CheckSmiToIndicator(Register dst, Register src) {
12351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (dst.is(src)) {
12361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    andl(dst, Immediate(kSmiTagMask));
12371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
12381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    movl(dst, Immediate(kSmiTagMask));
12391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    andl(dst, src);
12401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
12411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
12421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
12431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
12441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::CheckSmiToIndicator(Register dst, const Operand& src) {
12451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (!(src.AddressUsesRegister(dst))) {
12461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    movl(dst, Immediate(kSmiTagMask));
12471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    andl(dst, src);
12481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
12491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    movl(dst, src);
12501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    andl(dst, Immediate(kSmiTagMask));
12511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
12521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
12531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
12541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfNotValidSmiValue(Register src,
1256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                            Label* on_invalid,
1257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                            Label::Distance near_jump) {
1258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition is_valid = CheckInteger32ValidSmiValue(src);
1259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(NegateCondition(is_valid), on_invalid, near_jump);
1260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfUIntNotValidSmiValue(Register src,
1264257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                Label* on_invalid,
1265257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                Label::Distance near_jump) {
1266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition is_valid = CheckUInteger32ValidSmiValue(src);
1267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(NegateCondition(is_valid), on_invalid, near_jump);
1268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfSmi(Register src,
1272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               Label* on_smi,
1273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               Label::Distance near_jump) {
1274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition smi = CheckSmi(src);
1275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(smi, on_smi, near_jump);
1276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfNotSmi(Register src,
1280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                  Label* on_not_smi,
1281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                  Label::Distance near_jump) {
1282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition smi = CheckSmi(src);
1283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(NegateCondition(smi), on_not_smi, near_jump);
1284257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1285257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1286257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpUnlessNonNegativeSmi(
1288257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register src, Label* on_not_smi_or_negative,
1289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label::Distance near_jump) {
1290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition non_negative_smi = CheckNonNegativeSmi(src);
1291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(NegateCondition(non_negative_smi), on_not_smi_or_negative, near_jump);
1292257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1293257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfSmiEqualsConstant(Register src,
1296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Smi* constant,
1297257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Label* on_equals,
1298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Label::Distance near_jump) {
1299257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  SmiCompare(src, constant);
1300257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(equal, on_equals, near_jump);
1301257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1302257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1303257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1304257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfNotBothSmi(Register src1,
1305257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                      Register src2,
1306257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                      Label* on_not_both_smi,
1307257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                      Label::Distance near_jump) {
1308257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition both_smi = CheckBothSmi(src1, src2);
1309257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(NegateCondition(both_smi), on_not_both_smi, near_jump);
1310257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1311257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpUnlessBothNonNegativeSmi(Register src1,
1314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                  Register src2,
1315257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                  Label* on_not_both_smi,
1316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                  Label::Distance near_jump) {
1317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition both_smi = CheckBothNonNegativeSmi(src1, src2);
1318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(NegateCondition(both_smi), on_not_both_smi, near_jump);
1319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1322257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiTryAddConstant(Register dst,
1323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                       Register src,
1324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                       Smi* constant,
1325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                       Label* on_not_smi_result,
1326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                       Label::Distance near_jump) {
1327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Does not assume that src is a smi.
1328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT_EQ(static_cast<int>(1), static_cast<int>(kSmiTagMask));
132969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
1330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!dst.is(kScratchRegister));
1331257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src.is(kScratchRegister));
1332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  JumpIfNotSmi(src, on_not_smi_result, near_jump);
1334257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register tmp = (dst.is(src) ? kScratchRegister : dst);
1335257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  LoadSmiConstant(tmp, constant);
1336257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  addq(tmp, src);
1337257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(overflow, on_not_smi_result, near_jump);
1338257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (dst.is(src)) {
1339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(dst, tmp);
1340257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1342257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1343257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
13443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiAddConstant(Register dst, Register src, Smi* constant) {
13453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (constant->value() == 0) {
13463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (!dst.is(src)) {
13473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      movq(dst, src);
13483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
13498defd9ff6930b4e24729971a61cf7469daf119beSteve Block    return;
13503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (dst.is(src)) {
13513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    ASSERT(!dst.is(kScratchRegister));
13528defd9ff6930b4e24729971a61cf7469daf119beSteve Block    switch (constant->value()) {
13538defd9ff6930b4e24729971a61cf7469daf119beSteve Block      case 1:
13548defd9ff6930b4e24729971a61cf7469daf119beSteve Block        addq(dst, kSmiConstantRegister);
13558defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
13568defd9ff6930b4e24729971a61cf7469daf119beSteve Block      case 2:
13578defd9ff6930b4e24729971a61cf7469daf119beSteve Block        lea(dst, Operand(src, kSmiConstantRegister, times_2, 0));
13588defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
13598defd9ff6930b4e24729971a61cf7469daf119beSteve Block      case 4:
13608defd9ff6930b4e24729971a61cf7469daf119beSteve Block        lea(dst, Operand(src, kSmiConstantRegister, times_4, 0));
13618defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
13628defd9ff6930b4e24729971a61cf7469daf119beSteve Block      case 8:
13638defd9ff6930b4e24729971a61cf7469daf119beSteve Block        lea(dst, Operand(src, kSmiConstantRegister, times_8, 0));
13648defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
13658defd9ff6930b4e24729971a61cf7469daf119beSteve Block      default:
13668defd9ff6930b4e24729971a61cf7469daf119beSteve Block        Register constant_reg = GetSmiConstant(constant);
13678defd9ff6930b4e24729971a61cf7469daf119beSteve Block        addq(dst, constant_reg);
13688defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
13698defd9ff6930b4e24729971a61cf7469daf119beSteve Block    }
1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
13718defd9ff6930b4e24729971a61cf7469daf119beSteve Block    switch (constant->value()) {
13728defd9ff6930b4e24729971a61cf7469daf119beSteve Block      case 1:
13738defd9ff6930b4e24729971a61cf7469daf119beSteve Block        lea(dst, Operand(src, kSmiConstantRegister, times_1, 0));
13748defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
13758defd9ff6930b4e24729971a61cf7469daf119beSteve Block      case 2:
13768defd9ff6930b4e24729971a61cf7469daf119beSteve Block        lea(dst, Operand(src, kSmiConstantRegister, times_2, 0));
13778defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
13788defd9ff6930b4e24729971a61cf7469daf119beSteve Block      case 4:
13798defd9ff6930b4e24729971a61cf7469daf119beSteve Block        lea(dst, Operand(src, kSmiConstantRegister, times_4, 0));
13808defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
13818defd9ff6930b4e24729971a61cf7469daf119beSteve Block      case 8:
13828defd9ff6930b4e24729971a61cf7469daf119beSteve Block        lea(dst, Operand(src, kSmiConstantRegister, times_8, 0));
13838defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
13848defd9ff6930b4e24729971a61cf7469daf119beSteve Block      default:
13858defd9ff6930b4e24729971a61cf7469daf119beSteve Block        LoadSmiConstant(dst, constant);
13868defd9ff6930b4e24729971a61cf7469daf119beSteve Block        addq(dst, src);
13878defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
13888defd9ff6930b4e24729971a61cf7469daf119beSteve Block    }
1389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1393f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid MacroAssembler::SmiAddConstant(const Operand& dst, Smi* constant) {
1394f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (constant->value() != 0) {
13957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    addl(Operand(dst, kSmiShift / kBitsPerByte), Immediate(constant->value()));
1396f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1397f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1398f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1399f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiAddConstant(Register dst,
1401257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Register src,
1402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Smi* constant,
1403257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Label* on_not_smi_result,
1404257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Label::Distance near_jump) {
1405257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (constant->value() == 0) {
1406257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (!dst.is(src)) {
1407257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      movq(dst, src);
1408257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else if (dst.is(src)) {
1410257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(!dst.is(kScratchRegister));
1411257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1412257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    LoadSmiConstant(kScratchRegister, constant);
1413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    addq(kScratchRegister, src);
1414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(overflow, on_not_smi_result, near_jump);
1415257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(dst, kScratchRegister);
1416257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1417257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    LoadSmiConstant(dst, constant);
1418257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    addq(dst, src);
1419257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(overflow, on_not_smi_result, near_jump);
1420257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1421257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1422257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1423257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
14243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiSubConstant(Register dst, Register src, Smi* constant) {
14253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (constant->value() == 0) {
1426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!dst.is(src)) {
14273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      movq(dst, src);
1428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
14293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (dst.is(src)) {
14303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    ASSERT(!dst.is(kScratchRegister));
14318defd9ff6930b4e24729971a61cf7469daf119beSteve Block    Register constant_reg = GetSmiConstant(constant);
14328defd9ff6930b4e24729971a61cf7469daf119beSteve Block    subq(dst, constant_reg);
14333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
14343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (constant->value() == Smi::kMinValue) {
14358defd9ff6930b4e24729971a61cf7469daf119beSteve Block      LoadSmiConstant(dst, constant);
14369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // Adding and subtracting the min-value gives the same result, it only
14379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // differs on the overflow bit, which we don't check here.
14389dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      addq(dst, src);
1439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
14409dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // Subtract by adding the negation.
14418defd9ff6930b4e24729971a61cf7469daf119beSteve Block      LoadSmiConstant(dst, Smi::FromInt(-constant->value()));
14423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      addq(dst, src);
1443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiSubConstant(Register dst,
1449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Register src,
1450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Smi* constant,
1451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Label* on_not_smi_result,
1452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Label::Distance near_jump) {
1453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (constant->value() == 0) {
1454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (!dst.is(src)) {
1455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      movq(dst, src);
1456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else if (dst.is(src)) {
1458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(!dst.is(kScratchRegister));
1459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (constant->value() == Smi::kMinValue) {
1460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Subtracting min-value from any non-negative value will overflow.
1461257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // We test the non-negativeness before doing the subtraction.
1462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      testq(src, src);
1463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      j(not_sign, on_not_smi_result, near_jump);
1464257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      LoadSmiConstant(kScratchRegister, constant);
1465257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      subq(dst, kScratchRegister);
1466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
1467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Subtract by adding the negation.
1468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      LoadSmiConstant(kScratchRegister, Smi::FromInt(-constant->value()));
1469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      addq(kScratchRegister, dst);
1470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      j(overflow, on_not_smi_result, near_jump);
1471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      movq(dst, kScratchRegister);
1472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (constant->value() == Smi::kMinValue) {
1475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Subtracting min-value from any non-negative value will overflow.
1476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // We test the non-negativeness before doing the subtraction.
1477257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      testq(src, src);
1478257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      j(not_sign, on_not_smi_result, near_jump);
1479257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      LoadSmiConstant(dst, constant);
1480257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Adding and subtracting the min-value gives the same result, it only
1481257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // differs on the overflow bit, which we don't check here.
1482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      addq(dst, src);
1483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
1484257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Subtract by adding the negation.
1485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      LoadSmiConstant(dst, Smi::FromInt(-(constant->value())));
1486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      addq(dst, src);
1487257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      j(overflow, on_not_smi_result, near_jump);
1488257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1489257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1490257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1491257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1492257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1493257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiNeg(Register dst,
1494257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src,
1495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label* on_smi_result,
1496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label::Distance near_jump) {
1497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (dst.is(src)) {
1498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(!dst.is(kScratchRegister));
1499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(kScratchRegister, src);
1500257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    neg(dst);  // Low 32 bits are retained as zero by negation.
1501257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Test if result is zero or Smi::kMinValue.
1502257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    cmpq(dst, kScratchRegister);
1503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(not_equal, on_smi_result, near_jump);
1504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(src, kScratchRegister);
1505257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(dst, src);
1507257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    neg(dst);
1508257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    cmpq(dst, src);
1509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // If the result is zero or Smi::kMinValue, negation failed to create a smi.
1510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(not_equal, on_smi_result, near_jump);
1511257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1512257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1513257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiAdd(Register dst,
1516257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src1,
1517257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src2,
1518257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label* on_not_smi_result,
1519257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label::Distance near_jump) {
1520257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT_NOT_NULL(on_not_smi_result);
1521257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!dst.is(src2));
1522257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (dst.is(src1)) {
1523257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(kScratchRegister, src1);
1524257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    addq(kScratchRegister, src2);
1525257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(overflow, on_not_smi_result, near_jump);
1526257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(dst, kScratchRegister);
1527257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1528257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(dst, src1);
1529257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    addq(dst, src2);
1530257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(overflow, on_not_smi_result, near_jump);
1531257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1532257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1533257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1535257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiAdd(Register dst,
1536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src1,
1537257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            const Operand& src2,
1538257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label* on_not_smi_result,
1539257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label::Distance near_jump) {
1540257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT_NOT_NULL(on_not_smi_result);
1541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (dst.is(src1)) {
1542257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(kScratchRegister, src1);
1543257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    addq(kScratchRegister, src2);
1544257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(overflow, on_not_smi_result, near_jump);
1545257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(dst, kScratchRegister);
1546257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1547257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(!src2.AddressUsesRegister(dst));
1548257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(dst, src1);
1549257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    addq(dst, src2);
1550257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(overflow, on_not_smi_result, near_jump);
1551257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1552257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1554257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
15550d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::SmiAdd(Register dst,
15560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                            Register src1,
15570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                            Register src2) {
15580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // No overflow checking. Use only when it's known that
15590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // overflowing is impossible.
156044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!dst.is(src1)) {
1561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (emit_debug_code()) {
1562257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      movq(kScratchRegister, src1);
1563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      addq(kScratchRegister, src2);
1564257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Check(no_overflow, "Smi addition overflow");
1565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    lea(dst, Operand(src1, src2, times_1, 0));
1567257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1568257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    addq(dst, src2);
1569257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Assert(no_overflow, "Smi addition overflow");
1570257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1571257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1572257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1573257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1574257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiSub(Register dst,
1575257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src1,
1576257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src2,
1577257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label* on_not_smi_result,
1578257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label::Distance near_jump) {
1579257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT_NOT_NULL(on_not_smi_result);
1580257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!dst.is(src2));
1581257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (dst.is(src1)) {
1582257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    cmpq(dst, src2);
1583257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(overflow, on_not_smi_result, near_jump);
1584257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    subq(dst, src2);
1585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1586053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block    movq(dst, src1);
1587257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    subq(dst, src2);
1588257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(overflow, on_not_smi_result, near_jump);
1589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15930d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::SmiSub(Register dst, Register src1, Register src2) {
15940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // No overflow checking. Use only when it's known that
15950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // overflowing is impossible (e.g., subtracting two positive smis).
15960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(!dst.is(src2));
159744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!dst.is(src1)) {
15980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    movq(dst, src1);
15993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
160044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  subq(dst, src2);
16010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Assert(no_overflow, "Smi subtraction overflow");
1602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16050d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::SmiSub(Register dst,
1606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register src1,
1607257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            const Operand& src2,
1608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label* on_not_smi_result,
1609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label::Distance near_jump) {
1610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT_NOT_NULL(on_not_smi_result);
1611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (dst.is(src1)) {
1612257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(kScratchRegister, src2);
1613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    cmpq(src1, kScratchRegister);
1614257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(overflow, on_not_smi_result, near_jump);
1615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    subq(src1, kScratchRegister);
1616257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1617257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(dst, src1);
1618257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    subq(dst, src2);
1619257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(overflow, on_not_smi_result, near_jump);
1620257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1621257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1622257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1623257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiSub(Register dst,
1625257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src1,
16260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                            const Operand& src2) {
16270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // No overflow checking. Use only when it's known that
16280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // overflowing is impossible (e.g., subtracting two positive smis).
162944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!dst.is(src1)) {
16300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    movq(dst, src1);
1631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
163244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  subq(dst, src2);
16330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Assert(no_overflow, "Smi subtraction overflow");
1634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1637257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiMul(Register dst,
1638257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src1,
1639257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src2,
1640257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label* on_not_smi_result,
1641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label::Distance near_jump) {
1642257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!dst.is(src2));
1643257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!dst.is(kScratchRegister));
1644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src1.is(kScratchRegister));
1645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src2.is(kScratchRegister));
1646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (dst.is(src1)) {
1648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label failure, zero_correct_result;
1649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(kScratchRegister, src1);  // Create backup for later testing.
1650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    SmiToInteger64(dst, src1);
1651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    imul(dst, src2);
1652257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(overflow, &failure, Label::kNear);
1653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Check for negative zero result.  If product is zero, and one
1655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // argument is negative, go to slow case.
1656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label correct_result;
1657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    testq(dst, dst);
1658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(not_zero, &correct_result, Label::kNear);
1659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(dst, kScratchRegister);
1661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    xor_(dst, src2);
1662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Result was positive zero.
1663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(positive, &zero_correct_result, Label::kNear);
1664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    bind(&failure);  // Reused failure exit, restores src1.
1666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(src1, kScratchRegister);
1667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    jmp(on_not_smi_result, near_jump);
1668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    bind(&zero_correct_result);
1670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Set(dst, 0);
1671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    bind(&correct_result);
1673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    SmiToInteger64(dst, src1);
1675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    imul(dst, src2);
1676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(overflow, on_not_smi_result, near_jump);
1677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Check for negative zero result.  If product is zero, and one
1678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // argument is negative, go to slow case.
1679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label correct_result;
1680257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    testq(dst, dst);
1681257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(not_zero, &correct_result, Label::kNear);
1682257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // One of src1 and src2 is zero, the check whether the other is
1683257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // negative.
1684257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(kScratchRegister, src1);
1685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    xor_(kScratchRegister, src2);
1686257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(negative, on_not_smi_result, near_jump);
1687257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    bind(&correct_result);
1688257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1689257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1690257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1691257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiDiv(Register dst,
1693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src1,
1694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src2,
1695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label* on_not_smi_result,
1696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label::Distance near_jump) {
1697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src1.is(kScratchRegister));
1698257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src2.is(kScratchRegister));
1699257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!dst.is(kScratchRegister));
1700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src2.is(rax));
1701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src2.is(rdx));
1702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src1.is(rdx));
1703257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1704257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check for 0 divisor (result is +/-Infinity).
1705257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  testq(src2, src2);
1706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(zero, on_not_smi_result, near_jump);
1707257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1708257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (src1.is(rax)) {
1709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(kScratchRegister, src1);
1710257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1711257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  SmiToInteger32(rax, src1);
1712257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // We need to rule out dividing Smi::kMinValue by -1, since that would
1713257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // overflow in idiv and raise an exception.
1714257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // We combine this with negative zero test (negative zero only happens
1715257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // when dividing zero by a negative number).
1716257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1717257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // We overshoot a little and go to slow case if we divide min-value
1718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // by any negative value, not just -1.
1719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label safe_div;
1720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  testl(rax, Immediate(0x7fffffff));
1721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_zero, &safe_div, Label::kNear);
1722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  testq(src2, src2);
1723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (src1.is(rax)) {
1724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(positive, &safe_div, Label::kNear);
1725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(src1, kScratchRegister);
1726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    jmp(on_not_smi_result, near_jump);
1727257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(negative, on_not_smi_result, near_jump);
1729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&safe_div);
1731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  SmiToInteger32(src2, src2);
1733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Sign extend src1 into edx:eax.
1734257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  cdq();
1735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  idivl(src2);
1736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Integer32ToSmi(src2, src2);
1737257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the remainder is zero.
1738257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  testl(rdx, rdx);
1739257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (src1.is(rax)) {
1740257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label smi_result;
1741257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(zero, &smi_result, Label::kNear);
1742257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(src1, kScratchRegister);
1743257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    jmp(on_not_smi_result, near_jump);
1744257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    bind(&smi_result);
1745257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1746257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(not_zero, on_not_smi_result, near_jump);
1747257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!dst.is(src1) && src1.is(rax)) {
1749257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(src1, kScratchRegister);
1750257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Integer32ToSmi(dst, rax);
1752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1754257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1755257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiMod(Register dst,
1756257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src1,
1757257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src2,
1758257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label* on_not_smi_result,
1759257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label::Distance near_jump) {
1760257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!dst.is(kScratchRegister));
1761257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src1.is(kScratchRegister));
1762257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src2.is(kScratchRegister));
1763257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src2.is(rax));
1764257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src2.is(rdx));
1765257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src1.is(rdx));
1766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src1.is(src2));
1767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1768257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  testq(src2, src2);
1769257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(zero, on_not_smi_result, near_jump);
1770257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (src1.is(rax)) {
1772257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(kScratchRegister, src1);
1773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  SmiToInteger32(rax, src1);
1775257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  SmiToInteger32(src2, src2);
1776257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1777257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Test for the edge case of dividing Smi::kMinValue by -1 (will overflow).
1778257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label safe_div;
1779257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  cmpl(rax, Immediate(Smi::kMinValue));
1780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_equal, &safe_div, Label::kNear);
1781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  cmpl(src2, Immediate(-1));
1782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_equal, &safe_div, Label::kNear);
1783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Retag inputs and go slow case.
1784257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Integer32ToSmi(src2, src2);
1785257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (src1.is(rax)) {
1786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(src1, kScratchRegister);
1787257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1788257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  jmp(on_not_smi_result, near_jump);
1789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&safe_div);
1790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Sign extend eax into edx:eax.
1792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  cdq();
1793257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  idivl(src2);
1794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Restore smi tags on inputs.
1795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Integer32ToSmi(src2, src2);
1796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (src1.is(rax)) {
1797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(src1, kScratchRegister);
1798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1799257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check for a negative zero result.  If the result is zero, and the
1800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // dividend is negative, go slow to return a floating point negative zero.
1801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label smi_result;
1802257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  testl(rdx, rdx);
1803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_zero, &smi_result, Label::kNear);
1804257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  testq(src1, src1);
1805257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(negative, on_not_smi_result, near_jump);
1806257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&smi_result);
1807257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Integer32ToSmi(dst, rdx);
1808257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1809257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1810257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiNot(Register dst, Register src) {
18123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!dst.is(kScratchRegister));
18133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!src.is(kScratchRegister));
18143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Set tag and padding bits before negating, so that they are zero afterwards.
18153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  movl(kScratchRegister, Immediate(~0));
1816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (dst.is(src)) {
18173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    xor_(dst, kScratchRegister);
1818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
18193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    lea(dst, Operand(src, kScratchRegister, times_1, 0));
1820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
18213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  not_(dst);
1822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiAnd(Register dst, Register src1, Register src2) {
18263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!dst.is(src2));
1827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!dst.is(src1)) {
18283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src1);
1829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  and_(dst, src2);
1831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
18343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiAndConstant(Register dst, Register src, Smi* constant) {
18353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (constant->value() == 0) {
18369fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    Set(dst, 0);
18373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (dst.is(src)) {
18383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    ASSERT(!dst.is(kScratchRegister));
18398defd9ff6930b4e24729971a61cf7469daf119beSteve Block    Register constant_reg = GetSmiConstant(constant);
18408defd9ff6930b4e24729971a61cf7469daf119beSteve Block    and_(dst, constant_reg);
18413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
18428defd9ff6930b4e24729971a61cf7469daf119beSteve Block    LoadSmiConstant(dst, constant);
18433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    and_(dst, src);
1844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiOr(Register dst, Register src1, Register src2) {
1849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!dst.is(src1)) {
18508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    ASSERT(!src1.is(src2));
18513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src1);
1852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  or_(dst, src2);
1854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
18573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiOrConstant(Register dst, Register src, Smi* constant) {
18583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (dst.is(src)) {
18593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    ASSERT(!dst.is(kScratchRegister));
18608defd9ff6930b4e24729971a61cf7469daf119beSteve Block    Register constant_reg = GetSmiConstant(constant);
18618defd9ff6930b4e24729971a61cf7469daf119beSteve Block    or_(dst, constant_reg);
18623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
18638defd9ff6930b4e24729971a61cf7469daf119beSteve Block    LoadSmiConstant(dst, constant);
18643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    or_(dst, src);
1865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
18683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiXor(Register dst, Register src1, Register src2) {
1870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!dst.is(src1)) {
18718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    ASSERT(!src1.is(src2));
18723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src1);
1873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  xor_(dst, src2);
1875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
18783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiXorConstant(Register dst, Register src, Smi* constant) {
18793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (dst.is(src)) {
18803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    ASSERT(!dst.is(kScratchRegister));
18818defd9ff6930b4e24729971a61cf7469daf119beSteve Block    Register constant_reg = GetSmiConstant(constant);
18828defd9ff6930b4e24729971a61cf7469daf119beSteve Block    xor_(dst, constant_reg);
18833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
18848defd9ff6930b4e24729971a61cf7469daf119beSteve Block    LoadSmiConstant(dst, constant);
18853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    xor_(dst, src);
1886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftArithmeticRightConstant(Register dst,
1891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                     Register src,
1892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                     int shift_value) {
18933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(is_uint5(shift_value));
1894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (shift_value > 0) {
1895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (dst.is(src)) {
18963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      sar(dst, Immediate(shift_value + kSmiShift));
18973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      shl(dst, Immediate(kSmiShift));
1898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
1899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNIMPLEMENTED();  // Not used.
1900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftLeftConstant(Register dst,
1906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                          Register src,
190725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen                                          int shift_value) {
19083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src)) {
19093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src);
19103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
19113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (shift_value > 0) {
19123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    shl(dst, Immediate(shift_value));
1913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiShiftLogicalRightConstant(
1918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register dst, Register src, int shift_value,
1919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label* on_not_smi_result, Label::Distance near_jump) {
1920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Logic right shift interprets its result as an *unsigned* number.
1921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (dst.is(src)) {
1922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    UNIMPLEMENTED();  // Not used.
1923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(dst, src);
1925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (shift_value == 0) {
1926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      testq(dst, dst);
1927257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      j(negative, on_not_smi_result, near_jump);
1928257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1929257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    shr(dst, Immediate(shift_value + kSmiShift));
1930257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    shl(dst, Immediate(kSmiShift));
1931257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1932257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1933257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1934257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftLeft(Register dst,
1936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  Register src1,
193725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen                                  Register src2) {
1938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(rcx));
19393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Untag shift amount.
19403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src1)) {
19413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src1);
1942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
19433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiToInteger32(rcx, src2);
19443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Shift amount specified by lower 5 bits, not six as the shl opcode.
19453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  and_(rcx, Immediate(0x1f));
1946d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  shl_cl(dst);
1947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1950257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiShiftLogicalRight(Register dst,
1951257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                          Register src1,
1952257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                          Register src2,
1953257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                          Label* on_not_smi_result,
1954257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                          Label::Distance near_jump) {
1955257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!dst.is(kScratchRegister));
1956257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src1.is(kScratchRegister));
1957257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src2.is(kScratchRegister));
1958257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!dst.is(rcx));
1959257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // dst and src1 can be the same, because the one case that bails out
1960257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // is a shift by 0, which leaves dst, and therefore src1, unchanged.
1961257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (src1.is(rcx) || src2.is(rcx)) {
1962257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(kScratchRegister, rcx);
1963257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1964257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!dst.is(src1)) {
1965257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(dst, src1);
1966257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1967257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  SmiToInteger32(rcx, src2);
1968257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  orl(rcx, Immediate(kSmiShift));
1969257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  shr_cl(dst);  // Shift is rcx modulo 0x1f + 32.
1970257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  shl(dst, Immediate(kSmiShift));
1971257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  testq(dst, dst);
1972257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (src1.is(rcx) || src2.is(rcx)) {
1973257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label positive_result;
1974257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(positive, &positive_result, Label::kNear);
1975257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (src1.is(rcx)) {
1976257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      movq(src1, kScratchRegister);
1977257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
1978257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      movq(src2, kScratchRegister);
1979257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1980257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    jmp(on_not_smi_result, near_jump);
1981257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    bind(&positive_result);
1982257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1983257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // src2 was zero and src1 negative.
1984257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(negative, on_not_smi_result, near_jump);
1985257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1986257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1987257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1988257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftArithmeticRight(Register dst,
1990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register src1,
1991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register src2) {
19923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!dst.is(kScratchRegister));
19933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!src1.is(kScratchRegister));
19943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!src2.is(kScratchRegister));
1995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(rcx));
19963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (src1.is(rcx)) {
19973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(kScratchRegister, src1);
19983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (src2.is(rcx)) {
19993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(kScratchRegister, src2);
20003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
20013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src1)) {
20023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src1);
20033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SmiToInteger32(rcx, src2);
20053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  orl(rcx, Immediate(kSmiShift));
2006d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  sar_cl(dst);  // Shift 32 + original rcx & 0x1f.
20073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  shl(dst, Immediate(kSmiShift));
20083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (src1.is(rcx)) {
20093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(src1, kScratchRegister);
20103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (src2.is(rcx)) {
20113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(src2, kScratchRegister);
20123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2016257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SelectNonSmi(Register dst,
2017257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                  Register src1,
2018257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                  Register src2,
2019257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                  Label* on_not_smis,
2020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                  Label::Distance near_jump) {
2021257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!dst.is(kScratchRegister));
2022257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src1.is(kScratchRegister));
2023257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src2.is(kScratchRegister));
2024257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!dst.is(src1));
2025257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!dst.is(src2));
2026257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Both operands must not be smis.
2027257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#ifdef DEBUG
2028257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (allow_stub_calls()) {  // Check contains a stub call.
2029257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Condition not_both_smis = NegateCondition(CheckBothSmi(src1, src2));
2030257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Check(not_both_smis, "Both registers were smis in SelectNonSmi.");
2031257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2032257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif
203369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
2034257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT_EQ(0, Smi::FromInt(0));
2035257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  movl(kScratchRegister, Immediate(kSmiTagMask));
2036257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  and_(kScratchRegister, src1);
2037257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  testl(kScratchRegister, src2);
2038257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If non-zero then both are smis.
2039257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_zero, on_not_smis, near_jump);
2040257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2041257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Exactly one operand is a smi.
2042257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT_EQ(1, static_cast<int>(kSmiTagMask));
2043257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // kScratchRegister still holds src1 & kSmiTag, which is either zero or one.
2044257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  subq(kScratchRegister, Immediate(1));
2045257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If src1 is a smi, then scratch register all 1s, else it is all 0s.
2046257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  movq(dst, src1);
2047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  xor_(dst, src2);
2048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  and_(dst, kScratchRegister);
2049257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If src1 is a smi, dst holds src1 ^ src2, else it is zero.
2050257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  xor_(dst, src1);
2051257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If src1 is a smi, dst is src2, else it is src1, i.e., the non-smi.
2052257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2053257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2054257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockSmiIndex MacroAssembler::SmiToIndex(Register dst,
20563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                    Register src,
20573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                    int shift) {
2058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint6(shift));
20593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // There is a possible optimization if shift is in the range 60-63, but that
20603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // will (and must) never happen.
20613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src)) {
20623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src);
20633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
20643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (shift < kSmiShift) {
20653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    sar(dst, Immediate(kSmiShift - shift));
20663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
20673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    shl(dst, Immediate(shift - kSmiShift));
20683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return SmiIndex(dst, times_1);
2070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockSmiIndex MacroAssembler::SmiToNegativeIndex(Register dst,
2073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            Register src,
2074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            int shift) {
2075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Register src holds a positive smi.
2076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint6(shift));
20773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src)) {
20783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src);
2079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  neg(dst);
20813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (shift < kSmiShift) {
20823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    sar(dst, Immediate(kSmiShift - shift));
20833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
20843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    shl(dst, Immediate(shift - kSmiShift));
20853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return SmiIndex(dst, times_1);
2087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
209044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::AddSmiField(Register dst, const Operand& src) {
209144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT_EQ(0, kSmiShift % kBitsPerByte);
209244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  addl(dst, Operand(src, kSmiShift / kBitsPerByte));
209344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
209444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
209544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfNotString(Register object,
2097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Register object_map,
2098257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Label* not_string,
2099257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Label::Distance near_jump) {
2100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition is_smi = CheckSmi(object);
2101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(is_smi, not_string, near_jump);
2102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CmpObjectType(object, FIRST_NONSTRING_TYPE, object_map);
2103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(above_equal, not_string, near_jump);
2104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfNotBothSequentialAsciiStrings(
2108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register first_object,
2109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register second_object,
2110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register scratch1,
2111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register scratch2,
2112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label* on_fail,
2113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label::Distance near_jump) {
2114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that both objects are not smis.
2115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition either_smi = CheckEitherSmi(first_object, second_object);
2116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(either_smi, on_fail, near_jump);
2117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load instance type for both strings.
2119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  movq(scratch1, FieldOperand(first_object, HeapObject::kMapOffset));
2120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  movq(scratch2, FieldOperand(second_object, HeapObject::kMapOffset));
2121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  movzxbl(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset));
2122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  movzxbl(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset));
2123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
21243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check that both are flat ASCII strings.
2125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(kNotStringTag != 0);
2126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int kFlatAsciiStringMask =
2127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
2128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int kFlatAsciiStringTag = ASCII_STRING_TYPE;
2129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  andl(scratch1, Immediate(kFlatAsciiStringMask));
2131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  andl(scratch2, Immediate(kFlatAsciiStringMask));
2132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Interleave the bits to check both scratch1 and scratch2 in one test.
2133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3));
2134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  lea(scratch1, Operand(scratch1, scratch2, times_8, 0));
2135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  cmpl(scratch1,
2136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch       Immediate(kFlatAsciiStringTag + (kFlatAsciiStringTag << 3)));
2137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_equal, on_fail, near_jump);
2138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii(
2142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register instance_type,
2143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register scratch,
2144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label* failure,
2145257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label::Distance near_jump) {
2146257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!scratch.is(instance_type)) {
2147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movl(scratch, instance_type);
2148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int kFlatAsciiStringMask =
2151257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
2152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  andl(scratch, Immediate(kFlatAsciiStringMask));
2154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  cmpl(scratch, Immediate(kStringTag | kSeqStringTag | kAsciiStringTag));
2155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_equal, failure, near_jump);
2156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialAscii(
2160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register first_object_instance_type,
2161257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register second_object_instance_type,
2162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register scratch1,
2163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register scratch2,
2164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label* on_fail,
2165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label::Distance near_jump) {
2166257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load instance type for both strings.
2167257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  movq(scratch1, first_object_instance_type);
2168257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  movq(scratch2, second_object_instance_type);
2169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
21703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check that both are flat ASCII strings.
2171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(kNotStringTag != 0);
2172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int kFlatAsciiStringMask =
2173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
2174257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int kFlatAsciiStringTag = ASCII_STRING_TYPE;
2175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2176257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  andl(scratch1, Immediate(kFlatAsciiStringMask));
2177257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  andl(scratch2, Immediate(kFlatAsciiStringMask));
2178257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Interleave the bits to check both scratch1 and scratch2 in one test.
2179257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3));
2180257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  lea(scratch1, Operand(scratch1, scratch2, times_8, 0));
2181257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  cmpl(scratch1,
2182257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch       Immediate(kFlatAsciiStringTag + (kFlatAsciiStringTag << 3)));
2183257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_equal, on_fail, near_jump);
2184257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2185257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2186257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
218744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
21880d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::Move(Register dst, Register src) {
21890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (!dst.is(src)) {
21900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    movq(dst, src);
21916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
21926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
21936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Move(Register dst, Handle<Object> source) {
2196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!source->IsFailure());
2197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (source->IsSmi()) {
21983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Move(dst, Smi::cast(*source));
2199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(dst, source, RelocInfo::EMBEDDED_OBJECT);
2201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Move(const Operand& dst, Handle<Object> source) {
22063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!source->IsFailure());
2207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (source->IsSmi()) {
22083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Move(dst, Smi::cast(*source));
2209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT);
2211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(dst, kScratchRegister);
2212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Cmp(Register dst, Handle<Object> source) {
22173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (source->IsSmi()) {
221844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Cmp(dst, Smi::cast(*source));
22193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
22203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Move(kScratchRegister, source);
22213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    cmpq(dst, kScratchRegister);
22223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Cmp(const Operand& dst, Handle<Object> source) {
2227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (source->IsSmi()) {
222844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Cmp(dst, Smi::cast(*source));
2229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(source->IsHeapObject());
2231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT);
2232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    cmpq(dst, kScratchRegister);
2233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Push(Handle<Object> source) {
2238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (source->IsSmi()) {
22393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Push(Smi::cast(*source));
2240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(source->IsHeapObject());
2242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT);
2243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    push(kScratchRegister);
2244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::LoadHeapObject(Register result,
22493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    Handle<HeapObject> object) {
22503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (isolate()->heap()->InNewSpace(*object)) {
22513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell =
22523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        isolate()->factory()->NewJSGlobalPropertyCell(object);
22533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    movq(result, cell, RelocInfo::GLOBAL_PROPERTY_CELL);
22543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    movq(result, Operand(result, 0));
22553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
22563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Move(result, object);
22573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
22583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
22593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::PushHeapObject(Handle<HeapObject> object) {
22623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (isolate()->heap()->InNewSpace(*object)) {
22633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell =
22643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        isolate()->factory()->NewJSGlobalPropertyCell(object);
22653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    movq(kScratchRegister, cell, RelocInfo::GLOBAL_PROPERTY_CELL);
22663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    movq(kScratchRegister, Operand(kScratchRegister, 0));
22673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    push(kScratchRegister);
22683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
22693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Push(object);
22703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
22713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
22723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::LoadGlobalCell(Register dst,
22753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    Handle<JSGlobalPropertyCell> cell) {
22763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (dst.is(rax)) {
22773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    load_rax(cell.location(), RelocInfo::GLOBAL_PROPERTY_CELL);
22783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
22793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    movq(dst, cell, RelocInfo::GLOBAL_PROPERTY_CELL);
22803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    movq(dst, Operand(dst, 0));
22813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
22823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
22833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Push(Smi* source) {
22863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  intptr_t smi = reinterpret_cast<intptr_t>(source);
22873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (is_int32(smi)) {
22883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    push(Immediate(static_cast<int32_t>(smi)));
22893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
22908defd9ff6930b4e24729971a61cf7469daf119beSteve Block    Register constant = GetSmiConstant(source);
22918defd9ff6930b4e24729971a61cf7469daf119beSteve Block    push(constant);
22923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
22933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
22943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
22953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2296e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::Drop(int stack_elements) {
2297e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (stack_elements > 0) {
2298e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    addq(rsp, Immediate(stack_elements * kPointerSize));
2299e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2300e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
2301e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2302e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
23033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::Test(const Operand& src, Smi* source) {
2304f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  testl(Operand(src, kIntSize), Immediate(source->value()));
2305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
23083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::TestBit(const Operand& src, int bits) {
23093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int byte_offset = bits / kBitsPerByte;
23103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int bit_in_byte = bits & (kBitsPerByte - 1);
23113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  testb(Operand(src, byte_offset), Immediate(1 << bit_in_byte));
23123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
23133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Jump(ExternalReference ext) {
231644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(kScratchRegister, ext);
2317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  jmp(kScratchRegister);
2318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Jump(Address destination, RelocInfo::Mode rmode) {
2322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister, destination, rmode);
2323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  jmp(kScratchRegister);
2324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Jump(Handle<Code> code_object, RelocInfo::Mode rmode) {
23283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // TODO(X64): Inline this
23293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  jmp(code_object, rmode);
2330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
233344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint MacroAssembler::CallSize(ExternalReference ext) {
233444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Opcode for call kScratchRegister is: Rex.B FF D4 (three bytes).
233544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const int kCallInstructionSize = 3;
233644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return LoadAddressSize(ext) + kCallInstructionSize;
233744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
233844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
233944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Call(ExternalReference ext) {
234144f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
234244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int end_position = pc_offset() + CallSize(ext);
234344f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
234444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(kScratchRegister, ext);
2345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  call(kScratchRegister);
234644f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
234744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(end_position, pc_offset());
234844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
2349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Call(Address destination, RelocInfo::Mode rmode) {
235344f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
235444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int end_position = pc_offset() + CallSize(destination, rmode);
235544f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
2356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister, destination, rmode);
2357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  call(kScratchRegister);
235844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
235944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(pc_offset(), end_position);
236044f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
2361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2364257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::Call(Handle<Code> code_object,
2365257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                          RelocInfo::Mode rmode,
2366257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                          unsigned ast_id) {
236744f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
236844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int end_position = pc_offset() + CallSize(code_object);
236944f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
2370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(RelocInfo::IsCodeTarget(rmode));
2371257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  call(code_object, rmode, ast_id);
237244f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
237344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(end_position, pc_offset());
237444f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
2375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
23781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::Pushad() {
23791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  push(rax);
23801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  push(rcx);
23811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  push(rdx);
23821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  push(rbx);
23831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Not pushing rsp or rbp.
23841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  push(rsi);
23851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  push(rdi);
23861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  push(r8);
23871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  push(r9);
23881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // r10 is kScratchRegister.
23891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  push(r11);
239044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // r12 is kSmiConstantRegister.
23911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // r13 is kRootRegister.
23921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  push(r14);
239344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  push(r15);
2394e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  STATIC_ASSERT(11 == kNumSafepointSavedRegisters);
2395e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Use lea for symmetry with Popad.
2396e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int sp_delta =
2397e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      (kNumSafepointRegisters - kNumSafepointSavedRegisters) * kPointerSize;
2398e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  lea(rsp, Operand(rsp, -sp_delta));
23991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
24001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
24011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
24021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::Popad() {
2403e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Popad must not change the flags, so use lea instead of addq.
2404e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int sp_delta =
2405e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      (kNumSafepointRegisters - kNumSafepointSavedRegisters) * kPointerSize;
2406e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  lea(rsp, Operand(rsp, sp_delta));
240744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  pop(r15);
24081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  pop(r14);
24091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  pop(r11);
24101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  pop(r9);
24111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  pop(r8);
24121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  pop(rdi);
24131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  pop(rsi);
24141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  pop(rbx);
24151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  pop(rdx);
24161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  pop(rcx);
24171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  pop(rax);
24181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
24191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
24201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
24211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::Dropad() {
2422e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  addq(rsp, Immediate(kNumSafepointRegisters * kPointerSize));
24231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
24241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
24251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
24261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Order general registers are pushed by Pushad:
242744f0eee88ff00398ff7f715fab053374d808c90dSteve Block// rax, rcx, rdx, rbx, rsi, rdi, r8, r9, r11, r14, r15.
24283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int
24293ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochMacroAssembler::kSafepointPushRegisterIndices[Register::kNumRegisters] = {
24301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    0,
24311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    1,
24321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    2,
24331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    3,
24341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    -1,
24351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    -1,
24361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    4,
24371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    5,
24381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    6,
24391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    7,
24401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    -1,
24411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    8,
24421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    -1,
244344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    -1,
244444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    9,
244544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    10
24461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block};
24471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
24481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2449e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Register src) {
2450e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  movq(SafepointRegisterSlot(dst), src);
2451e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2452e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2453e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2454e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) {
2455e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  movq(dst, SafepointRegisterSlot(src));
2456e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2457e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2458e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2459e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochOperand MacroAssembler::SafepointRegisterSlot(Register reg) {
2460e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return Operand(rsp, SafepointRegisterStackIndex(reg.code()) * kPointerSize);
2461e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2462e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2463e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
24643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::PushTryHandler(StackHandler::Kind kind,
24653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    int handler_index) {
2466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Adjust this code if not the case.
246769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
24683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
24693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
24703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
24713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
24723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
24733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We will build up the handler from the bottom by pushing on the stack.
24753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // First push the frame pointer and context.
24763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (kind == StackHandler::JS_ENTRY) {
24773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // The frame pointer does not point to a JS frame so we save NULL for
24783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rbp. We expect the code throwing an exception to check rbp before
24793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // dereferencing it to restore the context.
248085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    push(Immediate(0));  // NULL frame pointer.
248185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    Push(Smi::FromInt(0));  // No context.
24823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
24833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    push(rbp);
24843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    push(rsi);
2485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
24863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Push the state and the code object.
24883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  unsigned state =
24893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      StackHandler::IndexField::encode(handler_index) |
24903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      StackHandler::KindField::encode(kind);
24913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  push(Immediate(state));
24923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Push(CodeObject());
24933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Link the current handler as the next handler.
24953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
24963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  push(ExternalOperand(handler_address));
24973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set this new handler as the current one.
24983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movq(ExternalOperand(handler_address), rsp);
2499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2502e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::PopTryHandler() {
25033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
25043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
25053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  pop(ExternalOperand(handler_address));
2506e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  addq(rsp, Immediate(StackHandlerConstants::kSize - kPointerSize));
2507e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
2508e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2509e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
25103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::JumpToHandlerEntry() {
25113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Compute the handler entry address and jump to it.  The handler table is
25123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // a fixed array of (smi-tagged) code offsets.
25133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // rax = exception, rdi = code object, rdx = state.
25143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movq(rbx, FieldOperand(rdi, Code::kHandlerTableOffset));
25153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  shr(rdx, Immediate(StackHandler::kKindWidth));
25163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movq(rdx, FieldOperand(rbx, rdx, times_8, FixedArray::kHeaderSize));
25173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SmiToInteger64(rdx, rdx);
25183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lea(rdi, FieldOperand(rdi, rdx, times_1, Code::kHeaderSize));
25193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  jmp(rdi);
25203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
25213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2523e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::Throw(Register value) {
252469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Adjust this code if not the case.
252569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
25263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
25273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
25283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
25293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
25303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
25313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The exception is expected in rax.
2533e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!value.is(rax)) {
2534e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    movq(rax, value);
2535e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
25363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Drop the stack pointer to the top of the top handler.
253785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
25383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movq(rsp, ExternalOperand(handler_address));
25393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Restore the next handler.
25403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  pop(ExternalOperand(handler_address));
25413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Remove the code object and state, compute the handler address in rdi.
25433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  pop(rdi);  // Code object.
25443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  pop(rdx);  // Offset and state.
25453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Restore the context and frame pointer.
254769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  pop(rsi);  // Context.
254869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  pop(rbp);  // Frame pointer.
2549e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
255069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // If the handler is a JS frame, restore the context to the frame.
25513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // (kind == ENTRY) == (rbp == 0) == (rsi == 0), so we could test either
25523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // rbp or rsi.
2553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label skip;
25543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  testq(rsi, rsi);
25553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(zero, &skip, Label::kNear);
255669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi);
2557e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  bind(&skip);
255869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
25593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpToHandlerEntry();
2560e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2561e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2562e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
25633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::ThrowUncatchable(Register value) {
256469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Adjust this code if not the case.
256569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
25663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
25673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
25683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
25693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
25703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
25713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The exception is expected in rax.
25735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (!value.is(rax)) {
2574592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    movq(rax, value);
2575e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
25763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Drop the stack pointer to the top of the top stack handler.
2577592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
2578592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Load(rsp, handler_address);
2579e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
25803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Unwind the handlers until the top ENTRY handler is found.
25813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label fetch_next, check_kind;
25823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  jmp(&check_kind, Label::kNear);
25833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&fetch_next);
25843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movq(rsp, Operand(rsp, StackHandlerConstants::kNextOffset));
2585e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
25863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&check_kind);
25873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandler::JS_ENTRY == 0);
25883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  testl(Operand(rsp, StackHandlerConstants::kStateOffset),
25893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Immediate(StackHandler::KindField::kMask));
25903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_zero, &fetch_next);
2591592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
25923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set the top handler address to next handler past the top ENTRY handler.
25933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  pop(ExternalOperand(handler_address));
2594592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
25953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Remove the code object and state, compute the handler address in rdi.
25963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  pop(rdi);  // Code object.
25973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  pop(rdx);  // Offset and state.
2598592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
25993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Clear the context pointer and frame pointer (0 was saved in the handler).
26003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  pop(rsi);
26013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  pop(rbp);
2602592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
26033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpToHandlerEntry();
2604e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2605e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2606e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Ret() {
2608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ret(0);
2609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::Ret(int bytes_dropped, Register scratch) {
26131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (is_uint16(bytes_dropped)) {
26141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ret(bytes_dropped);
26151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
26161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    pop(scratch);
26171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    addq(rsp, Immediate(bytes_dropped));
26181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    push(scratch);
26191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ret(0);
26201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
26211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
26221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
26231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::FCmp() {
26253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  fucomip();
26268defd9ff6930b4e24729971a61cf7469daf119beSteve Block  fstp(0);
2627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpObjectType(Register heap_object,
2631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   InstanceType type,
2632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   Register map) {
2633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(map, FieldOperand(heap_object, HeapObject::kMapOffset));
2634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CmpInstanceType(map, type);
2635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpInstanceType(Register map, InstanceType type) {
2639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cmpb(FieldOperand(map, Map::kInstanceTypeOffset),
2640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       Immediate(static_cast<int8_t>(type)));
2641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::CheckFastElements(Register map,
26453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                       Label* fail,
26463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                       Label::Distance distance) {
26473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS == 0);
26483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(FAST_ELEMENTS == 1);
26493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmpb(FieldOperand(map, Map::kBitField2Offset),
26503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       Immediate(Map::kMaximumBitField2FastElementValue));
26513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(above, fail, distance);
26523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
26533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckFastObjectElements(Register map,
26563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Label* fail,
26573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Label::Distance distance) {
26583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS == 0);
26593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(FAST_ELEMENTS == 1);
26603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmpb(FieldOperand(map, Map::kBitField2Offset),
26613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       Immediate(Map::kMaximumBitField2FastSmiOnlyElementValue));
26623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(below_equal, fail, distance);
2663592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  cmpb(FieldOperand(map, Map::kBitField2Offset),
2664592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch       Immediate(Map::kMaximumBitField2FastElementValue));
2665592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  j(above, fail, distance);
2666592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch}
2667592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
2668592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
26693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckFastSmiOnlyElements(Register map,
26703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              Label* fail,
26713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              Label::Distance distance) {
26723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS == 0);
26733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmpb(FieldOperand(map, Map::kBitField2Offset),
26743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       Immediate(Map::kMaximumBitField2FastSmiOnlyElementValue));
26753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(above, fail, distance);
26763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
26773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::StoreNumberToDoubleElements(
26803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register maybe_number,
26813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register elements,
26823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register index,
26833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    XMMRegister xmm_scratch,
26843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* fail) {
26853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label smi_value, is_nan, maybe_nan, not_nan, have_double_value, done;
26863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpIfSmi(maybe_number, &smi_value, Label::kNear);
26883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckMap(maybe_number,
26903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           isolate()->factory()->heap_number_map(),
26913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           fail,
26923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           DONT_DO_SMI_CHECK);
26933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Double value, canonicalize NaN.
26953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  uint32_t offset = HeapNumber::kValueOffset + sizeof(kHoleNanLower32);
26963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmpl(FieldOperand(maybe_number, offset),
26973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       Immediate(kNaNOrInfinityLowerBoundUpper32));
26983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(greater_equal, &maybe_nan, Label::kNear);
26993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&not_nan);
27013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movsd(xmm_scratch, FieldOperand(maybe_number, HeapNumber::kValueOffset));
27023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&have_double_value);
27033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movsd(FieldOperand(elements, index, times_8, FixedDoubleArray::kHeaderSize),
27043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        xmm_scratch);
27053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  jmp(&done);
27063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&maybe_nan);
27083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise
27093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // it's an Infinity, and the non-NaN code path applies.
27103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(greater, &is_nan, Label::kNear);
27113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmpl(FieldOperand(maybe_number, HeapNumber::kValueOffset), Immediate(0));
27123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(zero, &not_nan);
27133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&is_nan);
27143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Convert all NaNs to the same canonical NaN value when they are stored in
27153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the double array.
27163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Set(kScratchRegister, BitCast<uint64_t>(
27173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      FixedDoubleArray::canonical_not_the_hole_nan_as_double()));
27183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movq(xmm_scratch, kScratchRegister);
27193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  jmp(&have_double_value, Label::kNear);
27203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&smi_value);
27223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Value is a smi. convert to a double and store.
27233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Preserve original value.
27243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SmiToInteger32(kScratchRegister, maybe_number);
27253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cvtlsi2sd(xmm_scratch, kScratchRegister);
27263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movsd(FieldOperand(elements, index, times_8, FixedDoubleArray::kHeaderSize),
27273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        xmm_scratch);
27283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&done);
27293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
27303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CompareMap(Register obj,
27333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                Handle<Map> map,
27343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                Label* early_success,
27353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                CompareMapMode mode) {
27363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Cmp(FieldOperand(obj, HeapObject::kMapOffset), map);
27373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (mode == ALLOW_ELEMENT_TRANSITION_MAPS) {
27383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Map* transitioned_fast_element_map(
27393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        map->LookupElementsTransitionMap(FAST_ELEMENTS, NULL));
27403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(transitioned_fast_element_map == NULL ||
27413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           map->elements_kind() != FAST_ELEMENTS);
27423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (transitioned_fast_element_map != NULL) {
27433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      j(equal, early_success, Label::kNear);
27443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Cmp(FieldOperand(obj, HeapObject::kMapOffset),
27453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Handle<Map>(transitioned_fast_element_map));
27463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
27473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Map* transitioned_double_map(
27493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        map->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, NULL));
27503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(transitioned_double_map == NULL ||
27513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           map->elements_kind() == FAST_SMI_ONLY_ELEMENTS);
27523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (transitioned_double_map != NULL) {
27533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      j(equal, early_success, Label::kNear);
27543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Cmp(FieldOperand(obj, HeapObject::kMapOffset),
27553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Handle<Map>(transitioned_double_map));
27563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
27573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
27583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
27593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::CheckMap(Register obj,
27623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Handle<Map> map,
27633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Label* fail,
27643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              SmiCheckType smi_check_type,
27653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              CompareMapMode mode) {
2766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (smi_check_type == DO_SMI_CHECK) {
27673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    JumpIfSmi(obj, fail);
27683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
27693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label success;
27713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompareMap(obj, map, &success, mode);
27723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  j(not_equal, fail);
27733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&success);
27743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
27753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
27763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2777257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::ClampUint8(Register reg) {
2778257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
2779257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  testl(reg, Immediate(0xFFFFFF00));
2780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(zero, &done, Label::kNear);
2781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  setcc(negative, reg);  // 1 if negative, 0 if positive.
2782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  decb(reg);  // 0 if negative, 255 if positive.
2783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&done);
2784257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2785257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2787257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::ClampDoubleToUint8(XMMRegister input_reg,
2788257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                        XMMRegister temp_xmm_reg,
2789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                        Register result_reg,
2790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                        Register temp_reg) {
2791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
2792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Set(result_reg, 0);
2793257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  xorps(temp_xmm_reg, temp_xmm_reg);
2794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ucomisd(input_reg, temp_xmm_reg);
2795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(below, &done, Label::kNear);
2796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  uint64_t one_half = BitCast<uint64_t, double>(0.5);
2797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Set(temp_reg, one_half);
2798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  movq(temp_xmm_reg, temp_reg);
2799257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  addsd(temp_xmm_reg, input_reg);
2800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  cvttsd2si(result_reg, temp_xmm_reg);
2801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  testl(result_reg, Immediate(0xFFFFFF00));
2802257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(zero, &done, Label::kNear);
2803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Set(result_reg, 255);
2804257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&done);
2805257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2806257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2807257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2808257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::LoadInstanceDescriptors(Register map,
2809257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Register descriptors) {
2810257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  movq(descriptors, FieldOperand(map,
2811257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Map::kInstanceDescriptorsOrBitField3Offset));
2812257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label not_smi;
2813257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  JumpIfNotSmi(descriptors, &not_smi, Label::kNear);
2814257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Move(descriptors, isolate()->factory()->empty_descriptor_array());
2815257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&not_smi);
2816257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2817257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2818257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2819257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::DispatchMap(Register obj,
2820257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Handle<Map> map,
2821257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Handle<Code> success,
2822257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 SmiCheckType smi_check_type) {
2823257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label fail;
2824257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (smi_check_type == DO_SMI_CHECK) {
2825257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    JumpIfSmi(obj, &fail);
2826257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2827257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Cmp(FieldOperand(obj, HeapObject::kMapOffset), map);
2828257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(equal, success, RelocInfo::CODE_TARGET);
2829257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2830257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&fail);
2831257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2832257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2833257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid MacroAssembler::AbortIfNotNumber(Register object) {
2835257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label ok;
2836402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Condition is_smi = CheckSmi(object);
2837257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(is_smi, &ok, Label::kNear);
2838402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Cmp(FieldOperand(object, HeapObject::kMapOffset),
2839257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      isolate()->factory()->heap_number_map());
2840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Assert(equal, "Operand not a number");
2841402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  bind(&ok);
2842402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
2843402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2844402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2845756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid MacroAssembler::AbortIfSmi(Register object) {
2846756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Condition is_smi = CheckSmi(object);
2847756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Assert(NegateCondition(is_smi), "Operand is a smi");
2848756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
2849756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2850756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2851f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid MacroAssembler::AbortIfNotSmi(Register object) {
285244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Condition is_smi = CheckSmi(object);
285344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Assert(is_smi, "Operand is not a smi");
285444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
285544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
285644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
285744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::AbortIfNotSmi(const Operand& object) {
28586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Condition is_smi = CheckSmi(object);
2859756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Assert(is_smi, "Operand is not a smi");
28606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
28616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
28626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
28633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::AbortIfNotZeroExtended(Register int32_register) {
28643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!int32_register.is(kScratchRegister));
28653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movq(kScratchRegister, 0x100000000l, RelocInfo::NONE);
28663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmpq(kScratchRegister, int32_register);
28673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Assert(above_equal, "32 bit value in register is not zero-extended");
28683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
28693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2871e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::AbortIfNotString(Register object) {
2872e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  testb(object, Immediate(kSmiTagMask));
2873e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Assert(not_equal, "Operand is not a string");
2874e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  push(object);
2875e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  movq(object, FieldOperand(object, HeapObject::kMapOffset));
2876e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CmpInstanceType(object, FIRST_NONSTRING_TYPE);
2877e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  pop(object);
2878e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Assert(below, "Operand is not a string");
2879e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2880e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2881e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
28829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::AbortIfNotRootValue(Register src,
28839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                         Heap::RootListIndex root_value_index,
28849dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                         const char* message) {
28859dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  ASSERT(!src.is(kScratchRegister));
28869dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  LoadRoot(kScratchRegister, root_value_index);
28879dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  cmpq(src, kScratchRegister);
28889dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  Check(equal, message);
28899dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
28909dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
28919dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
28929dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
2893d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeCondition MacroAssembler::IsObjectStringType(Register heap_object,
2894d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                             Register map,
2895d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                             Register instance_type) {
2896d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  movq(map, FieldOperand(heap_object, HeapObject::kMapOffset));
28974515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  movzxbl(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
289869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kNotStringTag != 0);
2899d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  testb(instance_type, Immediate(kIsNotStringMask));
2900d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  return zero;
2901d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
2902d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2903d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::TryGetFunctionPrototype(Register function,
2905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register result,
29063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Label* miss,
29073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             bool miss_on_bound_function) {
2908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
2909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  testl(function, Immediate(kSmiTagMask));
2910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(zero, miss);
2911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the function really is a function.
2913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CmpObjectType(function, JS_FUNCTION_TYPE, result);
2914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(not_equal, miss);
2915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (miss_on_bound_function) {
29173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    movq(kScratchRegister,
29183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
29193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // It's not smi-tagged (stored in the top half of a smi-tagged 8-byte
29203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // field).
29213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    TestBit(FieldOperand(kScratchRegister,
29223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         SharedFunctionInfo::kCompilerHintsOffset),
29233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            SharedFunctionInfo::kBoundFunction);
29243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(not_zero, miss);
29253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
29263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure that the function has an instance prototype.
2928257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label non_instance;
2929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  testb(FieldOperand(result, Map::kBitFieldOffset),
2930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Immediate(1 << Map::kHasNonInstancePrototype));
2931257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_zero, &non_instance, Label::kNear);
2932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the prototype or initial map from the function.
2934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(result,
2935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
2936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the prototype or initial map is the hole, don't return it and
2938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // simply miss the cache instead. This will allow us to allocate a
2939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // prototype object on-demand in the runtime system.
2940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompareRoot(result, Heap::kTheHoleValueRootIndex);
2941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(equal, miss);
2942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the function does not have an initial map, we're done.
2944257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
2945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CmpObjectType(result, MAP_TYPE, kScratchRegister);
2946257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_equal, &done, Label::kNear);
2947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the prototype from the initial map.
2949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(result, FieldOperand(result, Map::kPrototypeOffset));
2950257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  jmp(&done, Label::kNear);
2951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Non-instance prototype: Fetch prototype from constructor field
2953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // in initial map.
2954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&non_instance);
2955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(result, FieldOperand(result, Map::kConstructorOffset));
2956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // All done.
2958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&done);
2959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SetCounter(StatsCounter* counter, int value) {
2963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
296444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Operand counter_operand = ExternalOperand(ExternalReference(counter));
29658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    movl(counter_operand, Immediate(value));
2966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::IncrementCounter(StatsCounter* counter, int value) {
2971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(value > 0);
2972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
297344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Operand counter_operand = ExternalOperand(ExternalReference(counter));
2974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (value == 1) {
297544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      incl(counter_operand);
2976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
297744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      addl(counter_operand, Immediate(value));
2978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::DecrementCounter(StatsCounter* counter, int value) {
2984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(value > 0);
2985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
298644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Operand counter_operand = ExternalOperand(ExternalReference(counter));
2987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (value == 1) {
298844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      decl(counter_operand);
2989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
299044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      subl(counter_operand, Immediate(value));
2991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
299680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#ifdef ENABLE_DEBUGGER_SUPPORT
2997402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::DebugBreak() {
29989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Set(rax, 0);  // No arguments.
299944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(rbx, ExternalReference(Runtime::kDebugBreak, isolate()));
3000402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CEntryStub ces(1);
30013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(AllowThisStubCall(&ces));
3002402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Call(ces.GetCode(), RelocInfo::DEBUG_BREAK);
3003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3004402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#endif  // ENABLE_DEBUGGER_SUPPORT
3005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3007257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SetCallKind(Register dst, CallKind call_kind) {
3008257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This macro takes the dst register to make the code more readable
3009257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // at the call sites. However, the dst register has to be rcx to
3010257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // follow the calling convention which requires the call type to be
3011257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // in rcx.
3012257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(dst.is(rcx));
3013257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (call_kind == CALL_AS_FUNCTION) {
3014257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    LoadSmiConstant(dst, Smi::FromInt(1));
3015257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
3016257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    LoadSmiConstant(dst, Smi::FromInt(0));
3017257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3018257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3019257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeCode(Register code,
3022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                const ParameterCount& expected,
3023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                const ParameterCount& actual,
3024e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                InvokeFlag flag,
3025257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                const CallWrapper& call_wrapper,
3026257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                CallKind call_kind) {
30273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a function without a valid frame.
30283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(flag == JUMP_FUNCTION || has_frame());
30293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3030257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
30313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool definitely_mismatches = false;
3032e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  InvokePrologue(expected,
3033e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 actual,
3034e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 Handle<Code>::null(),
3035e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 code,
3036e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 &done,
30373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 &definitely_mismatches,
3038e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 flag,
3039257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 Label::kNear,
3040257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 call_wrapper,
3041257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 call_kind);
30423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!definitely_mismatches) {
30433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (flag == CALL_FUNCTION) {
30443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call_wrapper.BeforeCall(CallSize(code));
30453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SetCallKind(rcx, call_kind);
30463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call(code);
30473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call_wrapper.AfterCall();
30483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
30493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(flag == JUMP_FUNCTION);
30503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SetCallKind(rcx, call_kind);
30513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      jmp(code);
30523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
30533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&done);
3054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeCode(Handle<Code> code,
3059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                const ParameterCount& expected,
3060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                const ParameterCount& actual,
3061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                RelocInfo::Mode rmode,
3062e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                InvokeFlag flag,
3063257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                const CallWrapper& call_wrapper,
3064257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                CallKind call_kind) {
30653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a function without a valid frame.
30663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(flag == JUMP_FUNCTION || has_frame());
30673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3068257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
30693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool definitely_mismatches = false;
3070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Register dummy = rax;
3071e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  InvokePrologue(expected,
3072e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 actual,
3073e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 code,
3074e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 dummy,
3075e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 &done,
30763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 &definitely_mismatches,
3077e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 flag,
3078257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 Label::kNear,
3079257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 call_wrapper,
3080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 call_kind);
30813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!definitely_mismatches) {
30823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (flag == CALL_FUNCTION) {
30833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call_wrapper.BeforeCall(CallSize(code));
30843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SetCallKind(rcx, call_kind);
30853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Call(code, rmode);
30863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call_wrapper.AfterCall();
30873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
30883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(flag == JUMP_FUNCTION);
30893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SetCallKind(rcx, call_kind);
30903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Jump(code, rmode);
30913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
30923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&done);
3093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeFunction(Register function,
3098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    const ParameterCount& actual,
3099e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                    InvokeFlag flag,
3100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    const CallWrapper& call_wrapper,
3101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    CallKind call_kind) {
31023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a function without a valid frame.
31033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(flag == JUMP_FUNCTION || has_frame());
31043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(function.is(rdi));
3106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rdx, FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
3107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rsi, FieldOperand(function, JSFunction::kContextOffset));
3108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movsxlq(rbx,
3109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          FieldOperand(rdx, SharedFunctionInfo::kFormalParameterCountOffset));
3110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Advances rdx to the end of the Code object header, to the start of
3111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the executable code.
3112791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
3113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ParameterCount expected(rbx);
3115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  InvokeCode(rdx, expected, actual, flag, call_wrapper, call_kind);
3116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
31193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::InvokeFunction(Handle<JSFunction> function,
3120402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                    const ParameterCount& actual,
3121e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                    InvokeFlag flag,
3122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    const CallWrapper& call_wrapper,
3123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    CallKind call_kind) {
31243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a function without a valid frame.
31253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(flag == JUMP_FUNCTION || has_frame());
31263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3127402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Get the function and setup the context.
31283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LoadHeapObject(rdi, function);
3129402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
3130402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
31313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We call indirectly through the code field in the function to
31323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // allow recompilation to take effect without changing any of the
31333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // call sites.
31343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
31353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ParameterCount expected(function->shared()->formal_parameter_count());
31363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  InvokeCode(rdx, expected, actual, flag, call_wrapper, call_kind);
3137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::InvokePrologue(const ParameterCount& expected,
3141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    const ParameterCount& actual,
3142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Handle<Code> code_constant,
3143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Register code_register,
3144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Label* done,
31453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    bool* definitely_mismatches,
3146257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    InvokeFlag flag,
3147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Label::Distance near_jump,
3148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    const CallWrapper& call_wrapper,
3149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    CallKind call_kind) {
3150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool definitely_matches = false;
31513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  *definitely_mismatches = false;
3152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label invoke;
3153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (expected.is_immediate()) {
3154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(actual.is_immediate());
3155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (expected.immediate() == actual.immediate()) {
3156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      definitely_matches = true;
3157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
3158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Set(rax, actual.immediate());
3159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (expected.immediate() ==
3160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              SharedFunctionInfo::kDontAdaptArgumentsSentinel) {
3161257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // Don't worry about adapting arguments for built-ins that
3162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // don't want that done. Skip adaption code by making it look
3163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // like we have a match between expected and actual number of
3164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // arguments.
3165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        definitely_matches = true;
3166257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      } else {
31673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        *definitely_mismatches = true;
3168257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        Set(rbx, expected.immediate());
3169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
3170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
3171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
3172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (actual.is_immediate()) {
3173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Expected is in register, actual is immediate. This is the
3174257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // case when we invoke function values without going through the
3175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // IC mechanism.
3176257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      cmpq(expected.reg(), Immediate(actual.immediate()));
3177257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      j(equal, &invoke, Label::kNear);
3178257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ASSERT(expected.reg().is(rbx));
3179257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Set(rax, actual.immediate());
3180257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else if (!expected.reg().is(actual.reg())) {
3181257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Both expected and actual are in (different) registers. This
3182257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // is the case when we invoke functions using call and apply.
3183257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      cmpq(expected.reg(), actual.reg());
3184257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      j(equal, &invoke, Label::kNear);
3185257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ASSERT(actual.reg().is(rax));
3186257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ASSERT(expected.reg().is(rbx));
3187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
3188257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3189257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3190257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!definitely_matches) {
3191257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Handle<Code> adaptor = isolate()->builtins()->ArgumentsAdaptorTrampoline();
3192257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (!code_constant.is_null()) {
3193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      movq(rdx, code_constant, RelocInfo::EMBEDDED_OBJECT);
3194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      addq(rdx, Immediate(Code::kHeaderSize - kHeapObjectTag));
3195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else if (!code_register.is(rdx)) {
3196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      movq(rdx, code_register);
3197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
3198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3199257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (flag == CALL_FUNCTION) {
3200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      call_wrapper.BeforeCall(CallSize(adaptor));
3201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      SetCallKind(rcx, call_kind);
3202257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Call(adaptor, RelocInfo::CODE_TARGET);
3203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      call_wrapper.AfterCall();
32043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (!*definitely_mismatches) {
32053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        jmp(done, near_jump);
32063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
3207257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
3208257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      SetCallKind(rcx, call_kind);
3209257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Jump(adaptor, RelocInfo::CODE_TARGET);
3210257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
3211257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    bind(&invoke);
32121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
3213402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
3214402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
3215402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
3216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::EnterFrame(StackFrame::Type type) {
3217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(rbp);
3218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rbp, rsp);
3219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(rsi);  // Context.
32203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Push(Smi::FromInt(type));
3221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT);
3222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(kScratchRegister);
322344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
3224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(kScratchRegister,
3225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         isolate()->factory()->undefined_value(),
3226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         RelocInfo::EMBEDDED_OBJECT);
3227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    cmpq(Operand(rsp, 0), kScratchRegister);
3228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(not_equal, "code object not properly patched");
3229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LeaveFrame(StackFrame::Type type) {
323444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
32353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Move(kScratchRegister, Smi::FromInt(type));
3236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    cmpq(Operand(rbp, StandardFrameConstants::kMarkerOffset), kScratchRegister);
3237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(equal, "stack frame types must match");
3238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rsp, rbp);
3240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pop(rbp);
3241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
324480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::EnterExitFramePrologue(bool save_rax) {
32453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up the frame structure on the stack.
3246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // All constants are relative to the frame pointer of the exit frame.
3247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize);
3248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize);
3249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(ExitFrameConstants::kCallerFPOffset ==  0 * kPointerSize);
3250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(rbp);
3251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rbp, rsp);
3252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
325380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Reserve room for entry stack pointer and push the code object.
32543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize);
3255402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  push(Immediate(0));  // Saved entry sp, patched before call.
3256402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT);
3257402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  push(kScratchRegister);  // Accessed from EditFrame::code_slot.
3258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Save the frame pointer and the context in top.
3260bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (save_rax) {
326144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    movq(r14, rax);  // Backup rax in callee-save register.
3262bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
3263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3264589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Store(ExternalReference(Isolate::kCEntryFPAddress, isolate()), rbp);
3265589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Store(ExternalReference(Isolate::kContextAddress, isolate()), rsi);
3266bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
3267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
32688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
32691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::EnterExitFrameEpilogue(int arg_stack_space,
32701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                            bool save_doubles) {
3271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef _WIN64
32721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  const int kShadowSpace = 4;
32731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  arg_stack_space += kShadowSpace;
3274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
32751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Optionally save all XMM registers.
32761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (save_doubles) {
32771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    int space = XMMRegister::kNumRegisters * kDoubleSize +
32781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        arg_stack_space * kPointerSize;
32791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    subq(rsp, Immediate(space));
32801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    int offset = -2 * kPointerSize;
32811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; i++) {
32821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      XMMRegister reg = XMMRegister::FromAllocationIndex(i);
32831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      movsd(Operand(rbp, offset - ((i + 1) * kDoubleSize)), reg);
32841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
32851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else if (arg_stack_space > 0) {
32868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    subq(rsp, Immediate(arg_stack_space * kPointerSize));
32878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  }
3288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the required frame alignment for the OS.
329044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const int kFrameAlignment = OS::ActivationFrameAlignment();
3291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (kFrameAlignment > 0) {
3292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(IsPowerOf2(kFrameAlignment));
32938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    ASSERT(is_int8(kFrameAlignment));
32948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    and_(rsp, Immediate(-kFrameAlignment));
3295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the saved entry sp.
3298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(Operand(rbp, ExitFrameConstants::kSPOffset), rsp);
3299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
33021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::EnterExitFrame(int arg_stack_space, bool save_doubles) {
330380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  EnterExitFramePrologue(true);
3304bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
33053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up argv in callee-saved register r15. It is reused in LeaveExitFrame,
3306bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // so it must be retained across the C-call.
3307bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
330844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lea(r15, Operand(rbp, r14, times_pointer_size, offset));
3309bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
33101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  EnterExitFrameEpilogue(arg_stack_space, save_doubles);
3311bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
3312bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
3313bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
33148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid MacroAssembler::EnterApiExitFrame(int arg_stack_space) {
331580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  EnterExitFramePrologue(false);
33161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  EnterExitFrameEpilogue(arg_stack_space, false);
3317bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
3318bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
3319bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
33201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::LeaveExitFrame(bool save_doubles) {
3321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Registers:
332244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // r15 : argv
33231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (save_doubles) {
33241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    int offset = -2 * kPointerSize;
33251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; i++) {
33261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      XMMRegister reg = XMMRegister::FromAllocationIndex(i);
33271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      movsd(reg, Operand(rbp, offset - ((i + 1) * kDoubleSize)));
33281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
33291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
3330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the return address from the stack and restore the frame pointer.
3331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rcx, Operand(rbp, 1 * kPointerSize));
3332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rbp, Operand(rbp, 0 * kPointerSize));
3333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
33341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Drop everything up to and including the arguments and the receiver
3335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // from the caller stack.
333644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lea(rsp, Operand(r15, 1 * kPointerSize));
3337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
33388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Push the return address to get ready to return.
33398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  push(rcx);
33408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
33418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LeaveExitFrameEpilogue();
33428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
33438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
33448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
33458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid MacroAssembler::LeaveApiExitFrame() {
33468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  movq(rsp, rbp);
33478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  pop(rbp);
33488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
33498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LeaveExitFrameEpilogue();
33508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
33518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
33528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
33538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid MacroAssembler::LeaveExitFrameEpilogue() {
3354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Restore current context from top and clear it in debug mode.
3355589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ExternalReference context_address(Isolate::kContextAddress, isolate());
335644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Operand context_operand = ExternalOperand(context_address);
335744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  movq(rsi, context_operand);
3358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
335944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  movq(context_operand, Immediate(0));
3360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
3361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clear the top frame.
3363589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress,
336444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       isolate());
336544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Operand c_entry_fp_operand = ExternalOperand(c_entry_fp_address);
336644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  movq(c_entry_fp_operand, Immediate(0));
3367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
3371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            Register scratch,
3372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            Label* miss) {
3373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label same_contexts;
3374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!holder_reg.is(scratch));
3376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!scratch.is(kScratchRegister));
3377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load current lexical context from the stack frame.
3378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(scratch, Operand(rbp, StandardFrameConstants::kContextOffset));
3379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // When generating debug code, make sure the lexical context is set.
338144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
3382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    cmpq(scratch, Immediate(0));
3383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(not_equal, "we should not have an empty lexical context");
3384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the global context of the current context.
3386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
3387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(scratch, FieldOperand(scratch, offset));
3388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(scratch, FieldOperand(scratch, GlobalObject::kGlobalContextOffset));
3389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check the context is a global context.
339144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
3392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Cmp(FieldOperand(scratch, HeapObject::kMapOffset),
3393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        isolate()->factory()->global_context_map());
3394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(equal, "JSGlobalObject::global_context should be a global context.");
3395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if both contexts are the same.
3398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cmpq(scratch, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset));
3399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(equal, &same_contexts);
3400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compare security tokens.
3402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the security token in the calling global object is
3403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // compatible with the security token in the receiving global
3404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object.
3405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check the context is a global context.
340744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
3408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Preserve original value of holder_reg.
3409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    push(holder_reg);
3410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(holder_reg, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset));
3411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CompareRoot(holder_reg, Heap::kNullValueRootIndex);
3412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(not_equal, "JSGlobalProxy::context() should not be null.");
3413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Read the first word and compare to global_context_map(),
3415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(holder_reg, FieldOperand(holder_reg, HeapObject::kMapOffset));
3416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CompareRoot(holder_reg, Heap::kGlobalContextMapRootIndex);
3417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(equal, "JSGlobalObject::global_context should be a global context.");
3418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    pop(holder_reg);
3419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister,
3422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       FieldOperand(holder_reg, JSGlobalProxy::kContextOffset));
34233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int token_offset =
34243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      Context::kHeaderSize + Context::SECURITY_TOKEN_INDEX * kPointerSize;
3425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(scratch, FieldOperand(scratch, token_offset));
3426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cmpq(scratch, FieldOperand(kScratchRegister, token_offset));
3427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(not_equal, miss);
3428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&same_contexts);
3430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3433c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdochvoid MacroAssembler::GetNumberHash(Register r0, Register scratch) {
3434c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // First of all we assign the hash seed to scratch.
3435c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  LoadRoot(scratch, Heap::kHashSeedRootIndex);
3436c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  SmiToInteger32(scratch, scratch);
3437c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
3438c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // Xor original key with a seed.
3439c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  xorl(r0, scratch);
3440c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
3441c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // Compute the hash code from the untagged key.  This must be kept in sync
3442c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // with ComputeIntegerHash in utils.h.
3443c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  //
3444c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = ~hash + (hash << 15);
3445c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  movl(scratch, r0);
3446c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  notl(r0);
3447c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  shll(scratch, Immediate(15));
3448c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  addl(r0, scratch);
3449c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash ^ (hash >> 12);
3450c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  movl(scratch, r0);
3451c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  shrl(scratch, Immediate(12));
3452c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  xorl(r0, scratch);
3453c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash + (hash << 2);
3454c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  leal(r0, Operand(r0, r0, times_4, 0));
3455c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash ^ (hash >> 4);
3456c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  movl(scratch, r0);
3457c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  shrl(scratch, Immediate(4));
3458c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  xorl(r0, scratch);
3459c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash * 2057;
3460c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  imull(r0, r0, Immediate(2057));
3461c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash ^ (hash >> 16);
3462c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  movl(scratch, r0);
3463c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  shrl(scratch, Immediate(16));
3464c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  xorl(r0, scratch);
3465c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch}
3466c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
3467c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
3468c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
34693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::LoadFromNumberDictionary(Label* miss,
34703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register elements,
34713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register key,
34723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register r0,
34733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register r1,
34743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register r2,
34753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register result) {
34763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Register use:
34773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
34783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // elements - holds the slow-case elements of the receiver on entry.
34793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //            Unchanged unless 'result' is the same register.
34803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
34813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // key      - holds the smi key on entry.
34823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //            Unchanged unless 'result' is the same register.
34833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
34843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Scratch registers:
34853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
34863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // r0 - holds the untagged key on entry and holds the hash once computed.
34873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
34883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // r1 - used to hold the capacity mask of the dictionary
34893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
34903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // r2 - used for the index into the dictionary.
34913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
34923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // result - holds the result on exit if the load succeeded.
34933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //          Allowed to be the same as 'key' or 'result'.
34943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //          Unchanged on bailout so 'key' or 'result' can be used
34953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //          in further computation.
34963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
34973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label done;
34983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3499c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  GetNumberHash(r0, r1);
35003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
35013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Compute capacity mask.
3502c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  SmiToInteger32(r1, FieldOperand(elements,
3503c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                                  SeededNumberDictionary::kCapacityOffset));
35043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  decl(r1);
35053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
35063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Generate an unrolled loop that performs a few probes before giving up.
35073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const int kProbes = 4;
35083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (int i = 0; i < kProbes; i++) {
35093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Use r2 for index calculations and keep the hash intact in r0.
35103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    movq(r2, r0);
35113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Compute the masked index: (hash + i + i * i) & mask.
35123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (i > 0) {
3513c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      addl(r2, Immediate(SeededNumberDictionary::GetProbeOffset(i)));
35143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
35153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    and_(r2, r1);
35163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
35173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Scale the index by multiplying by the entry size.
3518c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    ASSERT(SeededNumberDictionary::kEntrySize == 3);
35193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    lea(r2, Operand(r2, r2, times_2, 0));  // r2 = r2 * 3
35203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
35213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Check if the key matches.
35223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    cmpq(key, FieldOperand(elements,
35233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                           r2,
35243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                           times_pointer_size,
3525c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                           SeededNumberDictionary::kElementsStartOffset));
35263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (i != (kProbes - 1)) {
35273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      j(equal, &done);
35283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
35293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      j(not_equal, miss);
35303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
35313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
35323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
35333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bind(&done);
35343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the value is a normal propety.
35353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const int kDetailsOffset =
3536c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize;
35373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT_EQ(NORMAL, 0);
35383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset),
3539589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch       Smi::FromInt(PropertyDetails::TypeField::kMask));
35403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  j(not_zero, miss);
35413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
35423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Get the value at the masked, scaled index.
35433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const int kValueOffset =
3544c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      SeededNumberDictionary::kElementsStartOffset + kPointerSize;
35453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  movq(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset));
35463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
35473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
35483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LoadAllocationTopHelper(Register result,
3550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register scratch,
3551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             AllocationFlags flags) {
3552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference new_space_allocation_top =
355344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::new_space_allocation_top_address(isolate());
3554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Just return if allocation top is already known.
3556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((flags & RESULT_CONTAINS_TOP) != 0) {
3557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // No use of scratch if allocation top is provided.
35586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(!scratch.is_valid());
3559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
3560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Assert that result actually contains top on entry.
356144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Operand top_operand = ExternalOperand(new_space_allocation_top);
356244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    cmpq(result, top_operand);
3563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(equal, "Unexpected allocation top");
3564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
3565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
3566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
35686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Move address of new object to result. Use scratch register if available,
35696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // and keep address in scratch until call to UpdateAllocationTopHelper.
35706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (scratch.is_valid()) {
357144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    LoadAddress(scratch, new_space_allocation_top);
3572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(result, Operand(scratch, 0));
35736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
357444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Load(result, new_space_allocation_top);
3575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::UpdateAllocationTopHelper(Register result_end,
3580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                               Register scratch) {
358144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
3582d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    testq(result_end, Immediate(kObjectAlignmentMask));
3583d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Check(zero, "Unaligned allocation in new space");
3584d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
3585d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference new_space_allocation_top =
358744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::new_space_allocation_top_address(isolate());
3588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update new top.
359044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (scratch.is_valid()) {
359144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Scratch already contains address of allocation top.
359244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    movq(Operand(scratch, 0), result_end);
3593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
359444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Store(new_space_allocation_top, result_end);
3595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(int object_size,
3600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register result,
3601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register result_end,
3602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch,
3603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Label* gc_required,
3604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        AllocationFlags flags) {
36055913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  if (!FLAG_inline_new) {
360644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (emit_debug_code()) {
36075913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // Trash the registers to simulate an allocation failure.
36085913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      movl(result, Immediate(0x7091));
36095913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (result_end.is_valid()) {
36105913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        movl(result_end, Immediate(0x7191));
36115913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
36125913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (scratch.is_valid()) {
36135913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        movl(scratch, Immediate(0x7291));
36145913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
36155913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    }
36165913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    jmp(gc_required);
36175913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    return;
36185913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
3619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!result.is(result_end));
3620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load address of new object into result.
36228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LoadAllocationTopHelper(result, scratch, flags);
3623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate new top and bail out if new space is exhausted.
3625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference new_space_allocation_limit =
362644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::new_space_allocation_limit_address(isolate());
36276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
36286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Register top_reg = result_end.is_valid() ? result_end : result;
36296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
36301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (!top_reg.is(result)) {
36311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    movq(top_reg, result);
36326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
36331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addq(top_reg, Immediate(object_size));
36341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  j(carry, gc_required);
363544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Operand limit_operand = ExternalOperand(new_space_allocation_limit);
363644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  cmpq(top_reg, limit_operand);
3637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(above, gc_required);
3638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update allocation top.
36406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  UpdateAllocationTopHelper(top_reg, scratch);
3641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
36426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (top_reg.is(result)) {
36436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if ((flags & TAG_OBJECT) != 0) {
36446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      subq(result, Immediate(object_size - kHeapObjectTag));
36456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
36466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      subq(result, Immediate(object_size));
36476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
36486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else if ((flags & TAG_OBJECT) != 0) {
36496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Tag the result if requested.
3650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    addq(result, Immediate(kHeapObjectTag));
3651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(int header_size,
3656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        ScaleFactor element_size,
3657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register element_count,
3658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register result,
3659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register result_end,
3660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch,
3661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Label* gc_required,
3662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        AllocationFlags flags) {
36635913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  if (!FLAG_inline_new) {
366444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (emit_debug_code()) {
36655913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // Trash the registers to simulate an allocation failure.
36665913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      movl(result, Immediate(0x7091));
36675913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      movl(result_end, Immediate(0x7191));
36685913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (scratch.is_valid()) {
36695913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        movl(scratch, Immediate(0x7291));
36705913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
36715913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // Register element_count is not modified by the function.
36725913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    }
36735913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    jmp(gc_required);
36745913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    return;
36755913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
3676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!result.is(result_end));
3677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load address of new object into result.
36798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LoadAllocationTopHelper(result, scratch, flags);
3680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate new top and bail out if new space is exhausted.
3682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference new_space_allocation_limit =
368344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::new_space_allocation_limit_address(isolate());
36841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // We assume that element_count*element_size + header_size does not
36861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // overflow.
36871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  lea(result_end, Operand(element_count, element_size, header_size));
36881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addq(result_end, result);
36891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  j(carry, gc_required);
369044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Operand limit_operand = ExternalOperand(new_space_allocation_limit);
369144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  cmpq(result_end, limit_operand);
3692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(above, gc_required);
3693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update allocation top.
3695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  UpdateAllocationTopHelper(result_end, scratch);
3696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Tag the result if requested.
3698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((flags & TAG_OBJECT) != 0) {
3699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    addq(result, Immediate(kHeapObjectTag));
3700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(Register object_size,
3705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register result,
3706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register result_end,
3707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch,
3708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Label* gc_required,
3709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        AllocationFlags flags) {
37105913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  if (!FLAG_inline_new) {
371144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (emit_debug_code()) {
37125913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // Trash the registers to simulate an allocation failure.
37135913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      movl(result, Immediate(0x7091));
37145913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      movl(result_end, Immediate(0x7191));
37155913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (scratch.is_valid()) {
37165913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        movl(scratch, Immediate(0x7291));
37175913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
37185913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // object_size is left unchanged by this function.
37195913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    }
37205913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    jmp(gc_required);
37215913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    return;
37225913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
37235913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  ASSERT(!result.is(result_end));
37245913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck
3725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load address of new object into result.
37268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LoadAllocationTopHelper(result, scratch, flags);
3727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate new top and bail out if new space is exhausted.
3729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference new_space_allocation_limit =
373044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::new_space_allocation_limit_address(isolate());
3731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!object_size.is(result_end)) {
3732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(result_end, object_size);
3733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addq(result_end, result);
37351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  j(carry, gc_required);
373644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Operand limit_operand = ExternalOperand(new_space_allocation_limit);
373744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  cmpq(result_end, limit_operand);
3738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(above, gc_required);
3739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update allocation top.
3741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  UpdateAllocationTopHelper(result_end, scratch);
3742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Tag the result if requested.
3744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((flags & TAG_OBJECT) != 0) {
3745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    addq(result, Immediate(kHeapObjectTag));
3746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::UndoAllocationInNewSpace(Register object) {
3751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference new_space_allocation_top =
375244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::new_space_allocation_top_address(isolate());
3753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure the object has no tag before resetting top.
3755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  and_(object, Immediate(~kHeapObjectTagMask));
375644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Operand top_operand = ExternalOperand(new_space_allocation_top);
3757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
375844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  cmpq(object, top_operand);
3759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Check(below, "Undo allocation of non allocated memory");
3760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
376144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  movq(top_operand, object);
3762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
37653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::AllocateHeapNumber(Register result,
37663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                        Register scratch,
37673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                        Label* gc_required) {
37683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Allocate heap number in new space.
37693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  AllocateInNewSpace(HeapNumber::kSize,
37703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                     result,
37713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                     scratch,
37723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                     no_reg,
37733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                     gc_required,
37743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                     TAG_OBJECT);
37753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
37763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Set the map.
37773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  LoadRoot(kScratchRegister, Heap::kHeapNumberMapRootIndex);
37783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
37793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
37803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
37813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3782e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::AllocateTwoByteString(Register result,
3783e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                           Register length,
3784e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                           Register scratch1,
3785e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                           Register scratch2,
3786e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                           Register scratch3,
3787e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                           Label* gc_required) {
3788e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Calculate the number of bytes needed for the characters in the string while
3789e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // observing object alignment.
37906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const int kHeaderAlignment = SeqTwoByteString::kHeaderSize &
37916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               kObjectAlignmentMask;
3792e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(kShortSize == 2);
3793e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // scratch1 = length * 2 + kObjectAlignmentMask.
37946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  lea(scratch1, Operand(length, length, times_1, kObjectAlignmentMask +
37956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                kHeaderAlignment));
3796e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  and_(scratch1, Immediate(~kObjectAlignmentMask));
37976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (kHeaderAlignment > 0) {
37986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    subq(scratch1, Immediate(kHeaderAlignment));
37996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3800e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3801e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Allocate two byte string in new space.
3802e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  AllocateInNewSpace(SeqTwoByteString::kHeaderSize,
3803e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     times_1,
3804e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch1,
3805e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     result,
3806e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch2,
3807e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch3,
3808e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     gc_required,
3809e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     TAG_OBJECT);
3810e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3811e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Set the map, length and hash field.
3812e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LoadRoot(kScratchRegister, Heap::kStringMapRootIndex);
3813e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
38146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Integer32ToSmi(scratch1, length);
38156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  movq(FieldOperand(result, String::kLengthOffset), scratch1);
38167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  movq(FieldOperand(result, String::kHashFieldOffset),
3817e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke       Immediate(String::kEmptyHashField));
3818e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3819e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3820e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3821e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::AllocateAsciiString(Register result,
3822e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                         Register length,
3823e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                         Register scratch1,
3824e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                         Register scratch2,
3825e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                         Register scratch3,
3826e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                         Label* gc_required) {
3827e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Calculate the number of bytes needed for the characters in the string while
3828e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // observing object alignment.
38296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const int kHeaderAlignment = SeqAsciiString::kHeaderSize &
38306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               kObjectAlignmentMask;
3831e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movl(scratch1, length);
3832e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(kCharSize == 1);
38336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  addq(scratch1, Immediate(kObjectAlignmentMask + kHeaderAlignment));
3834e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  and_(scratch1, Immediate(~kObjectAlignmentMask));
38356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (kHeaderAlignment > 0) {
38366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    subq(scratch1, Immediate(kHeaderAlignment));
38376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3838e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
38393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Allocate ASCII string in new space.
3840e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  AllocateInNewSpace(SeqAsciiString::kHeaderSize,
3841e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     times_1,
3842e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch1,
3843e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     result,
3844e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch2,
3845e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch3,
3846e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     gc_required,
3847e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     TAG_OBJECT);
3848e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3849e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Set the map, length and hash field.
3850e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LoadRoot(kScratchRegister, Heap::kAsciiStringMapRootIndex);
3851e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
38526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Integer32ToSmi(scratch1, length);
38536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  movq(FieldOperand(result, String::kLengthOffset), scratch1);
38547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  movq(FieldOperand(result, String::kHashFieldOffset),
3855e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke       Immediate(String::kEmptyHashField));
3856e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3857e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3858e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3859589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid MacroAssembler::AllocateTwoByteConsString(Register result,
3860e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                        Register scratch1,
3861e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                        Register scratch2,
3862e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                        Label* gc_required) {
3863e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Allocate heap number in new space.
3864e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  AllocateInNewSpace(ConsString::kSize,
3865e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     result,
3866e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch1,
3867e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch2,
3868e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     gc_required,
3869e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     TAG_OBJECT);
3870e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3871e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Set the map. The other fields are left uninitialized.
3872e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LoadRoot(kScratchRegister, Heap::kConsStringMapRootIndex);
3873e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
3874e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3875e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3876e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3877e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::AllocateAsciiConsString(Register result,
3878e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                             Register scratch1,
3879e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                             Register scratch2,
3880e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                             Label* gc_required) {
3881e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Allocate heap number in new space.
3882e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  AllocateInNewSpace(ConsString::kSize,
3883e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     result,
3884e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch1,
3885e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch2,
3886e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     gc_required,
3887e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     TAG_OBJECT);
3888e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3889e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Set the map. The other fields are left uninitialized.
3890e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LoadRoot(kScratchRegister, Heap::kConsAsciiStringMapRootIndex);
3891e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
3892e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3893e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3894e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3895589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid MacroAssembler::AllocateTwoByteSlicedString(Register result,
3896589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                          Register scratch1,
3897589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                          Register scratch2,
3898589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                          Label* gc_required) {
3899589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Allocate heap number in new space.
3900589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  AllocateInNewSpace(SlicedString::kSize,
3901589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                     result,
3902589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                     scratch1,
3903589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                     scratch2,
3904589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                     gc_required,
3905589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                     TAG_OBJECT);
3906589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
3907589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Set the map. The other fields are left uninitialized.
3908589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  LoadRoot(kScratchRegister, Heap::kSlicedStringMapRootIndex);
3909589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
3910589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
3911589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
3912589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
3913589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid MacroAssembler::AllocateAsciiSlicedString(Register result,
3914589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                               Register scratch1,
3915589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                               Register scratch2,
3916589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                               Label* gc_required) {
3917589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Allocate heap number in new space.
3918589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  AllocateInNewSpace(SlicedString::kSize,
3919589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                     result,
3920589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                     scratch1,
3921589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                     scratch2,
3922589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                     gc_required,
3923589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                     TAG_OBJECT);
3924589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
3925589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Set the map. The other fields are left uninitialized.
3926589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  LoadRoot(kScratchRegister, Heap::kSlicedAsciiStringMapRootIndex);
3927589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
3928589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
3929589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
3930589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
393144f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Copy memory, byte-by-byte, from source to destination.  Not optimized for
393244f0eee88ff00398ff7f715fab053374d808c90dSteve Block// long or aligned copies.  The contents of scratch and length are destroyed.
393344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Destination is incremented by length, source, length and scratch are
393444f0eee88ff00398ff7f715fab053374d808c90dSteve Block// clobbered.
393544f0eee88ff00398ff7f715fab053374d808c90dSteve Block// A simpler loop is faster on small copies, but slower on large ones.
393644f0eee88ff00398ff7f715fab053374d808c90dSteve Block// The cld() instruction must have been emitted, to set the direction flag(),
393744f0eee88ff00398ff7f715fab053374d808c90dSteve Block// before calling this function.
393844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CopyBytes(Register destination,
393944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               Register source,
394044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               Register length,
394144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               int min_length,
394244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               Register scratch) {
394344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(min_length >= 0);
394444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (FLAG_debug_code) {
394544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    cmpl(length, Immediate(min_length));
394644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Assert(greater_equal, "Invalid min_length");
394744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
394844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label loop, done, short_string, short_loop;
394944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
395044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const int kLongStringLimit = 20;
395144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (min_length <= kLongStringLimit) {
395244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    cmpl(length, Immediate(kLongStringLimit));
395344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    j(less_equal, &short_string);
395444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
395544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
395644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(source.is(rsi));
395744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(destination.is(rdi));
395844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(length.is(rcx));
395944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
396044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Because source is 8-byte aligned in our uses of this function,
396144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // we keep source aligned for the rep movs operation by copying the odd bytes
396244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // at the end of the ranges.
396344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  movq(scratch, length);
396444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  shrl(length, Immediate(3));
396544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  repmovsq();
396644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Move remaining bytes of length.
396744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  andl(scratch, Immediate(0x7));
396844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  movq(length, Operand(source, scratch, times_1, -8));
396944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  movq(Operand(destination, scratch, times_1, -8), length);
397044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  addq(destination, scratch);
397144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
397244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (min_length <= kLongStringLimit) {
397344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    jmp(&done);
397444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
397544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    bind(&short_string);
397644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (min_length == 0) {
397744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      testl(length, length);
397844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      j(zero, &done);
397944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
398044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    lea(scratch, Operand(destination, length, times_1, 0));
398144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
398244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    bind(&short_loop);
398344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    movb(length, Operand(source, 0));
398444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    movb(Operand(destination, 0), length);
398544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    incq(source);
398644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    incq(destination);
398744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    cmpq(destination, scratch);
398844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    j(not_equal, &short_loop);
398944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
399044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    bind(&done);
399144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
399244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
399344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
399444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
39953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::InitializeFieldsWithFiller(Register start_offset,
39963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Register end_offset,
39973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Register filler) {
39983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label loop, entry;
39993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  jmp(&entry);
40003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&loop);
40013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movq(Operand(start_offset, 0), filler);
40023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  addq(start_offset, Immediate(kPointerSize));
40033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&entry);
40043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmpq(start_offset, end_offset);
40053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(less, &loop);
40063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
40073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4009d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::LoadContext(Register dst, int context_chain_length) {
4010d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (context_chain_length > 0) {
4011d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Move up the chain of contexts to the context containing the slot.
40123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    movq(dst, Operand(rsi, Context::SlotOffset(Context::PREVIOUS_INDEX)));
4013d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    for (int i = 1; i < context_chain_length; i++) {
40143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      movq(dst, Operand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX)));
4015d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
4016e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
4017e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Slot is in the current function context.  Move it into the
4018e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // destination register in case we store into it (the write barrier
4019e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // cannot be allowed to destroy the context in rsi).
4020e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    movq(dst, rsi);
4021e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
4022e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
40233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // We should not have found a with context by walking the context
40243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // chain (i.e., the static scope chain and runtime context chain do
40253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // not agree).  A variable occurring in such a scope should have
40263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // slot type LOOKUP and not CONTEXT.
402744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
40283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    CompareRoot(FieldOperand(dst, HeapObject::kMapOffset),
40293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                Heap::kWithContextMapRootIndex);
40303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Check(not_equal, "Variable resolved to with context.");
4031d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
4032d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
4033d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
40343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::LoadTransitionedArrayMapConditional(
40363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ElementsKind expected_kind,
40373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ElementsKind transitioned_kind,
40383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register map_in_out,
40393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch,
40403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* no_map_match) {
40413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load the global or builtins object from the current context.
40423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movq(scratch, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
40433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movq(scratch, FieldOperand(scratch, GlobalObject::kGlobalContextOffset));
40443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check that the function's map is the same as the expected cached map.
40463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int expected_index =
40473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Context::GetContextMapIndexFromElementsKind(expected_kind);
40483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmpq(map_in_out, Operand(scratch, Context::SlotOffset(expected_index)));
40493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_equal, no_map_match);
40503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Use the transitioned cached map.
40523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int trans_index =
40533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Context::GetContextMapIndexFromElementsKind(transitioned_kind);
40543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movq(map_in_out, Operand(scratch, Context::SlotOffset(trans_index)));
40553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
40563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::LoadInitialArrayMap(
40593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register function_in, Register scratch, Register map_out) {
40603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!function_in.is(map_out));
40613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
40623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movq(map_out, FieldOperand(function_in,
40633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             JSFunction::kPrototypeOrInitialMapOffset));
40643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!FLAG_smi_only_arrays) {
40653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS,
40663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        FAST_ELEMENTS,
40673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        map_out,
40683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        scratch,
40693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        &done);
40703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
40713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&done);
40723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
40733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
407444f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef _WIN64
407544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic const int kRegisterPassedArguments = 4;
407644f0eee88ff00398ff7f715fab053374d808c90dSteve Block#else
407744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic const int kRegisterPassedArguments = 6;
407844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
40797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
4080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid MacroAssembler::LoadGlobalFunction(int index, Register function) {
4081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Load the global or builtins object from the current context.
4082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  movq(function, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
4083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Load the global context from the global or builtins object.
4084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  movq(function, FieldOperand(function, GlobalObject::kGlobalContextOffset));
4085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Load the function from the global context.
4086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  movq(function, Operand(function, Context::SlotOffset(index)));
4087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
4091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  Register map) {
4092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Load the initial map.  The global functions all have initial maps.
4093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  movq(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
409444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
4095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Label ok, fail;
4096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CheckMap(map, isolate()->factory()->meta_map(), &fail, DO_SMI_CHECK);
4097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    jmp(&ok);
4098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    bind(&fail);
4099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Abort("Global functions must have initial map");
4100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    bind(&ok);
4101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
41054515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkeint MacroAssembler::ArgumentStackSlotsForCFunctionCall(int num_arguments) {
41067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // On Windows 64 stack slots are reserved by the caller for all arguments
41077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // including the ones passed in registers, and space is always allocated for
41087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // the four register arguments even if the function takes fewer than four
41097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // arguments.
41107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // On AMD64 ABI (Linux/Mac) the first six arguments are passed in registers
41117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // and the caller does not reserve stack slots for them.
41124515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  ASSERT(num_arguments >= 0);
41134515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke#ifdef _WIN64
411444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const int kMinimumStackSlots = kRegisterPassedArguments;
41157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (num_arguments < kMinimumStackSlots) return kMinimumStackSlots;
41167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  return num_arguments;
41174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke#else
41187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (num_arguments < kRegisterPassedArguments) return 0;
41197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  return num_arguments - kRegisterPassedArguments;
41204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke#endif
41214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
41224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
41237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
41244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid MacroAssembler::PrepareCallCFunction(int num_arguments) {
41254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  int frame_alignment = OS::ActivationFrameAlignment();
41264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  ASSERT(frame_alignment != 0);
41274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  ASSERT(num_arguments >= 0);
412844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
41294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // Make stack end at alignment and allocate space for arguments and old rsp.
41304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  movq(kScratchRegister, rsp);
41314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  ASSERT(IsPowerOf2(frame_alignment));
41324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  int argument_slots_on_stack =
41334515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      ArgumentStackSlotsForCFunctionCall(num_arguments);
41344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  subq(rsp, Immediate((argument_slots_on_stack + 1) * kPointerSize));
41354515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  and_(rsp, Immediate(-frame_alignment));
41364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  movq(Operand(rsp, argument_slots_on_stack * kPointerSize), kScratchRegister);
41374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
41384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
41394515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
41404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid MacroAssembler::CallCFunction(ExternalReference function,
41414515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                                   int num_arguments) {
414244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(rax, function);
41434515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  CallCFunction(rax, num_arguments);
41444515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
41454515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
41464515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
41474515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid MacroAssembler::CallCFunction(Register function, int num_arguments) {
41483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(has_frame());
41496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check stack alignment.
415044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
41516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CheckStackAlignment();
41526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
41536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
41544515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  call(function);
41554515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  ASSERT(OS::ActivationFrameAlignment() != 0);
41564515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  ASSERT(num_arguments >= 0);
41574515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  int argument_slots_on_stack =
41584515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      ArgumentStackSlotsForCFunctionCall(num_arguments);
41594515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  movq(rsp, Operand(rsp, argument_slots_on_stack * kPointerSize));
41604515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
41614515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
4162d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
41633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool AreAliased(Register r1, Register r2, Register r3, Register r4) {
41643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (r1.is(r2)) return true;
41653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (r1.is(r3)) return true;
41663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (r1.is(r4)) return true;
41673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (r2.is(r3)) return true;
41683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (r2.is(r4)) return true;
41693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (r3.is(r4)) return true;
41703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return false;
41713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
41723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCodePatcher::CodePatcher(byte* address, int size)
41758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    : address_(address),
41768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      size_(size),
41778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      masm_(Isolate::Current(), address, size + Assembler::kGap) {
4178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a new macro assembler pointing to the address of the code to patch.
4179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The size is adjusted with kGap on order for the assembler to generate size
4180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // bytes of instructions without failing with buffer size constraints.
4181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
4182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCodePatcher::~CodePatcher() {
4186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Indicate that code has changed.
4187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CPU::FlushICache(address_, size_);
4188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the code was patched as expected.
4190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(masm_.pc_ == address_ + size_);
4191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
4192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
41943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckPageFlag(
41963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register object,
41973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch,
41983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int mask,
41993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Condition cc,
42003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* condition_met,
42013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label::Distance condition_met_distance) {
42023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(cc == zero || cc == not_zero);
42033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (scratch.is(object)) {
42043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    and_(scratch, Immediate(~Page::kPageAlignmentMask));
42053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
42063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    movq(scratch, Immediate(~Page::kPageAlignmentMask));
42073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    and_(scratch, object);
42083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
42093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (mask < (1 << kBitsPerByte)) {
42103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    testb(Operand(scratch, MemoryChunk::kFlagsOffset),
42113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Immediate(static_cast<uint8_t>(mask)));
42123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
42133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    testl(Operand(scratch, MemoryChunk::kFlagsOffset), Immediate(mask));
42143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
42153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(cc, condition_met, condition_met_distance);
42163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
42173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::JumpIfBlack(Register object,
42203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register bitmap_scratch,
42213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register mask_scratch,
42223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Label* on_black,
42233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Label::Distance on_black_distance) {
42243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!AreAliased(object, bitmap_scratch, mask_scratch, rcx));
42253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GetMarkBits(object, bitmap_scratch, mask_scratch);
42263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0);
42283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The mask_scratch register contains a 1 at the position of the first bit
42293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // and a 0 at all other positions, including the position of the second bit.
42303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movq(rcx, mask_scratch);
42313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Make rcx into a mask that covers both marking bits using the operation
42323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // rcx = mask | (mask << 1).
42333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lea(rcx, Operand(mask_scratch, mask_scratch, times_2, 0));
42343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Note that we are using a 4-byte aligned 8-byte load.
42353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(rcx, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
42363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmpq(mask_scratch, rcx);
42373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(equal, on_black, on_black_distance);
42383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
42393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Detect some, but not all, common pointer-free objects.  This is used by the
42423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// incremental write barrier which doesn't care about oddballs (they are always
42433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// marked black immediately so this code is not hit).
42443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::JumpIfDataObject(
42453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register value,
42463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch,
42473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* not_data_object,
42483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label::Distance not_data_object_distance) {
42493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label is_data_object;
42503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movq(scratch, FieldOperand(value, HeapObject::kMapOffset));
42513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompareRoot(scratch, Heap::kHeapNumberMapRootIndex);
42523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(equal, &is_data_object, Label::kNear);
42533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1);
42543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(kNotStringTag == 0x80 && kIsNotStringMask == 0x80);
42553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If it's a string and it's not a cons string then it's an object containing
42563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // no GC pointers.
42573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  testb(FieldOperand(scratch, Map::kInstanceTypeOffset),
42583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Immediate(kIsIndirectStringMask | kIsNotStringMask));
42593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_zero, not_data_object, not_data_object_distance);
42603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&is_data_object);
42613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
42623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::GetMarkBits(Register addr_reg,
42653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register bitmap_reg,
42663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register mask_reg) {
42673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!AreAliased(addr_reg, bitmap_reg, mask_reg, rcx));
42683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movq(bitmap_reg, addr_reg);
42693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Sign extended 32 bit immediate.
42703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(bitmap_reg, Immediate(~Page::kPageAlignmentMask));
42713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movq(rcx, addr_reg);
42723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int shift =
42733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Bitmap::kBitsPerCellLog2 + kPointerSizeLog2 - Bitmap::kBytesPerCellLog2;
42743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  shrl(rcx, Immediate(shift));
42753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(rcx,
42763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       Immediate((Page::kPageAlignmentMask >> shift) &
42773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 ~(Bitmap::kBytesPerCell - 1)));
42783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  addq(bitmap_reg, rcx);
42803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movq(rcx, addr_reg);
42813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  shrl(rcx, Immediate(kPointerSizeLog2));
42823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(rcx, Immediate((1 << Bitmap::kBitsPerCellLog2) - 1));
42833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movl(mask_reg, Immediate(1));
42843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  shl_cl(mask_reg);
42853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
42863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::EnsureNotWhite(
42893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register value,
42903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register bitmap_scratch,
42913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register mask_scratch,
42923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* value_is_white_and_not_data,
42933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label::Distance distance) {
42943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!AreAliased(value, bitmap_scratch, mask_scratch, rcx));
42953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GetMarkBits(value, bitmap_scratch, mask_scratch);
42963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If the value is black or grey we don't need to do anything.
42983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(strcmp(Marking::kWhiteBitPattern, "00") == 0);
42993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0);
43003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(strcmp(Marking::kGreyBitPattern, "11") == 0);
43013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(strcmp(Marking::kImpossibleBitPattern, "01") == 0);
43023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
43043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Since both black and grey have a 1 in the first position and white does
43063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // not have a 1 there we only need to check one bit.
43073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  testq(Operand(bitmap_scratch, MemoryChunk::kHeaderSize), mask_scratch);
43083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_zero, &done, Label::kNear);
43093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_debug_code) {
43113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check for impossible bit pattern.
43123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label ok;
43133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    push(mask_scratch);
43143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // shl.  May overflow making the check conservative.
43153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    addq(mask_scratch, mask_scratch);
43163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    testq(Operand(bitmap_scratch, MemoryChunk::kHeaderSize), mask_scratch);
43173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(zero, &ok, Label::kNear);
43183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int3();
43193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&ok);
43203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    pop(mask_scratch);
43213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
43223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Value is white.  We check whether it is data that doesn't need scanning.
43243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Currently only checks for HeapNumber and non-cons strings.
43253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register map = rcx;  // Holds map while checking type.
43263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register length = rcx;  // Holds length of object after checking type.
43273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label not_heap_number;
43283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label is_data_object;
43293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for heap-number
43313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movq(map, FieldOperand(value, HeapObject::kMapOffset));
43323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompareRoot(map, Heap::kHeapNumberMapRootIndex);
43333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_equal, &not_heap_number, Label::kNear);
43343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movq(length, Immediate(HeapNumber::kSize));
43353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  jmp(&is_data_object, Label::kNear);
43363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&not_heap_number);
43383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for strings.
43393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1);
43403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(kNotStringTag == 0x80 && kIsNotStringMask == 0x80);
43413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If it's a string and it's not a cons string then it's an object containing
43423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // no GC pointers.
43433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register instance_type = rcx;
43443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movzxbl(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
43453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  testb(instance_type, Immediate(kIsIndirectStringMask | kIsNotStringMask));
43463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_zero, value_is_white_and_not_data);
43473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // It's a non-indirect (non-cons and non-slice) string.
43483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If it's external, the length is just ExternalString::kSize.
43493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Otherwise it's String::kHeaderSize + string->length() * (1 or 2).
43503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label not_external;
43513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // External strings are the only ones with the kExternalStringTag bit
43523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // set.
43533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT_EQ(0, kSeqStringTag & kExternalStringTag);
43543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT_EQ(0, kConsStringTag & kExternalStringTag);
43553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  testb(instance_type, Immediate(kExternalStringTag));
43563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(zero, &not_external, Label::kNear);
43573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movq(length, Immediate(ExternalString::kSize));
43583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  jmp(&is_data_object, Label::kNear);
43593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&not_external);
43613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Sequential string, either ASCII or UC16.
43623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(kAsciiStringTag == 0x04);
43633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(length, Immediate(kStringEncodingMask));
43643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  xor_(length, Immediate(kStringEncodingMask));
43653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  addq(length, Immediate(0x04));
43663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Value now either 4 (if ASCII) or 8 (if UC16), i.e. char-size shifted by 2.
43673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  imul(length, FieldOperand(value, String::kLengthOffset));
43683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  shr(length, Immediate(2 + kSmiTagSize + kSmiShiftSize));
43693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  addq(length, Immediate(SeqString::kHeaderSize + kObjectAlignmentMask));
43703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(length, Immediate(~kObjectAlignmentMask));
43713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&is_data_object);
43733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Value is a data object, and it is white.  Mark it black.  Since we know
43743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // that the object is white we can make it black by flipping one bit.
43753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  or_(Operand(bitmap_scratch, MemoryChunk::kHeaderSize), mask_scratch);
43763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(bitmap_scratch, Immediate(~Page::kPageAlignmentMask));
43783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  addl(Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset), length);
43793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&done);
43813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
43823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckEnumCache(Register null_value, Label* call_runtime) {
43853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label next;
43863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register empty_fixed_array_value = r8;
43873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex);
43883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register empty_descriptor_array_value = r9;
43893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LoadRoot(empty_descriptor_array_value,
43903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              Heap::kEmptyDescriptorArrayRootIndex);
43913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movq(rcx, rax);
43923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&next);
43933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check that there are no elements.  Register rcx contains the
43953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // current JS object we've reached through the prototype chain.
43963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmpq(empty_fixed_array_value,
43973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       FieldOperand(rcx, JSObject::kElementsOffset));
43983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_equal, call_runtime);
43993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check that instance descriptors are not empty so that we can
44013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // check for an enum cache.  Leave the map in rbx for the subsequent
44023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // prototype load.
44033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movq(rbx, FieldOperand(rcx, HeapObject::kMapOffset));
44043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movq(rdx, FieldOperand(rbx, Map::kInstanceDescriptorsOrBitField3Offset));
44053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpIfSmi(rdx, call_runtime);
44063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check that there is an enum cache in the non-empty instance
44083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // descriptors (rdx).  This is the case if the next enumeration
44093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // index field does not contain a smi.
44103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movq(rdx, FieldOperand(rdx, DescriptorArray::kEnumerationIndexOffset));
44113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpIfSmi(rdx, call_runtime);
44123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // For all objects but the receiver, check that the cache is empty.
44143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label check_prototype;
44153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmpq(rcx, rax);
44163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(equal, &check_prototype, Label::kNear);
44173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movq(rdx, FieldOperand(rdx, DescriptorArray::kEnumCacheBridgeCacheOffset));
44183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmpq(rdx, empty_fixed_array_value);
44193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_equal, call_runtime);
44203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load the prototype from the map and loop if non-null.
44223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&check_prototype);
44233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movq(rcx, FieldOperand(rbx, Map::kPrototypeOffset));
44243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmpq(rcx, null_value);
44253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_equal, &next);
44263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
44273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
4430f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
4431f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_X64
4432