macro-assembler-x64.cc revision 69a99ed0b2b2ef69d393c371b03db3a98aaf880e
1e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Copyright 2011 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),
478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      root_array_available_(true) {
488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (isolate() != NULL) {
498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    code_object_ = Handle<Object>(isolate()->heap()->undefined_value(),
508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                  isolate());
518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
5244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
5344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic intptr_t RootRegisterDelta(ExternalReference other, Isolate* isolate) {
5644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Address roots_register_value = kRootRegisterBias +
5744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      reinterpret_cast<Address>(isolate->heap()->roots_address());
5844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  intptr_t delta = other.address() - roots_register_value;
5944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return delta;
6044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
6144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6344f0eee88ff00398ff7f715fab053374d808c90dSteve BlockOperand MacroAssembler::ExternalOperand(ExternalReference target,
6444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                        Register scratch) {
6544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (root_array_available_ && !Serializer::enabled()) {
6644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    intptr_t delta = RootRegisterDelta(target, isolate());
6744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (is_int32(delta)) {
6844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Serializer::TooLateToEnableNow();
6944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      return Operand(kRootRegister, static_cast<int32_t>(delta));
7044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
7144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
7244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  movq(scratch, target);
7344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return Operand(scratch, 0);
7444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
7544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
7644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
7744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::Load(Register destination, ExternalReference source) {
7844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (root_array_available_ && !Serializer::enabled()) {
7944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    intptr_t delta = RootRegisterDelta(source, isolate());
8044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (is_int32(delta)) {
8144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Serializer::TooLateToEnableNow();
8244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      movq(destination, Operand(kRootRegister, static_cast<int32_t>(delta)));
8344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      return;
8444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
8544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
8644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Safe code.
8744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (destination.is(rax)) {
8844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    load_rax(source);
8944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
9044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    movq(kScratchRegister, source);
9144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    movq(destination, Operand(kScratchRegister, 0));
9244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
9344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
9444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
9544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
9644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::Store(ExternalReference destination, Register source) {
9744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (root_array_available_ && !Serializer::enabled()) {
9844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    intptr_t delta = RootRegisterDelta(destination, isolate());
9944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (is_int32(delta)) {
10044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Serializer::TooLateToEnableNow();
10144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      movq(Operand(kRootRegister, static_cast<int32_t>(delta)), source);
10244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      return;
10344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
10444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
10544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Safe code.
10644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (source.is(rax)) {
10744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    store_rax(destination);
10844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
10944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    movq(kScratchRegister, destination);
11044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    movq(Operand(kScratchRegister, 0), source);
11144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
11244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
11344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
11444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
11544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::LoadAddress(Register destination,
11644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                 ExternalReference source) {
11744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (root_array_available_ && !Serializer::enabled()) {
11844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    intptr_t delta = RootRegisterDelta(source, isolate());
11944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (is_int32(delta)) {
12044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Serializer::TooLateToEnableNow();
12144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      lea(destination, Operand(kRootRegister, static_cast<int32_t>(delta)));
12244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      return;
12344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
12444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
12544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Safe code.
12644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  movq(destination, source);
12744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
12844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
12944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
13044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint MacroAssembler::LoadAddressSize(ExternalReference source) {
13144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (root_array_available_ && !Serializer::enabled()) {
13244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // This calculation depends on the internals of LoadAddress.
13344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // It's correctness is ensured by the asserts in the Call
13444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // instruction below.
13544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    intptr_t delta = RootRegisterDelta(source, isolate());
13644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (is_int32(delta)) {
13744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Serializer::TooLateToEnableNow();
13844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Operand is lea(scratch, Operand(kRootRegister, delta));
13944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Opcodes : REX.W 8D ModRM Disp8/Disp32  - 4 or 7.
14044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      int size = 4;
14144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (!is_int8(static_cast<int32_t>(delta))) {
14244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        size += 3;  // Need full four-byte displacement in lea.
14344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
14444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      return size;
14544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
14644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
14744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Size of movq(destination, src);
14844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return 10;
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index) {
15344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(root_array_available_);
154e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  movq(destination, Operand(kRootRegister,
155e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                            (index << kPointerSizeLog2) - kRootRegisterBias));
156e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
157e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
158e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
159e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::LoadRootIndexed(Register destination,
160e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                     Register variable_offset,
161e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                     int fixed_offset) {
16244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(root_array_available_);
163e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  movq(destination,
164e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch       Operand(kRootRegister,
165e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch               variable_offset, times_pointer_size,
166e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch               (fixed_offset << kPointerSizeLog2) - kRootRegisterBias));
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsenvoid MacroAssembler::StoreRoot(Register source, Heap::RootListIndex index) {
17144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(root_array_available_);
172e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  movq(Operand(kRootRegister, (index << kPointerSizeLog2) - kRootRegisterBias),
173e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch       source);
17425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen}
17525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
17625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::PushRoot(Heap::RootListIndex index) {
17844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(root_array_available_);
179e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  push(Operand(kRootRegister, (index << kPointerSizeLog2) - kRootRegisterBias));
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) {
18444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(root_array_available_);
185e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  cmpq(with, Operand(kRootRegister,
186e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                     (index << kPointerSizeLog2) - kRootRegisterBias));
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::CompareRoot(const Operand& with,
1911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                 Heap::RootListIndex index) {
19244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(root_array_available_);
1931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(!with.AddressUsesRegister(kScratchRegister));
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LoadRoot(kScratchRegister, index);
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cmpq(with, kScratchRegister);
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1996ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::RecordWriteHelper(Register object,
2006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                       Register addr,
2016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                       Register scratch) {
20244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
2036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Check that the object is not in new space.
204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label not_in_new_space;
205257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    InNewSpace(object, scratch, not_equal, &not_in_new_space, Label::kNear);
2066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Abort("new-space object passed to RecordWriteHelper");
2076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    bind(&not_in_new_space);
2086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compute the page start address from the heap object pointer, and reuse
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the 'object' register for it.
2127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  and_(object, Immediate(~Page::kPageAlignmentMask));
2137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Compute number of region covering addr. See Page::GetRegionNumberForAddress
2157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // method for more details.
2167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  shrl(addr, Immediate(Page::kRegionSizeLog2));
2179dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  andl(addr, Immediate(Page::kPageAlignmentMask >> Page::kRegionSizeLog2));
2187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Set dirty mark for region.
2207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  bts(Operand(object, Page::kDirtyFlagOffset), addr);
2217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::InNewSpace(Register object,
225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Register scratch,
226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Condition cc,
227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Label* branch,
228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Label::Distance near_jump) {
229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (Serializer::enabled()) {
230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Can't do arithmetic on external references if it might get serialized.
231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // The mask isn't really an address.  We load it as an external reference in
232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // case the size of the new space is different between the snapshot maker
233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // and the running system.
234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (scratch.is(object)) {
235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      movq(kScratchRegister, ExternalReference::new_space_mask(isolate()));
236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      and_(scratch, kScratchRegister);
237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      movq(scratch, ExternalReference::new_space_mask(isolate()));
239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      and_(scratch, object);
240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(kScratchRegister, ExternalReference::new_space_start(isolate()));
242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    cmpq(scratch, kScratchRegister);
243257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(cc, branch, near_jump);
244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(is_int32(static_cast<int64_t>(HEAP->NewSpaceMask())));
246257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    intptr_t new_space_start =
247257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        reinterpret_cast<intptr_t>(HEAP->NewSpaceStart());
248257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(kScratchRegister, -new_space_start, RelocInfo::NONE);
249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (scratch.is(object)) {
250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      addq(scratch, kScratchRegister);
251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      lea(scratch, Operand(object, kScratchRegister, times_1, 0));
253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    and_(scratch, Immediate(static_cast<int32_t>(HEAP->NewSpaceMask())));
255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(cc, branch, near_jump);
256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::RecordWrite(Register object,
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 int offset,
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Register value,
2639dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                 Register index) {
2644515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // The compiled code assumes that record write doesn't change the
2654515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // context register, so we check that none of the clobbered
2664515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // registers are rsi.
2679dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  ASSERT(!object.is(rsi) && !value.is(rsi) && !index.is(rsi));
2684515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
2697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // First, check if a write barrier is even needed. The tests below
27044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // catch stores of smis and stores into the young generation.
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label done;
2723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  JumpIfSmi(value, &done);
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2749dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  RecordWriteNonSmi(object, offset, value, index);
2753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bind(&done);
2764515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
2774515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // Clobber all input registers when running with the debug-code flag
2784515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // turned on to provoke errors. This clobbering repeats the
2794515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // clobbering done inside RecordWriteNonSmi but it's necessary to
2804515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // avoid having the fast case for smis leave the registers
2814515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // unchanged.
28244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
2836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
2846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
2859dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    movq(index, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
2864515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
2873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
2883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2908defd9ff6930b4e24729971a61cf7469daf119beSteve Blockvoid MacroAssembler::RecordWrite(Register object,
2918defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                 Register address,
2928defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                 Register value) {
2938defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // The compiled code assumes that record write doesn't change the
2948defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // context register, so we check that none of the clobbered
295e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // registers are rsi.
2968defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ASSERT(!object.is(rsi) && !value.is(rsi) && !address.is(rsi));
2978defd9ff6930b4e24729971a61cf7469daf119beSteve Block
2988defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // First, check if a write barrier is even needed. The tests below
29944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // catch stores of smis and stores into the young generation.
3008defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Label done;
3018defd9ff6930b4e24729971a61cf7469daf119beSteve Block  JumpIfSmi(value, &done);
3028defd9ff6930b4e24729971a61cf7469daf119beSteve Block
3038defd9ff6930b4e24729971a61cf7469daf119beSteve Block  InNewSpace(object, value, equal, &done);
3048defd9ff6930b4e24729971a61cf7469daf119beSteve Block
3058defd9ff6930b4e24729971a61cf7469daf119beSteve Block  RecordWriteHelper(object, address, value);
3068defd9ff6930b4e24729971a61cf7469daf119beSteve Block
3078defd9ff6930b4e24729971a61cf7469daf119beSteve Block  bind(&done);
3088defd9ff6930b4e24729971a61cf7469daf119beSteve Block
3098defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Clobber all input registers when running with the debug-code flag
3108defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // turned on to provoke errors.
31144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
3128defd9ff6930b4e24729971a61cf7469daf119beSteve Block    movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
3138defd9ff6930b4e24729971a61cf7469daf119beSteve Block    movq(address, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
3148defd9ff6930b4e24729971a61cf7469daf119beSteve Block    movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
3158defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
3168defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
3178defd9ff6930b4e24729971a61cf7469daf119beSteve Block
3188defd9ff6930b4e24729971a61cf7469daf119beSteve Block
3193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::RecordWriteNonSmi(Register object,
3203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                       int offset,
3213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                       Register scratch,
3229dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                       Register index) {
3233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label done;
3244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
32544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label okay;
327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    JumpIfNotSmi(object, &okay, Label::kNear);
3284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    Abort("MacroAssembler::RecordWriteNonSmi cannot deal with smis");
3294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    bind(&okay);
3309dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
3319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    if (offset == 0) {
3329dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // index must be int32.
3339dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      Register tmp = index.is(rax) ? rbx : rax;
3349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      push(tmp);
3359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      movl(tmp, index);
3369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      cmpq(tmp, index);
3379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      Check(equal, "Index register for RecordWrite must be untagged int32.");
3389dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      pop(tmp);
3399dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    }
3404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
3414515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
3427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Test that the object address is not in the new space. We cannot
3437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // update page dirty marks for new space pages.
3446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  InNewSpace(object, scratch, equal, &done);
3456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // The offset is relative to a tagged or untagged HeapObject pointer,
3476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // so either offset or offset + kHeapObjectTag must be a
3486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // multiple of kPointerSize.
3496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(IsAligned(offset, kPointerSize) ||
3506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block         IsAligned(offset + kHeapObjectTag, kPointerSize));
3516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3529dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  Register dst = index;
3537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (offset != 0) {
3547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    lea(dst, Operand(object, offset));
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
3567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // array access: calculate the destination address in the same manner as
3577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // KeyedStoreIC::GenerateGeneric.
3587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    lea(dst, FieldOperand(object,
3599dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                          index,
3609dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                          times_pointer_size,
3617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                          FixedArray::kHeaderSize));
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  RecordWriteHelper(object, dst, scratch);
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&done);
3664515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
3674515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // Clobber all input registers when running with the debug-code flag
3684515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // turned on to provoke errors.
36944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
3706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
3716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    movq(scratch, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
3729dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    movq(index, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
3736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
3756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Assert(Condition cc, const char* msg) {
37744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) Check(cc, msg);
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
381756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid MacroAssembler::AssertFastElements(Register elements) {
38244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
383257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label ok;
384756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
385756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                Heap::kFixedArrayMapRootIndex);
386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(equal, &ok, Label::kNear);
387756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
3883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                Heap::kFixedDoubleArrayMapRootIndex);
3893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    j(equal, &ok, Label::kNear);
3903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
391756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                Heap::kFixedCOWArrayMapRootIndex);
392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(equal, &ok, Label::kNear);
393756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Abort("JSObject with fast elements map has slow elements");
394756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    bind(&ok);
395756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
396756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
397756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
398756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Check(Condition cc, const char* msg) {
400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label L;
401257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(cc, &L, Label::kNear);
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Abort(msg);
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // will not return here
404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&L);
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4086ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::CheckStackAlignment() {
4096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int frame_alignment = OS::ActivationFrameAlignment();
4106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int frame_alignment_mask = frame_alignment - 1;
4116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (frame_alignment > kPointerSize) {
4126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(IsPowerOf2(frame_alignment));
413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label alignment_as_expected;
4146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    testq(rsp, Immediate(frame_alignment_mask));
415257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(zero, &alignment_as_expected, Label::kNear);
4166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Abort if stack is not aligned.
4176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int3();
4186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    bind(&alignment_as_expected);
4196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
4216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::NegativeZeroTest(Register result,
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register op,
425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Label* then_label) {
426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label ok;
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  testl(result, result);
428257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_zero, &ok, Label::kNear);
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  testl(op, op);
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(sign, then_label);
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&ok);
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Abort(const char* msg) {
436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // We want to pass the msg string like a smi to avoid GC
437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // problems, however msg is not guaranteed to be aligned
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // properly. Instead, we pass an aligned pointer that is
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // a proper v8 smi, but also pass the alignment difference
440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // from the real pointer as a smi.
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  intptr_t p1 = reinterpret_cast<intptr_t>(msg);
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  intptr_t p0 = (p1 & ~kSmiTagMask) + kSmiTag;
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Note: p0 might not be a valid Smi *value*, but it has a valid Smi tag.
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(reinterpret_cast<Object*>(p0)->IsSmi());
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (msg != NULL) {
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RecordComment("Abort message: ");
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RecordComment(msg);
449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
451d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Disable stub call restrictions to always allow calls to abort.
452086aeeaae12517475c22695a200be45495516549Ben Murdoch  AllowStubCallsScope allow_scope(this, true);
453d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(rax);
455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister, p0, RelocInfo::NONE);
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(kScratchRegister);
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister,
458d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block       reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(p1 - p0))),
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       RelocInfo::NONE);
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(kScratchRegister);
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CallRuntime(Runtime::kAbort, 2);
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // will not return here
463d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int3();
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::CallStub(CodeStub* stub, unsigned ast_id) {
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(allow_stub_calls());  // calls are not allowed in some stubs
469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id);
470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4735913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* MacroAssembler::TryCallStub(CodeStub* stub) {
474bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ASSERT(allow_stub_calls());  // Calls are not allowed in some stubs.
4755913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  MaybeObject* result = stub->TryGetCode();
476bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (!result->IsFailure()) {
4775913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    call(Handle<Code>(Code::cast(result->ToObjectUnchecked())),
4785913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck         RelocInfo::CODE_TARGET);
479bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
480bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  return result;
481bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
482bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
483bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
484e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::TailCallStub(CodeStub* stub) {
4858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  ASSERT(allow_stub_calls());  // Calls are not allowed in some stubs.
486e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Jump(stub->GetCode(), RelocInfo::CODE_TARGET);
487e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
488e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
489e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4905913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* MacroAssembler::TryTailCallStub(CodeStub* stub) {
491bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ASSERT(allow_stub_calls());  // Calls are not allowed in some stubs.
4925913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  MaybeObject* result = stub->TryGetCode();
493bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (!result->IsFailure()) {
4945913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    jmp(Handle<Code>(Code::cast(result->ToObjectUnchecked())),
4955913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        RelocInfo::CODE_TARGET);
496bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
497bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  return result;
498bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
499bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
500bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::StubReturn(int argc) {
502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(argc >= 1 && generating_stub());
503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ret((argc - 1) * kPointerSize);
504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::IllegalOperation(int num_arguments) {
508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (num_arguments > 0) {
509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    addq(rsp, Immediate(num_arguments * kPointerSize));
510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LoadRoot(rax, Heap::kUndefinedValueRootIndex);
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
51580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::IndexFromHash(Register hash, Register index) {
51680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // The assert checks that the constants for the maximum number of digits
51780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // for an array index cached in the hash field and the number of bits
51880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // reserved for it does not conflict.
51980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
52080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen         (1 << String::kArrayIndexValueBits));
52180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // We want the smi-tagged index in key. Even if we subsequently go to
52280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // the slow case, converting the key to a smi is always valid.
52380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // key: string key
52480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // hash: key's hash field, including its array index value.
52580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  and_(hash, Immediate(String::kArrayIndexValueMask));
52680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  shr(hash, Immediate(String::kHashShift));
52780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Here we actually clobber the key which will be used if calling into
52880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // runtime later. However as the new key is the numeric value of a string key
52980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // there is no difference in using either key.
53080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Integer32ToSmi(index, hash);
53180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
53280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
53380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CallRuntime(Runtime::FunctionId id, int num_arguments) {
535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CallRuntime(Runtime::FunctionForId(id), num_arguments);
536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::CallRuntimeSaveDoubles(Runtime::FunctionId id) {
54044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const Runtime::Function* function = Runtime::FunctionForId(id);
5411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Set(rax, function->nargs);
54244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(rbx, ExternalReference(function, isolate()));
5431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CEntryStub ces(1);
5441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ces.SaveDoubles();
5451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CallStub(&ces);
5461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
5471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5495913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* MacroAssembler::TryCallRuntime(Runtime::FunctionId id,
5505913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                            int num_arguments) {
551bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  return TryCallRuntime(Runtime::FunctionForId(id), num_arguments);
552bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
553bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
554bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
55544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CallRuntime(const Runtime::Function* f,
55644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                 int num_arguments) {
557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the expected number of arguments of the runtime function is
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // constant, we check that the actual number of arguments match the
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // expectation.
560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (f->nargs >= 0 && f->nargs != num_arguments) {
561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    IllegalOperation(num_arguments);
562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5654515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // TODO(1236192): Most runtime routines don't need the number of
5664515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // arguments passed in because it is constant. At some point we
5674515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // should remove this need and make the runtime routine entry code
5684515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // smarter.
5698defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Set(rax, num_arguments);
57044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(rbx, ExternalReference(f, isolate()));
5714515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  CEntryStub ces(f->result_size);
5724515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  CallStub(&ces);
573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
57644f0eee88ff00398ff7f715fab053374d808c90dSteve BlockMaybeObject* MacroAssembler::TryCallRuntime(const Runtime::Function* f,
5775913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                            int num_arguments) {
578bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (f->nargs >= 0 && f->nargs != num_arguments) {
579bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    IllegalOperation(num_arguments);
580bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    // Since we did not call the stub, there was no allocation failure.
581bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    // Return some non-failure object.
58244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return HEAP->undefined_value();
583bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
584bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
585bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // TODO(1236192): Most runtime routines don't need the number of
586bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // arguments passed in because it is constant. At some point we
587bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // should remove this need and make the runtime routine entry code
588bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // smarter.
589bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Set(rax, num_arguments);
59044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(rbx, ExternalReference(f, isolate()));
591bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  CEntryStub ces(f->result_size);
592bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  return TryCallStub(&ces);
593bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
594bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
595bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
596402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::CallExternalReference(const ExternalReference& ext,
597402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                           int num_arguments) {
5988defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Set(rax, num_arguments);
59944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(rbx, ext);
600402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
601402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CEntryStub stub(1);
602402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CallStub(&stub);
603402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
604402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
605402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6066ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::TailCallExternalReference(const ExternalReference& ext,
6076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                               int num_arguments,
6086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                               int result_size) {
609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0] : return address
611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[8] : argument num_arguments - 1
612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  ...
613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[8 * num_arguments] : argument 0 (receiver)
614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // TODO(1236192): Most runtime routines don't need the number of
617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // arguments passed in because it is constant. At some point we
618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // should remove this need and make the runtime routine entry code
619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // smarter.
6208defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Set(rax, num_arguments);
6216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  JumpToExternalReference(ext, result_size);
622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) WangMaybeObject* MacroAssembler::TryTailCallExternalReference(
6268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    const ExternalReference& ext, int num_arguments, int result_size) {
6278a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // ----------- S t a t e -------------
6288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- rsp[0] : return address
6298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- rsp[8] : argument num_arguments - 1
6308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  ...
6318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- rsp[8 * num_arguments] : argument 0 (receiver)
6328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // -----------------------------------
6338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
6348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // TODO(1236192): Most runtime routines don't need the number of
6358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // arguments passed in because it is constant. At some point we
6368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // should remove this need and make the runtime routine entry code
6378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // smarter.
6388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Set(rax, num_arguments);
6398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  return TryJumpToExternalReference(ext, result_size);
6408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
6418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
6428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
6436ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::TailCallRuntime(Runtime::FunctionId fid,
6446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                     int num_arguments,
6456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                     int result_size) {
64644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  TailCallExternalReference(ExternalReference(fid, isolate()),
64744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                            num_arguments,
64844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                            result_size);
6496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
6506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) WangMaybeObject* MacroAssembler::TryTailCallRuntime(Runtime::FunctionId fid,
6538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                                int num_arguments,
6548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                                int result_size) {
65544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return TryTailCallExternalReference(ExternalReference(fid, isolate()),
6568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                      num_arguments,
6578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                      result_size);
6588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
6598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
6608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
661bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochstatic int Offset(ExternalReference ref0, ExternalReference ref1) {
662bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  int64_t offset = (ref0.address() - ref1.address());
663bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Check that fits into int.
664bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ASSERT(static_cast<int>(offset) == offset);
665bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  return static_cast<int>(offset);
666bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
667bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
668bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
6698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid MacroAssembler::PrepareCallApiFunction(int arg_stack_space) {
6708a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang#ifdef _WIN64
6718a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // We need to prepare a slot for result handle on stack and put
6728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // a pointer to it into 1st arg register.
6738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  EnterApiExitFrame(arg_stack_space + 1);
6748a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
6758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // rcx must be used to pass the pointer to the return value slot.
6768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  lea(rcx, StackSpaceOperand(arg_stack_space));
6778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang#else
6788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  EnterApiExitFrame(arg_stack_space);
6798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang#endif
680bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
681bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
682bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
6838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) WangMaybeObject* MacroAssembler::TryCallApiFunctionAndReturn(
6848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    ApiFunction* function, int stack_space) {
6855913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Label empty_result;
6865913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Label prologue;
6875913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Label promote_scheduled_exception;
6885913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Label delete_allocated_handles;
6895913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Label leave_exit_frame;
690bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Label write_back;
691bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Factory* factory = isolate()->factory();
6935913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  ExternalReference next_address =
6945913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      ExternalReference::handle_scope_next_address();
6955913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  const int kNextOffset = 0;
6965913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  const int kLimitOffset = Offset(
6975913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      ExternalReference::handle_scope_limit_address(),
6985913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      next_address);
6995913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  const int kLevelOffset = Offset(
7005913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      ExternalReference::handle_scope_level_address(),
7015913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      next_address);
7025913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  ExternalReference scheduled_exception_address =
70344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::scheduled_exception_address(isolate());
7045913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck
7055913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  // Allocate HandleScope in callee-save registers.
7065913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Register prev_next_address_reg = r14;
7075913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Register prev_limit_reg = rbx;
70844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register base_reg = r15;
7095913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  movq(base_reg, next_address);
7105913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  movq(prev_next_address_reg, Operand(base_reg, kNextOffset));
7115913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  movq(prev_limit_reg, Operand(base_reg, kLimitOffset));
7125913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  addl(Operand(base_reg, kLevelOffset), Immediate(1));
7135913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  // Call the api function!
7145913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  movq(rax,
7155913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck       reinterpret_cast<int64_t>(function->address()),
7165913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck       RelocInfo::RUNTIME_ENTRY);
7175913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  call(rax);
718bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
7195913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck#ifdef _WIN64
7205913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  // rax keeps a pointer to v8::Handle, unpack it.
7215913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  movq(rax, Operand(rax, 0));
7225913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck#endif
7235913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  // Check if the result handle holds 0.
7245913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  testq(rax, rax);
7255913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  j(zero, &empty_result);
7265913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  // It was non-zero.  Dereference to get the result value.
7275913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  movq(rax, Operand(rax, 0));
7285913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  bind(&prologue);
7295913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck
7305913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  // No more valid handles (the result handle was the last one). Restore
7315913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  // previous handle scope.
7325913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  subl(Operand(base_reg, kLevelOffset), Immediate(1));
7335913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  movq(Operand(base_reg, kNextOffset), prev_next_address_reg);
7345913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  cmpq(prev_limit_reg, Operand(base_reg, kLimitOffset));
7355913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  j(not_equal, &delete_allocated_handles);
7365913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  bind(&leave_exit_frame);
7375913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck
7385913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  // Check if the function scheduled an exception.
7395913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  movq(rsi, scheduled_exception_address);
740257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Cmp(Operand(rsi, 0), factory->the_hole_value());
7415913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  j(not_equal, &promote_scheduled_exception);
7425913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck
7438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LeaveApiExitFrame();
7448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  ret(stack_space * kPointerSize);
745bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
7465913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  bind(&promote_scheduled_exception);
7478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  MaybeObject* result = TryTailCallRuntime(Runtime::kPromoteScheduledException,
7488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                           0, 1);
7498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  if (result->IsFailure()) {
7508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    return result;
7518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  }
752bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
7535913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  bind(&empty_result);
7545913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  // It was zero; the result is undefined.
755257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Move(rax, factory->undefined_value());
7565913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  jmp(&prologue);
757bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
7585913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  // HandleScope limit has changed. Delete allocated extensions.
7595913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  bind(&delete_allocated_handles);
7605913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  movq(Operand(base_reg, kLimitOffset), prev_limit_reg);
7615913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  movq(prev_limit_reg, rax);
76244f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef _WIN64
76344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(rcx, ExternalReference::isolate_address());
76444f0eee88ff00398ff7f715fab053374d808c90dSteve Block#else
76544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(rdi, ExternalReference::isolate_address());
76644f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
76744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(rax,
76844f0eee88ff00398ff7f715fab053374d808c90dSteve Block              ExternalReference::delete_handle_scope_extensions(isolate()));
7695913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  call(rax);
7705913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  movq(rax, prev_limit_reg);
7715913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  jmp(&leave_exit_frame);
7728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
7738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  return result;
774bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
775bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
776bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
7776ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::JumpToExternalReference(const ExternalReference& ext,
7786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                             int result_size) {
779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set the entry point and jump to the C entry runtime stub.
78044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(rbx, ext);
781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CEntryStub ces(result_size);
7823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  jmp(ces.GetCode(), RelocInfo::CODE_TARGET);
783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) WangMaybeObject* MacroAssembler::TryJumpToExternalReference(
7878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    const ExternalReference& ext, int result_size) {
7888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Set the entry point and jump to the C entry runtime stub.
78944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(rbx, ext);
7908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CEntryStub ces(result_size);
7918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  return TryTailCallStub(&ces);
7928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
7938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
7948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
795e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
796e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   InvokeFlag flag,
797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   const CallWrapper& call_wrapper) {
798402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Calls are not allowed in some stubs.
799402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ASSERT(flag == JUMP_FUNCTION || allow_stub_calls());
800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
801402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Rely on the assertion to check that the number of provided
802402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // arguments match the expected number of arguments. Fake a
803402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // parameter count to avoid emitting code to do the check.
804402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ParameterCount expected(0);
805402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GetBuiltinEntry(rdx, id);
806257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  InvokeCode(rdx, expected, expected, flag, call_wrapper, CALL_AS_METHOD);
807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
809402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
810791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockvoid MacroAssembler::GetBuiltinFunction(Register target,
811791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                                        Builtins::JavaScript id) {
8126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Load the builtins object into target register.
8136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  movq(target, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
8146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  movq(target, FieldOperand(target, GlobalObject::kBuiltinsOffset));
815791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  movq(target, FieldOperand(target,
816791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                            JSBuiltinsObject::OffsetOfFunctionWithId(id)));
817791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block}
8186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
820791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockvoid MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
821791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  ASSERT(!target.is(rdi));
822791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  // Load the JavaScript builtin function from the builtins object.
823791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  GetBuiltinFunction(rdi, id);
824791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  movq(target, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Set(Register dst, int64_t x) {
829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (x == 0) {
8308defd9ff6930b4e24729971a61cf7469daf119beSteve Block    xorl(dst, dst);
831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (is_uint32(x)) {
832d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    movl(dst, Immediate(static_cast<uint32_t>(x)));
8338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } else if (is_int32(x)) {
8348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    movq(dst, Immediate(static_cast<int32_t>(x)));
835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(dst, x, RelocInfo::NONE);
837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Set(const Operand& dst, int64_t x) {
8419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  if (is_int32(x)) {
842d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    movq(dst, Immediate(static_cast<int32_t>(x)));
843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
8448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Set(kScratchRegister, x);
845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(dst, kScratchRegister);
846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------
850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Smi tagging, untagging and tag detection.
851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8528defd9ff6930b4e24729971a61cf7469daf119beSteve BlockRegister MacroAssembler::GetSmiConstant(Smi* source) {
8538defd9ff6930b4e24729971a61cf7469daf119beSteve Block  int value = source->value();
8548defd9ff6930b4e24729971a61cf7469daf119beSteve Block  if (value == 0) {
8558defd9ff6930b4e24729971a61cf7469daf119beSteve Block    xorl(kScratchRegister, kScratchRegister);
8568defd9ff6930b4e24729971a61cf7469daf119beSteve Block    return kScratchRegister;
8578defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
8588defd9ff6930b4e24729971a61cf7469daf119beSteve Block  if (value == 1) {
8598defd9ff6930b4e24729971a61cf7469daf119beSteve Block    return kSmiConstantRegister;
8608defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
8618defd9ff6930b4e24729971a61cf7469daf119beSteve Block  LoadSmiConstant(kScratchRegister, source);
8628defd9ff6930b4e24729971a61cf7469daf119beSteve Block  return kScratchRegister;
8638defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
8648defd9ff6930b4e24729971a61cf7469daf119beSteve Block
8658defd9ff6930b4e24729971a61cf7469daf119beSteve Blockvoid MacroAssembler::LoadSmiConstant(Register dst, Smi* source) {
86644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
8678defd9ff6930b4e24729971a61cf7469daf119beSteve Block    movq(dst,
8688defd9ff6930b4e24729971a61cf7469daf119beSteve Block         reinterpret_cast<uint64_t>(Smi::FromInt(kSmiConstantRegisterValue)),
8698defd9ff6930b4e24729971a61cf7469daf119beSteve Block         RelocInfo::NONE);
8708defd9ff6930b4e24729971a61cf7469daf119beSteve Block    cmpq(dst, kSmiConstantRegister);
8718defd9ff6930b4e24729971a61cf7469daf119beSteve Block    if (allow_stub_calls()) {
8728defd9ff6930b4e24729971a61cf7469daf119beSteve Block      Assert(equal, "Uninitialized kSmiConstantRegister");
8738defd9ff6930b4e24729971a61cf7469daf119beSteve Block    } else {
874257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Label ok;
875257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      j(equal, &ok, Label::kNear);
8768defd9ff6930b4e24729971a61cf7469daf119beSteve Block      int3();
8778defd9ff6930b4e24729971a61cf7469daf119beSteve Block      bind(&ok);
8788defd9ff6930b4e24729971a61cf7469daf119beSteve Block    }
8798defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
88044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int value = source->value();
88144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (value == 0) {
8828defd9ff6930b4e24729971a61cf7469daf119beSteve Block    xorl(dst, dst);
8838defd9ff6930b4e24729971a61cf7469daf119beSteve Block    return;
8848defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
8858defd9ff6930b4e24729971a61cf7469daf119beSteve Block  bool negative = value < 0;
8868defd9ff6930b4e24729971a61cf7469daf119beSteve Block  unsigned int uvalue = negative ? -value : value;
8878defd9ff6930b4e24729971a61cf7469daf119beSteve Block
8888defd9ff6930b4e24729971a61cf7469daf119beSteve Block  switch (uvalue) {
8898defd9ff6930b4e24729971a61cf7469daf119beSteve Block    case 9:
8908defd9ff6930b4e24729971a61cf7469daf119beSteve Block      lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_8, 0));
8918defd9ff6930b4e24729971a61cf7469daf119beSteve Block      break;
8928defd9ff6930b4e24729971a61cf7469daf119beSteve Block    case 8:
8938defd9ff6930b4e24729971a61cf7469daf119beSteve Block      xorl(dst, dst);
8948defd9ff6930b4e24729971a61cf7469daf119beSteve Block      lea(dst, Operand(dst, kSmiConstantRegister, times_8, 0));
8958defd9ff6930b4e24729971a61cf7469daf119beSteve Block      break;
8968defd9ff6930b4e24729971a61cf7469daf119beSteve Block    case 4:
8978defd9ff6930b4e24729971a61cf7469daf119beSteve Block      xorl(dst, dst);
8988defd9ff6930b4e24729971a61cf7469daf119beSteve Block      lea(dst, Operand(dst, kSmiConstantRegister, times_4, 0));
8998defd9ff6930b4e24729971a61cf7469daf119beSteve Block      break;
9008defd9ff6930b4e24729971a61cf7469daf119beSteve Block    case 5:
9018defd9ff6930b4e24729971a61cf7469daf119beSteve Block      lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_4, 0));
9028defd9ff6930b4e24729971a61cf7469daf119beSteve Block      break;
9038defd9ff6930b4e24729971a61cf7469daf119beSteve Block    case 3:
9048defd9ff6930b4e24729971a61cf7469daf119beSteve Block      lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_2, 0));
9058defd9ff6930b4e24729971a61cf7469daf119beSteve Block      break;
9068defd9ff6930b4e24729971a61cf7469daf119beSteve Block    case 2:
9078defd9ff6930b4e24729971a61cf7469daf119beSteve Block      lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_1, 0));
9088defd9ff6930b4e24729971a61cf7469daf119beSteve Block      break;
9098defd9ff6930b4e24729971a61cf7469daf119beSteve Block    case 1:
9108defd9ff6930b4e24729971a61cf7469daf119beSteve Block      movq(dst, kSmiConstantRegister);
9118defd9ff6930b4e24729971a61cf7469daf119beSteve Block      break;
9128defd9ff6930b4e24729971a61cf7469daf119beSteve Block    case 0:
9138defd9ff6930b4e24729971a61cf7469daf119beSteve Block      UNREACHABLE();
9148defd9ff6930b4e24729971a61cf7469daf119beSteve Block      return;
9158defd9ff6930b4e24729971a61cf7469daf119beSteve Block    default:
9168defd9ff6930b4e24729971a61cf7469daf119beSteve Block      movq(dst, reinterpret_cast<uint64_t>(source), RelocInfo::NONE);
9178defd9ff6930b4e24729971a61cf7469daf119beSteve Block      return;
9188defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
9198defd9ff6930b4e24729971a61cf7469daf119beSteve Block  if (negative) {
9208defd9ff6930b4e24729971a61cf7469daf119beSteve Block    neg(dst);
9218defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
9228defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
9238defd9ff6930b4e24729971a61cf7469daf119beSteve Block
924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9250d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::Integer32ToSmi(Register dst, Register src) {
92669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!dst.is(src)) {
928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movl(dst, src);
929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
9303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  shl(dst, Immediate(kSmiShift));
931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::Integer32ToSmiField(const Operand& dst, Register src) {
93544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
9369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    testb(dst, Immediate(0x01));
937257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label ok;
938257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(zero, &ok, Label::kNear);
9399dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    if (allow_stub_calls()) {
9409dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      Abort("Integer32ToSmiField writing to non-smi location");
9419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    } else {
9429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      int3();
9439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    }
9449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    bind(&ok);
9459dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
9469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  ASSERT(kSmiShift % kBitsPerByte == 0);
9479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  movl(Operand(dst, kSmiShift / kBitsPerByte), src);
9489dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
9499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
9509dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
9513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::Integer64PlusConstantToSmi(Register dst,
9523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                Register src,
9533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                int constant) {
9543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (dst.is(src)) {
95544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    addl(dst, Immediate(constant));
9563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
95744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    leal(dst, Operand(src, constant));
9583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
9593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  shl(dst, Immediate(kSmiShift));
960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiToInteger32(Register dst, Register src) {
96469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!dst.is(src)) {
9663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src);
967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
9683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  shr(dst, Immediate(kSmiShift));
969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid MacroAssembler::SmiToInteger32(Register dst, const Operand& src) {
9737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  movl(dst, Operand(src, kSmiShift / kBitsPerByte));
9747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
9757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
9767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiToInteger64(Register dst, Register src) {
97869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
9793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src)) {
9803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src);
981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
9823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  sar(dst, Immediate(kSmiShift));
983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9869dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::SmiToInteger64(Register dst, const Operand& src) {
9879dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  movsxlq(dst, Operand(src, kSmiShift / kBitsPerByte));
9889dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
9899dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
9909dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
9913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiTest(Register src) {
9923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  testq(src, src);
993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
99644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::SmiCompare(Register smi1, Register smi2) {
99744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
99844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    AbortIfNotSmi(smi1);
99944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    AbortIfNotSmi(smi2);
100044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
100144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  cmpq(smi1, smi2);
1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(Register dst, Smi* src) {
100644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
100744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    AbortIfNotSmi(dst);
100844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
100944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Cmp(dst, src);
101044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
101144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
101244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
101344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::Cmp(Register dst, Smi* src) {
10143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!dst.is(kScratchRegister));
10153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (src->value() == 0) {
10163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    testq(dst, dst);
10173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
1018756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Register constant_reg = GetSmiConstant(src);
1019756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    cmpq(dst, constant_reg);
1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1024f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid MacroAssembler::SmiCompare(Register dst, const Operand& src) {
102544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
102644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    AbortIfNotSmi(dst);
102744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    AbortIfNotSmi(src);
102844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
10296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  cmpq(dst, src);
10306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
10316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(const Operand& dst, Register src) {
103444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
103544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    AbortIfNotSmi(dst);
103644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    AbortIfNotSmi(src);
103744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
10383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  cmpq(dst, src);
1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(const Operand& dst, Smi* src) {
104344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
104444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    AbortIfNotSmi(dst);
104544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
10467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  cmpl(Operand(dst, kSmiShift / kBitsPerByte), Immediate(src->value()));
1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
105044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::Cmp(const Operand& dst, Smi* src) {
105144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // The Operand cannot use the smi register.
105244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register smi_reg = GetSmiConstant(src);
105344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!dst.AddressUsesRegister(smi_reg));
105444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  cmpq(dst, smi_reg);
105544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
105644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
105744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
10589dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::SmiCompareInteger32(const Operand& dst, Register src) {
10599dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  cmpl(Operand(dst, kSmiShift / kBitsPerByte), src);
10609dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
10619dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
10629dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
10633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::PositiveSmiTimesPowerOfTwoToInteger64(Register dst,
10643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                           Register src,
10653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                           int power) {
10663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(power >= 0);
10673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(power < 64);
10683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (power == 0) {
10693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    SmiToInteger64(dst, src);
10703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    return;
10713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
10723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src)) {
10733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src);
10743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
10753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (power < kSmiShift) {
10763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    sar(dst, Immediate(kSmiShift - power));
10773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (power > kSmiShift) {
10783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    shl(dst, Immediate(power - kSmiShift));
10793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid MacroAssembler::PositiveSmiDivPowerOfTwoToInteger32(Register dst,
10847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                                         Register src,
10857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                                         int power) {
10867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT((0 <= power) && (power < 32));
10877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (dst.is(src)) {
10887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    shr(dst, Immediate(power + kSmiShift));
10897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  } else {
10907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    UNIMPLEMENTED();  // Not used.
10917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
10927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
10937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
10947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1095257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiOrIfSmis(Register dst, Register src1, Register src2,
1096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Label* on_not_smis,
1097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Label::Distance near_jump) {
1098257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (dst.is(src1) || dst.is(src2)) {
1099257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(!src1.is(kScratchRegister));
1100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(!src2.is(kScratchRegister));
1101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(kScratchRegister, src1);
1102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    or_(kScratchRegister, src2);
1103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    JumpIfNotSmi(kScratchRegister, on_not_smis, near_jump);
1104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(dst, kScratchRegister);
1105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(dst, src1);
1107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    or_(dst, src2);
1108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    JumpIfNotSmi(dst, on_not_smis, near_jump);
1109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
11133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockCondition MacroAssembler::CheckSmi(Register src) {
111469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  testb(src, Immediate(kSmiTagMask));
11163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  return zero;
1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11201e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockCondition MacroAssembler::CheckSmi(const Operand& src) {
112169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
11221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  testb(src, Immediate(kSmiTagMask));
11231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return zero;
11241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
11251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
11261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1127f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochCondition MacroAssembler::CheckNonNegativeSmi(Register src) {
112869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
1129e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Test that both bits of the mask 0x8000000000000001 are zero.
11303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  movq(kScratchRegister, src);
11313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  rol(kScratchRegister, Immediate(1));
11328defd9ff6930b4e24729971a61cf7469daf119beSteve Block  testb(kScratchRegister, Immediate(3));
1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return zero;
1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCondition MacroAssembler::CheckBothSmi(Register first, Register second) {
1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (first.is(second)) {
1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return CheckSmi(first);
1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
114169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0 && kHeapObjectTag == 1 && kHeapObjectTagMask == 3);
11428defd9ff6930b4e24729971a61cf7469daf119beSteve Block  leal(kScratchRegister, Operand(first, second, times_1, 0));
11438defd9ff6930b4e24729971a61cf7469daf119beSteve Block  testb(kScratchRegister, Immediate(0x03));
11443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  return zero;
1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1148f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochCondition MacroAssembler::CheckBothNonNegativeSmi(Register first,
1149f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch                                                  Register second) {
1150d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (first.is(second)) {
1151f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    return CheckNonNegativeSmi(first);
1152d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
11538defd9ff6930b4e24729971a61cf7469daf119beSteve Block  movq(kScratchRegister, first);
11548defd9ff6930b4e24729971a61cf7469daf119beSteve Block  or_(kScratchRegister, second);
1155d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  rol(kScratchRegister, Immediate(1));
1156f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  testl(kScratchRegister, Immediate(3));
1157d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  return zero;
1158d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1159d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1160d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1161bb769b257e753aafcbd96767abb2abc645eaa20cBen MurdochCondition MacroAssembler::CheckEitherSmi(Register first,
1162bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                         Register second,
1163bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                         Register scratch) {
1164e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (first.is(second)) {
1165e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    return CheckSmi(first);
1166e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
1167bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (scratch.is(second)) {
1168bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    andl(scratch, first);
1169bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  } else {
1170bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    if (!scratch.is(first)) {
1171bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      movl(scratch, first);
1172bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    }
1173bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    andl(scratch, second);
1174bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
1175bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  testb(scratch, Immediate(kSmiTagMask));
1176e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  return zero;
1177e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1178e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1179e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCondition MacroAssembler::CheckIsMinSmi(Register src) {
11818defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ASSERT(!src.is(kScratchRegister));
11828defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // If we overflow by subtracting one, it's the minimal smi value.
11838defd9ff6930b4e24729971a61cf7469daf119beSteve Block  cmpq(src, kSmiConstantRegister);
11848defd9ff6930b4e24729971a61cf7469daf119beSteve Block  return overflow;
1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockCondition MacroAssembler::CheckInteger32ValidSmiValue(Register src) {
11893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // A 32-bit integer value can always be converted to a smi.
11903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  return always;
1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockCondition MacroAssembler::CheckUInteger32ValidSmiValue(Register src) {
11953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // An unsigned 32-bit integer value is valid as long as the high bit
11963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // is not set.
11978defd9ff6930b4e24729971a61cf7469daf119beSteve Block  testl(src, src);
11988defd9ff6930b4e24729971a61cf7469daf119beSteve Block  return positive;
1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::CheckSmiToIndicator(Register dst, Register src) {
12031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (dst.is(src)) {
12041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    andl(dst, Immediate(kSmiTagMask));
12051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
12061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    movl(dst, Immediate(kSmiTagMask));
12071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    andl(dst, src);
12081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
12091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
12101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
12111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
12121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::CheckSmiToIndicator(Register dst, const Operand& src) {
12131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (!(src.AddressUsesRegister(dst))) {
12141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    movl(dst, Immediate(kSmiTagMask));
12151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    andl(dst, src);
12161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
12171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    movl(dst, src);
12181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    andl(dst, Immediate(kSmiTagMask));
12191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
12201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
12211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
12221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1223257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfNotValidSmiValue(Register src,
1224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                            Label* on_invalid,
1225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                            Label::Distance near_jump) {
1226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition is_valid = CheckInteger32ValidSmiValue(src);
1227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(NegateCondition(is_valid), on_invalid, near_jump);
1228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfUIntNotValidSmiValue(Register src,
1232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                Label* on_invalid,
1233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                Label::Distance near_jump) {
1234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition is_valid = CheckUInteger32ValidSmiValue(src);
1235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(NegateCondition(is_valid), on_invalid, near_jump);
1236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfSmi(Register src,
1240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               Label* on_smi,
1241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               Label::Distance near_jump) {
1242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition smi = CheckSmi(src);
1243257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(smi, on_smi, near_jump);
1244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1246257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1247257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfNotSmi(Register src,
1248257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                  Label* on_not_smi,
1249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                  Label::Distance near_jump) {
1250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition smi = CheckSmi(src);
1251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(NegateCondition(smi), on_not_smi, near_jump);
1252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpUnlessNonNegativeSmi(
1256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register src, Label* on_not_smi_or_negative,
1257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label::Distance near_jump) {
1258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition non_negative_smi = CheckNonNegativeSmi(src);
1259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(NegateCondition(non_negative_smi), on_not_smi_or_negative, near_jump);
1260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfSmiEqualsConstant(Register src,
1264257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Smi* constant,
1265257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Label* on_equals,
1266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Label::Distance near_jump) {
1267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  SmiCompare(src, constant);
1268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(equal, on_equals, near_jump);
1269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfNotBothSmi(Register src1,
1273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                      Register src2,
1274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                      Label* on_not_both_smi,
1275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                      Label::Distance near_jump) {
1276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition both_smi = CheckBothSmi(src1, src2);
1277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(NegateCondition(both_smi), on_not_both_smi, near_jump);
1278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpUnlessBothNonNegativeSmi(Register src1,
1282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                  Register src2,
1283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                  Label* on_not_both_smi,
1284257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                  Label::Distance near_jump) {
1285257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition both_smi = CheckBothNonNegativeSmi(src1, src2);
1286257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(NegateCondition(both_smi), on_not_both_smi, near_jump);
1287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1288257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiTryAddConstant(Register dst,
1291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                       Register src,
1292257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                       Smi* constant,
1293257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                       Label* on_not_smi_result,
1294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                       Label::Distance near_jump) {
1295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Does not assume that src is a smi.
1296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT_EQ(static_cast<int>(1), static_cast<int>(kSmiTagMask));
129769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
1298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!dst.is(kScratchRegister));
1299257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src.is(kScratchRegister));
1300257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1301257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  JumpIfNotSmi(src, on_not_smi_result, near_jump);
1302257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register tmp = (dst.is(src) ? kScratchRegister : dst);
1303257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  LoadSmiConstant(tmp, constant);
1304257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  addq(tmp, src);
1305257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(overflow, on_not_smi_result, near_jump);
1306257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (dst.is(src)) {
1307257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(dst, tmp);
1308257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1309257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1310257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1311257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
13123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiAddConstant(Register dst, Register src, Smi* constant) {
13133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (constant->value() == 0) {
13143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (!dst.is(src)) {
13153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      movq(dst, src);
13163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
13178defd9ff6930b4e24729971a61cf7469daf119beSteve Block    return;
13183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (dst.is(src)) {
13193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    ASSERT(!dst.is(kScratchRegister));
13208defd9ff6930b4e24729971a61cf7469daf119beSteve Block    switch (constant->value()) {
13218defd9ff6930b4e24729971a61cf7469daf119beSteve Block      case 1:
13228defd9ff6930b4e24729971a61cf7469daf119beSteve Block        addq(dst, kSmiConstantRegister);
13238defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
13248defd9ff6930b4e24729971a61cf7469daf119beSteve Block      case 2:
13258defd9ff6930b4e24729971a61cf7469daf119beSteve Block        lea(dst, Operand(src, kSmiConstantRegister, times_2, 0));
13268defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
13278defd9ff6930b4e24729971a61cf7469daf119beSteve Block      case 4:
13288defd9ff6930b4e24729971a61cf7469daf119beSteve Block        lea(dst, Operand(src, kSmiConstantRegister, times_4, 0));
13298defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
13308defd9ff6930b4e24729971a61cf7469daf119beSteve Block      case 8:
13318defd9ff6930b4e24729971a61cf7469daf119beSteve Block        lea(dst, Operand(src, kSmiConstantRegister, times_8, 0));
13328defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
13338defd9ff6930b4e24729971a61cf7469daf119beSteve Block      default:
13348defd9ff6930b4e24729971a61cf7469daf119beSteve Block        Register constant_reg = GetSmiConstant(constant);
13358defd9ff6930b4e24729971a61cf7469daf119beSteve Block        addq(dst, constant_reg);
13368defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
13378defd9ff6930b4e24729971a61cf7469daf119beSteve Block    }
1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
13398defd9ff6930b4e24729971a61cf7469daf119beSteve Block    switch (constant->value()) {
13408defd9ff6930b4e24729971a61cf7469daf119beSteve Block      case 1:
13418defd9ff6930b4e24729971a61cf7469daf119beSteve Block        lea(dst, Operand(src, kSmiConstantRegister, times_1, 0));
13428defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
13438defd9ff6930b4e24729971a61cf7469daf119beSteve Block      case 2:
13448defd9ff6930b4e24729971a61cf7469daf119beSteve Block        lea(dst, Operand(src, kSmiConstantRegister, times_2, 0));
13458defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
13468defd9ff6930b4e24729971a61cf7469daf119beSteve Block      case 4:
13478defd9ff6930b4e24729971a61cf7469daf119beSteve Block        lea(dst, Operand(src, kSmiConstantRegister, times_4, 0));
13488defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
13498defd9ff6930b4e24729971a61cf7469daf119beSteve Block      case 8:
13508defd9ff6930b4e24729971a61cf7469daf119beSteve Block        lea(dst, Operand(src, kSmiConstantRegister, times_8, 0));
13518defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
13528defd9ff6930b4e24729971a61cf7469daf119beSteve Block      default:
13538defd9ff6930b4e24729971a61cf7469daf119beSteve Block        LoadSmiConstant(dst, constant);
13548defd9ff6930b4e24729971a61cf7469daf119beSteve Block        addq(dst, src);
13558defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
13568defd9ff6930b4e24729971a61cf7469daf119beSteve Block    }
1357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1361f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid MacroAssembler::SmiAddConstant(const Operand& dst, Smi* constant) {
1362f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (constant->value() != 0) {
13637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    addl(Operand(dst, kSmiShift / kBitsPerByte), Immediate(constant->value()));
1364f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1365f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1366f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1367f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1368257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiAddConstant(Register dst,
1369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Register src,
1370257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Smi* constant,
1371257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Label* on_not_smi_result,
1372257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Label::Distance near_jump) {
1373257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (constant->value() == 0) {
1374257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (!dst.is(src)) {
1375257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      movq(dst, src);
1376257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1377257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else if (dst.is(src)) {
1378257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(!dst.is(kScratchRegister));
1379257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1380257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    LoadSmiConstant(kScratchRegister, constant);
1381257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    addq(kScratchRegister, src);
1382257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(overflow, on_not_smi_result, near_jump);
1383257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(dst, kScratchRegister);
1384257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1385257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    LoadSmiConstant(dst, constant);
1386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    addq(dst, src);
1387257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(overflow, on_not_smi_result, near_jump);
1388257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
13923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiSubConstant(Register dst, Register src, Smi* constant) {
13933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (constant->value() == 0) {
1394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!dst.is(src)) {
13953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      movq(dst, src);
1396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
13973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (dst.is(src)) {
13983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    ASSERT(!dst.is(kScratchRegister));
13998defd9ff6930b4e24729971a61cf7469daf119beSteve Block    Register constant_reg = GetSmiConstant(constant);
14008defd9ff6930b4e24729971a61cf7469daf119beSteve Block    subq(dst, constant_reg);
14013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
14023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (constant->value() == Smi::kMinValue) {
14038defd9ff6930b4e24729971a61cf7469daf119beSteve Block      LoadSmiConstant(dst, constant);
14049dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // Adding and subtracting the min-value gives the same result, it only
14059dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // differs on the overflow bit, which we don't check here.
14069dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      addq(dst, src);
1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
14089dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // Subtract by adding the negation.
14098defd9ff6930b4e24729971a61cf7469daf119beSteve Block      LoadSmiConstant(dst, Smi::FromInt(-constant->value()));
14103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      addq(dst, src);
1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1416257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiSubConstant(Register dst,
1417257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Register src,
1418257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Smi* constant,
1419257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Label* on_not_smi_result,
1420257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Label::Distance near_jump) {
1421257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (constant->value() == 0) {
1422257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (!dst.is(src)) {
1423257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      movq(dst, src);
1424257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1425257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else if (dst.is(src)) {
1426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(!dst.is(kScratchRegister));
1427257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (constant->value() == Smi::kMinValue) {
1428257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Subtracting min-value from any non-negative value will overflow.
1429257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // We test the non-negativeness before doing the subtraction.
1430257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      testq(src, src);
1431257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      j(not_sign, on_not_smi_result, near_jump);
1432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      LoadSmiConstant(kScratchRegister, constant);
1433257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      subq(dst, kScratchRegister);
1434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
1435257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Subtract by adding the negation.
1436257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      LoadSmiConstant(kScratchRegister, Smi::FromInt(-constant->value()));
1437257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      addq(kScratchRegister, dst);
1438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      j(overflow, on_not_smi_result, near_jump);
1439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      movq(dst, kScratchRegister);
1440257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (constant->value() == Smi::kMinValue) {
1443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Subtracting min-value from any non-negative value will overflow.
1444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // We test the non-negativeness before doing the subtraction.
1445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      testq(src, src);
1446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      j(not_sign, on_not_smi_result, near_jump);
1447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      LoadSmiConstant(dst, constant);
1448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Adding and subtracting the min-value gives the same result, it only
1449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // differs on the overflow bit, which we don't check here.
1450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      addq(dst, src);
1451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
1452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Subtract by adding the negation.
1453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      LoadSmiConstant(dst, Smi::FromInt(-(constant->value())));
1454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      addq(dst, src);
1455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      j(overflow, on_not_smi_result, near_jump);
1456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1461257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiNeg(Register dst,
1462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src,
1463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label* on_smi_result,
1464257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label::Distance near_jump) {
1465257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (dst.is(src)) {
1466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(!dst.is(kScratchRegister));
1467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(kScratchRegister, src);
1468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    neg(dst);  // Low 32 bits are retained as zero by negation.
1469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Test if result is zero or Smi::kMinValue.
1470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    cmpq(dst, kScratchRegister);
1471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(not_equal, on_smi_result, near_jump);
1472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(src, kScratchRegister);
1473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(dst, src);
1475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    neg(dst);
1476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    cmpq(dst, src);
1477257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // If the result is zero or Smi::kMinValue, negation failed to create a smi.
1478257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(not_equal, on_smi_result, near_jump);
1479257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1480257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1481257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiAdd(Register dst,
1484257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src1,
1485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src2,
1486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label* on_not_smi_result,
1487257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label::Distance near_jump) {
1488257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT_NOT_NULL(on_not_smi_result);
1489257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!dst.is(src2));
1490257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (dst.is(src1)) {
1491257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(kScratchRegister, src1);
1492257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    addq(kScratchRegister, src2);
1493257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(overflow, on_not_smi_result, near_jump);
1494257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(dst, kScratchRegister);
1495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(dst, src1);
1497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    addq(dst, src2);
1498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(overflow, on_not_smi_result, near_jump);
1499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1500257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1501257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1502257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiAdd(Register dst,
1504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src1,
1505257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            const Operand& src2,
1506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label* on_not_smi_result,
1507257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label::Distance near_jump) {
1508257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT_NOT_NULL(on_not_smi_result);
1509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (dst.is(src1)) {
1510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(kScratchRegister, src1);
1511257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    addq(kScratchRegister, src2);
1512257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(overflow, on_not_smi_result, near_jump);
1513257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(dst, kScratchRegister);
1514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(!src2.AddressUsesRegister(dst));
1516257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(dst, src1);
1517257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    addq(dst, src2);
1518257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(overflow, on_not_smi_result, near_jump);
1519257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1520257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1521257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1522257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
15230d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::SmiAdd(Register dst,
15240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                            Register src1,
15250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                            Register src2) {
15260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // No overflow checking. Use only when it's known that
15270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // overflowing is impossible.
152844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!dst.is(src1)) {
1529257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (emit_debug_code()) {
1530257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      movq(kScratchRegister, src1);
1531257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      addq(kScratchRegister, src2);
1532257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Check(no_overflow, "Smi addition overflow");
1533257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    lea(dst, Operand(src1, src2, times_1, 0));
1535257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    addq(dst, src2);
1537257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Assert(no_overflow, "Smi addition overflow");
1538257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1539257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1540257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1542257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiSub(Register dst,
1543257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src1,
1544257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src2,
1545257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label* on_not_smi_result,
1546257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label::Distance near_jump) {
1547257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT_NOT_NULL(on_not_smi_result);
1548257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!dst.is(src2));
1549257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (dst.is(src1)) {
1550257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    cmpq(dst, src2);
1551257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(overflow, on_not_smi_result, near_jump);
1552257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    subq(dst, src2);
1553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1554053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block    movq(dst, src1);
1555257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    subq(dst, src2);
1556257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(overflow, on_not_smi_result, near_jump);
1557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15610d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::SmiSub(Register dst, Register src1, Register src2) {
15620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // No overflow checking. Use only when it's known that
15630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // overflowing is impossible (e.g., subtracting two positive smis).
15640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(!dst.is(src2));
156544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!dst.is(src1)) {
15660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    movq(dst, src1);
15673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
156844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  subq(dst, src2);
15690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Assert(no_overflow, "Smi subtraction overflow");
1570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15730d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::SmiSub(Register dst,
1574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register src1,
1575257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            const Operand& src2,
1576257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label* on_not_smi_result,
1577257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label::Distance near_jump) {
1578257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT_NOT_NULL(on_not_smi_result);
1579257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (dst.is(src1)) {
1580257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(kScratchRegister, src2);
1581257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    cmpq(src1, kScratchRegister);
1582257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(overflow, on_not_smi_result, near_jump);
1583257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    subq(src1, kScratchRegister);
1584257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(dst, src1);
1586257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    subq(dst, src2);
1587257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(overflow, on_not_smi_result, near_jump);
1588257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1589257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1590257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1591257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1592257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiSub(Register dst,
1593257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src1,
15940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                            const Operand& src2) {
15950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // No overflow checking. Use only when it's known that
15960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // overflowing is impossible (e.g., subtracting two positive smis).
159744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!dst.is(src1)) {
15980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    movq(dst, src1);
1599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
160044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  subq(dst, src2);
16010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Assert(no_overflow, "Smi subtraction overflow");
1602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiMul(Register dst,
1606257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src1,
1607257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src2,
1608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label* on_not_smi_result,
1609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label::Distance near_jump) {
1610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!dst.is(src2));
1611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!dst.is(kScratchRegister));
1612257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src1.is(kScratchRegister));
1613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src2.is(kScratchRegister));
1614257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (dst.is(src1)) {
1616257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label failure, zero_correct_result;
1617257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(kScratchRegister, src1);  // Create backup for later testing.
1618257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    SmiToInteger64(dst, src1);
1619257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    imul(dst, src2);
1620257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(overflow, &failure, Label::kNear);
1621257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1622257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Check for negative zero result.  If product is zero, and one
1623257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // argument is negative, go to slow case.
1624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label correct_result;
1625257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    testq(dst, dst);
1626257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(not_zero, &correct_result, Label::kNear);
1627257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1628257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(dst, kScratchRegister);
1629257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    xor_(dst, src2);
1630257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Result was positive zero.
1631257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(positive, &zero_correct_result, Label::kNear);
1632257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1633257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    bind(&failure);  // Reused failure exit, restores src1.
1634257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(src1, kScratchRegister);
1635257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    jmp(on_not_smi_result, near_jump);
1636257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1637257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    bind(&zero_correct_result);
1638257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Set(dst, 0);
1639257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1640257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    bind(&correct_result);
1641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1642257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    SmiToInteger64(dst, src1);
1643257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    imul(dst, src2);
1644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(overflow, on_not_smi_result, near_jump);
1645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Check for negative zero result.  If product is zero, and one
1646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // argument is negative, go to slow case.
1647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label correct_result;
1648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    testq(dst, dst);
1649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(not_zero, &correct_result, Label::kNear);
1650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // One of src1 and src2 is zero, the check whether the other is
1651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // negative.
1652257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(kScratchRegister, src1);
1653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    xor_(kScratchRegister, src2);
1654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(negative, on_not_smi_result, near_jump);
1655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    bind(&correct_result);
1656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiDiv(Register dst,
1661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src1,
1662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src2,
1663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label* on_not_smi_result,
1664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label::Distance near_jump) {
1665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src1.is(kScratchRegister));
1666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src2.is(kScratchRegister));
1667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!dst.is(kScratchRegister));
1668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src2.is(rax));
1669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src2.is(rdx));
1670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src1.is(rdx));
1671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check for 0 divisor (result is +/-Infinity).
1673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  testq(src2, src2);
1674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(zero, on_not_smi_result, near_jump);
1675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (src1.is(rax)) {
1677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(kScratchRegister, src1);
1678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  SmiToInteger32(rax, src1);
1680257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // We need to rule out dividing Smi::kMinValue by -1, since that would
1681257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // overflow in idiv and raise an exception.
1682257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // We combine this with negative zero test (negative zero only happens
1683257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // when dividing zero by a negative number).
1684257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // We overshoot a little and go to slow case if we divide min-value
1686257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // by any negative value, not just -1.
1687257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label safe_div;
1688257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  testl(rax, Immediate(0x7fffffff));
1689257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_zero, &safe_div, Label::kNear);
1690257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  testq(src2, src2);
1691257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (src1.is(rax)) {
1692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(positive, &safe_div, Label::kNear);
1693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(src1, kScratchRegister);
1694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    jmp(on_not_smi_result, near_jump);
1695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(negative, on_not_smi_result, near_jump);
1697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1698257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&safe_div);
1699257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  SmiToInteger32(src2, src2);
1701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Sign extend src1 into edx:eax.
1702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  cdq();
1703257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  idivl(src2);
1704257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Integer32ToSmi(src2, src2);
1705257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the remainder is zero.
1706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  testl(rdx, rdx);
1707257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (src1.is(rax)) {
1708257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label smi_result;
1709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(zero, &smi_result, Label::kNear);
1710257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(src1, kScratchRegister);
1711257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    jmp(on_not_smi_result, near_jump);
1712257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    bind(&smi_result);
1713257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1714257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(not_zero, on_not_smi_result, near_jump);
1715257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1716257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!dst.is(src1) && src1.is(rax)) {
1717257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(src1, kScratchRegister);
1718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Integer32ToSmi(dst, rax);
1720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiMod(Register dst,
1724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src1,
1725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src2,
1726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label* on_not_smi_result,
1727257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label::Distance near_jump) {
1728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!dst.is(kScratchRegister));
1729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src1.is(kScratchRegister));
1730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src2.is(kScratchRegister));
1731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src2.is(rax));
1732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src2.is(rdx));
1733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src1.is(rdx));
1734257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src1.is(src2));
1735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  testq(src2, src2);
1737257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(zero, on_not_smi_result, near_jump);
1738257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1739257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (src1.is(rax)) {
1740257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(kScratchRegister, src1);
1741257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1742257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  SmiToInteger32(rax, src1);
1743257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  SmiToInteger32(src2, src2);
1744257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1745257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Test for the edge case of dividing Smi::kMinValue by -1 (will overflow).
1746257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label safe_div;
1747257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  cmpl(rax, Immediate(Smi::kMinValue));
1748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_equal, &safe_div, Label::kNear);
1749257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  cmpl(src2, Immediate(-1));
1750257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_equal, &safe_div, Label::kNear);
1751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Retag inputs and go slow case.
1752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Integer32ToSmi(src2, src2);
1753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (src1.is(rax)) {
1754257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(src1, kScratchRegister);
1755257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1756257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  jmp(on_not_smi_result, near_jump);
1757257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&safe_div);
1758257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1759257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Sign extend eax into edx:eax.
1760257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  cdq();
1761257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  idivl(src2);
1762257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Restore smi tags on inputs.
1763257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Integer32ToSmi(src2, src2);
1764257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (src1.is(rax)) {
1765257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(src1, kScratchRegister);
1766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check for a negative zero result.  If the result is zero, and the
1768257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // dividend is negative, go slow to return a floating point negative zero.
1769257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label smi_result;
1770257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  testl(rdx, rdx);
1771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_zero, &smi_result, Label::kNear);
1772257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  testq(src1, src1);
1773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(negative, on_not_smi_result, near_jump);
1774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&smi_result);
1775257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Integer32ToSmi(dst, rdx);
1776257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1777257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1778257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiNot(Register dst, Register src) {
17803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!dst.is(kScratchRegister));
17813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!src.is(kScratchRegister));
17823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Set tag and padding bits before negating, so that they are zero afterwards.
17833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  movl(kScratchRegister, Immediate(~0));
1784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (dst.is(src)) {
17853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    xor_(dst, kScratchRegister);
1786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
17873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    lea(dst, Operand(src, kScratchRegister, times_1, 0));
1788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
17893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  not_(dst);
1790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiAnd(Register dst, Register src1, Register src2) {
17943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!dst.is(src2));
1795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!dst.is(src1)) {
17963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src1);
1797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  and_(dst, src2);
1799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
18023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiAndConstant(Register dst, Register src, Smi* constant) {
18033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (constant->value() == 0) {
18049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    Set(dst, 0);
18053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (dst.is(src)) {
18063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    ASSERT(!dst.is(kScratchRegister));
18078defd9ff6930b4e24729971a61cf7469daf119beSteve Block    Register constant_reg = GetSmiConstant(constant);
18088defd9ff6930b4e24729971a61cf7469daf119beSteve Block    and_(dst, constant_reg);
18093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
18108defd9ff6930b4e24729971a61cf7469daf119beSteve Block    LoadSmiConstant(dst, constant);
18113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    and_(dst, src);
1812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiOr(Register dst, Register src1, Register src2) {
1817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!dst.is(src1)) {
18188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    ASSERT(!src1.is(src2));
18193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src1);
1820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  or_(dst, src2);
1822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
18253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiOrConstant(Register dst, Register src, Smi* constant) {
18263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (dst.is(src)) {
18273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    ASSERT(!dst.is(kScratchRegister));
18288defd9ff6930b4e24729971a61cf7469daf119beSteve Block    Register constant_reg = GetSmiConstant(constant);
18298defd9ff6930b4e24729971a61cf7469daf119beSteve Block    or_(dst, constant_reg);
18303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
18318defd9ff6930b4e24729971a61cf7469daf119beSteve Block    LoadSmiConstant(dst, constant);
18323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    or_(dst, src);
1833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
18363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiXor(Register dst, Register src1, Register src2) {
1838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!dst.is(src1)) {
18398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    ASSERT(!src1.is(src2));
18403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src1);
1841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  xor_(dst, src2);
1843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
18463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiXorConstant(Register dst, Register src, Smi* constant) {
18473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (dst.is(src)) {
18483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    ASSERT(!dst.is(kScratchRegister));
18498defd9ff6930b4e24729971a61cf7469daf119beSteve Block    Register constant_reg = GetSmiConstant(constant);
18508defd9ff6930b4e24729971a61cf7469daf119beSteve Block    xor_(dst, constant_reg);
18513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
18528defd9ff6930b4e24729971a61cf7469daf119beSteve Block    LoadSmiConstant(dst, constant);
18533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    xor_(dst, src);
1854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftArithmeticRightConstant(Register dst,
1859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                     Register src,
1860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                     int shift_value) {
18613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(is_uint5(shift_value));
1862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (shift_value > 0) {
1863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (dst.is(src)) {
18643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      sar(dst, Immediate(shift_value + kSmiShift));
18653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      shl(dst, Immediate(kSmiShift));
1866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
1867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNIMPLEMENTED();  // Not used.
1868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftLeftConstant(Register dst,
1874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                          Register src,
187525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen                                          int shift_value) {
18763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src)) {
18773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src);
18783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
18793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (shift_value > 0) {
18803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    shl(dst, Immediate(shift_value));
1881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1885257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiShiftLogicalRightConstant(
1886257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register dst, Register src, int shift_value,
1887257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label* on_not_smi_result, Label::Distance near_jump) {
1888257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Logic right shift interprets its result as an *unsigned* number.
1889257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (dst.is(src)) {
1890257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    UNIMPLEMENTED();  // Not used.
1891257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1892257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(dst, src);
1893257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (shift_value == 0) {
1894257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      testq(dst, dst);
1895257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      j(negative, on_not_smi_result, near_jump);
1896257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1897257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    shr(dst, Immediate(shift_value + kSmiShift));
1898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    shl(dst, Immediate(kSmiShift));
1899257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1900257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1901257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1902257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftLeft(Register dst,
1904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  Register src1,
190525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen                                  Register src2) {
1906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(rcx));
19073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Untag shift amount.
19083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src1)) {
19093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src1);
1910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
19113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiToInteger32(rcx, src2);
19123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Shift amount specified by lower 5 bits, not six as the shl opcode.
19133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  and_(rcx, Immediate(0x1f));
1914d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  shl_cl(dst);
1915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiShiftLogicalRight(Register dst,
1919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                          Register src1,
1920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                          Register src2,
1921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                          Label* on_not_smi_result,
1922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                          Label::Distance near_jump) {
1923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!dst.is(kScratchRegister));
1924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src1.is(kScratchRegister));
1925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src2.is(kScratchRegister));
1926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!dst.is(rcx));
1927257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // dst and src1 can be the same, because the one case that bails out
1928257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // is a shift by 0, which leaves dst, and therefore src1, unchanged.
1929257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (src1.is(rcx) || src2.is(rcx)) {
1930257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(kScratchRegister, rcx);
1931257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1932257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!dst.is(src1)) {
1933257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(dst, src1);
1934257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1935257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  SmiToInteger32(rcx, src2);
1936257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  orl(rcx, Immediate(kSmiShift));
1937257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  shr_cl(dst);  // Shift is rcx modulo 0x1f + 32.
1938257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  shl(dst, Immediate(kSmiShift));
1939257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  testq(dst, dst);
1940257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (src1.is(rcx) || src2.is(rcx)) {
1941257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label positive_result;
1942257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(positive, &positive_result, Label::kNear);
1943257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (src1.is(rcx)) {
1944257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      movq(src1, kScratchRegister);
1945257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
1946257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      movq(src2, kScratchRegister);
1947257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1948257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    jmp(on_not_smi_result, near_jump);
1949257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    bind(&positive_result);
1950257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1951257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // src2 was zero and src1 negative.
1952257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(negative, on_not_smi_result, near_jump);
1953257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1954257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1955257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1956257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftArithmeticRight(Register dst,
1958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register src1,
1959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register src2) {
19603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!dst.is(kScratchRegister));
19613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!src1.is(kScratchRegister));
19623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!src2.is(kScratchRegister));
1963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(rcx));
19643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (src1.is(rcx)) {
19653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(kScratchRegister, src1);
19663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (src2.is(rcx)) {
19673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(kScratchRegister, src2);
19683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
19693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src1)) {
19703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src1);
19713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SmiToInteger32(rcx, src2);
19733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  orl(rcx, Immediate(kSmiShift));
1974d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  sar_cl(dst);  // Shift 32 + original rcx & 0x1f.
19753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  shl(dst, Immediate(kSmiShift));
19763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (src1.is(rcx)) {
19773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(src1, kScratchRegister);
19783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (src2.is(rcx)) {
19793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(src2, kScratchRegister);
19803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1984257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SelectNonSmi(Register dst,
1985257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                  Register src1,
1986257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                  Register src2,
1987257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                  Label* on_not_smis,
1988257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                  Label::Distance near_jump) {
1989257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!dst.is(kScratchRegister));
1990257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src1.is(kScratchRegister));
1991257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!src2.is(kScratchRegister));
1992257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!dst.is(src1));
1993257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!dst.is(src2));
1994257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Both operands must not be smis.
1995257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#ifdef DEBUG
1996257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (allow_stub_calls()) {  // Check contains a stub call.
1997257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Condition not_both_smis = NegateCondition(CheckBothSmi(src1, src2));
1998257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Check(not_both_smis, "Both registers were smis in SelectNonSmi.");
1999257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2000257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif
200169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
2002257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT_EQ(0, Smi::FromInt(0));
2003257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  movl(kScratchRegister, Immediate(kSmiTagMask));
2004257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  and_(kScratchRegister, src1);
2005257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  testl(kScratchRegister, src2);
2006257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If non-zero then both are smis.
2007257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_zero, on_not_smis, near_jump);
2008257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2009257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Exactly one operand is a smi.
2010257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT_EQ(1, static_cast<int>(kSmiTagMask));
2011257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // kScratchRegister still holds src1 & kSmiTag, which is either zero or one.
2012257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  subq(kScratchRegister, Immediate(1));
2013257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If src1 is a smi, then scratch register all 1s, else it is all 0s.
2014257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  movq(dst, src1);
2015257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  xor_(dst, src2);
2016257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  and_(dst, kScratchRegister);
2017257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If src1 is a smi, dst holds src1 ^ src2, else it is zero.
2018257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  xor_(dst, src1);
2019257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If src1 is a smi, dst is src2, else it is src1, i.e., the non-smi.
2020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2021257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2022257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockSmiIndex MacroAssembler::SmiToIndex(Register dst,
20243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                    Register src,
20253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                    int shift) {
2026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint6(shift));
20273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // There is a possible optimization if shift is in the range 60-63, but that
20283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // will (and must) never happen.
20293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src)) {
20303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src);
20313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
20323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (shift < kSmiShift) {
20333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    sar(dst, Immediate(kSmiShift - shift));
20343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
20353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    shl(dst, Immediate(shift - kSmiShift));
20363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return SmiIndex(dst, times_1);
2038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockSmiIndex MacroAssembler::SmiToNegativeIndex(Register dst,
2041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            Register src,
2042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            int shift) {
2043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Register src holds a positive smi.
2044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint6(shift));
20453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src)) {
20463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src);
2047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  neg(dst);
20493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (shift < kSmiShift) {
20503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    sar(dst, Immediate(kSmiShift - shift));
20513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
20523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    shl(dst, Immediate(shift - kSmiShift));
20533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return SmiIndex(dst, times_1);
2055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
205844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::AddSmiField(Register dst, const Operand& src) {
205944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT_EQ(0, kSmiShift % kBitsPerByte);
206044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  addl(dst, Operand(src, kSmiShift / kBitsPerByte));
206144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
206244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
206344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2064257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfNotString(Register object,
2065257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Register object_map,
2066257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Label* not_string,
2067257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Label::Distance near_jump) {
2068257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition is_smi = CheckSmi(object);
2069257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(is_smi, not_string, near_jump);
2070257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CmpObjectType(object, FIRST_NONSTRING_TYPE, object_map);
2071257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(above_equal, not_string, near_jump);
2072257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2073257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2074257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2075257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfNotBothSequentialAsciiStrings(
2076257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register first_object,
2077257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register second_object,
2078257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register scratch1,
2079257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register scratch2,
2080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label* on_fail,
2081257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label::Distance near_jump) {
2082257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that both objects are not smis.
2083257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition either_smi = CheckEitherSmi(first_object, second_object);
2084257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(either_smi, on_fail, near_jump);
2085257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2086257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load instance type for both strings.
2087257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  movq(scratch1, FieldOperand(first_object, HeapObject::kMapOffset));
2088257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  movq(scratch2, FieldOperand(second_object, HeapObject::kMapOffset));
2089257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  movzxbl(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset));
2090257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  movzxbl(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset));
2091257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2092257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that both are flat ascii strings.
2093257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(kNotStringTag != 0);
2094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int kFlatAsciiStringMask =
2095257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
2096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int kFlatAsciiStringTag = ASCII_STRING_TYPE;
2097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2098257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  andl(scratch1, Immediate(kFlatAsciiStringMask));
2099257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  andl(scratch2, Immediate(kFlatAsciiStringMask));
2100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Interleave the bits to check both scratch1 and scratch2 in one test.
2101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3));
2102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  lea(scratch1, Operand(scratch1, scratch2, times_8, 0));
2103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  cmpl(scratch1,
2104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch       Immediate(kFlatAsciiStringTag + (kFlatAsciiStringTag << 3)));
2105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_equal, on_fail, near_jump);
2106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii(
2110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register instance_type,
2111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register scratch,
2112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label* failure,
2113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label::Distance near_jump) {
2114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!scratch.is(instance_type)) {
2115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movl(scratch, instance_type);
2116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int kFlatAsciiStringMask =
2119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
2120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  andl(scratch, Immediate(kFlatAsciiStringMask));
2122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  cmpl(scratch, Immediate(kStringTag | kSeqStringTag | kAsciiStringTag));
2123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_equal, failure, near_jump);
2124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialAscii(
2128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register first_object_instance_type,
2129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register second_object_instance_type,
2130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register scratch1,
2131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register scratch2,
2132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label* on_fail,
2133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label::Distance near_jump) {
2134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load instance type for both strings.
2135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  movq(scratch1, first_object_instance_type);
2136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  movq(scratch2, second_object_instance_type);
2137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that both are flat ascii strings.
2139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(kNotStringTag != 0);
2140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int kFlatAsciiStringMask =
2141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
2142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int kFlatAsciiStringTag = ASCII_STRING_TYPE;
2143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  andl(scratch1, Immediate(kFlatAsciiStringMask));
2145257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  andl(scratch2, Immediate(kFlatAsciiStringMask));
2146257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Interleave the bits to check both scratch1 and scratch2 in one test.
2147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3));
2148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  lea(scratch1, Operand(scratch1, scratch2, times_8, 0));
2149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  cmpl(scratch1,
2150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch       Immediate(kFlatAsciiStringTag + (kFlatAsciiStringTag << 3)));
2151257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_equal, on_fail, near_jump);
2152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
215544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
21560d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::Move(Register dst, Register src) {
21570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (!dst.is(src)) {
21580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    movq(dst, src);
21596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
21606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
21616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Move(Register dst, Handle<Object> source) {
2164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!source->IsFailure());
2165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (source->IsSmi()) {
21663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Move(dst, Smi::cast(*source));
2167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(dst, source, RelocInfo::EMBEDDED_OBJECT);
2169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Move(const Operand& dst, Handle<Object> source) {
21743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!source->IsFailure());
2175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (source->IsSmi()) {
21763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Move(dst, Smi::cast(*source));
2177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT);
2179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(dst, kScratchRegister);
2180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Cmp(Register dst, Handle<Object> source) {
21853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (source->IsSmi()) {
218644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Cmp(dst, Smi::cast(*source));
21873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
21883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Move(kScratchRegister, source);
21893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    cmpq(dst, kScratchRegister);
21903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Cmp(const Operand& dst, Handle<Object> source) {
2195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (source->IsSmi()) {
219644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Cmp(dst, Smi::cast(*source));
2197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(source->IsHeapObject());
2199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT);
2200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    cmpq(dst, kScratchRegister);
2201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Push(Handle<Object> source) {
2206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (source->IsSmi()) {
22073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Push(Smi::cast(*source));
2208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(source->IsHeapObject());
2210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT);
2211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    push(kScratchRegister);
2212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Push(Smi* source) {
22173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  intptr_t smi = reinterpret_cast<intptr_t>(source);
22183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (is_int32(smi)) {
22193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    push(Immediate(static_cast<int32_t>(smi)));
22203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
22218defd9ff6930b4e24729971a61cf7469daf119beSteve Block    Register constant = GetSmiConstant(source);
22228defd9ff6930b4e24729971a61cf7469daf119beSteve Block    push(constant);
22233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
22243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
22253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
22263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2227e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::Drop(int stack_elements) {
2228e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (stack_elements > 0) {
2229e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    addq(rsp, Immediate(stack_elements * kPointerSize));
2230e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2231e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
2232e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2233e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
22343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::Test(const Operand& src, Smi* source) {
2235f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  testl(Operand(src, kIntSize), Immediate(source->value()));
2236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Jump(ExternalReference ext) {
224044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(kScratchRegister, ext);
2241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  jmp(kScratchRegister);
2242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Jump(Address destination, RelocInfo::Mode rmode) {
2246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister, destination, rmode);
2247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  jmp(kScratchRegister);
2248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Jump(Handle<Code> code_object, RelocInfo::Mode rmode) {
22523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // TODO(X64): Inline this
22533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  jmp(code_object, rmode);
2254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
225744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint MacroAssembler::CallSize(ExternalReference ext) {
225844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Opcode for call kScratchRegister is: Rex.B FF D4 (three bytes).
225944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const int kCallInstructionSize = 3;
226044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return LoadAddressSize(ext) + kCallInstructionSize;
226144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
226244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
226344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Call(ExternalReference ext) {
226544f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
226644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int end_position = pc_offset() + CallSize(ext);
226744f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
226844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(kScratchRegister, ext);
2269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  call(kScratchRegister);
227044f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
227144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(end_position, pc_offset());
227244f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
2273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Call(Address destination, RelocInfo::Mode rmode) {
227744f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
227844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int end_position = pc_offset() + CallSize(destination, rmode);
227944f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
2280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister, destination, rmode);
2281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  call(kScratchRegister);
228244f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
228344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(pc_offset(), end_position);
228444f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
2285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2288257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::Call(Handle<Code> code_object,
2289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                          RelocInfo::Mode rmode,
2290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                          unsigned ast_id) {
229144f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
229244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int end_position = pc_offset() + CallSize(code_object);
229344f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
2294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(RelocInfo::IsCodeTarget(rmode));
2295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  call(code_object, rmode, ast_id);
229644f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
229744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(end_position, pc_offset());
229844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
2299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
23021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::Pushad() {
23031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  push(rax);
23041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  push(rcx);
23051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  push(rdx);
23061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  push(rbx);
23071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Not pushing rsp or rbp.
23081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  push(rsi);
23091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  push(rdi);
23101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  push(r8);
23111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  push(r9);
23121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // r10 is kScratchRegister.
23131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  push(r11);
231444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // r12 is kSmiConstantRegister.
23151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // r13 is kRootRegister.
23161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  push(r14);
231744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  push(r15);
2318e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  STATIC_ASSERT(11 == kNumSafepointSavedRegisters);
2319e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Use lea for symmetry with Popad.
2320e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int sp_delta =
2321e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      (kNumSafepointRegisters - kNumSafepointSavedRegisters) * kPointerSize;
2322e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  lea(rsp, Operand(rsp, -sp_delta));
23231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
23241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
23251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
23261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::Popad() {
2327e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Popad must not change the flags, so use lea instead of addq.
2328e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int sp_delta =
2329e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      (kNumSafepointRegisters - kNumSafepointSavedRegisters) * kPointerSize;
2330e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  lea(rsp, Operand(rsp, sp_delta));
233144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  pop(r15);
23321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  pop(r14);
23331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  pop(r11);
23341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  pop(r9);
23351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  pop(r8);
23361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  pop(rdi);
23371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  pop(rsi);
23381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  pop(rbx);
23391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  pop(rdx);
23401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  pop(rcx);
23411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  pop(rax);
23421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
23431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
23441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
23451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::Dropad() {
2346e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  addq(rsp, Immediate(kNumSafepointRegisters * kPointerSize));
23471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
23481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
23491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
23501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Order general registers are pushed by Pushad:
235144f0eee88ff00398ff7f715fab053374d808c90dSteve Block// rax, rcx, rdx, rbx, rsi, rdi, r8, r9, r11, r14, r15.
23521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockint MacroAssembler::kSafepointPushRegisterIndices[Register::kNumRegisters] = {
23531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    0,
23541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    1,
23551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    2,
23561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    3,
23571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    -1,
23581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    -1,
23591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    4,
23601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    5,
23611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    6,
23621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    7,
23631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    -1,
23641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    8,
23651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    -1,
236644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    -1,
236744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    9,
236844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    10
23691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block};
23701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
23711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2372e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Register src) {
2373e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  movq(SafepointRegisterSlot(dst), src);
2374e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2375e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2376e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2377e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) {
2378e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  movq(dst, SafepointRegisterSlot(src));
2379e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2380e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2381e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2382e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochOperand MacroAssembler::SafepointRegisterSlot(Register reg) {
2383e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return Operand(rsp, SafepointRegisterStackIndex(reg.code()) * kPointerSize);
2384e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2385e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2386e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::PushTryHandler(CodeLocation try_location,
2388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    HandlerType type) {
2389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Adjust this code if not the case.
239069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
239169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize);
239269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kContextOffset == 1 * kPointerSize);
239369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize);
239469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kStateOffset == 3 * kPointerSize);
239569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize);
2396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The pc (return address) is already on TOS.  This code pushes state,
239869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // frame pointer, context, and current handler.
2399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (try_location == IN_JAVASCRIPT) {
2400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (type == TRY_CATCH_HANDLER) {
2401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      push(Immediate(StackHandler::TRY_CATCH));
2402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
2403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      push(Immediate(StackHandler::TRY_FINALLY));
2404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    push(rbp);
240669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    push(rsi);
2407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(try_location == IN_JS_ENTRY);
2409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // The frame pointer does not point to a JS frame so we save NULL
2410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // for rbp. We expect the code throwing an exception to check rbp
2411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // before dereferencing it to restore the context.
2412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    push(Immediate(StackHandler::ENTRY));
2413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    push(Immediate(0));  // NULL frame pointer.
241469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Push(Smi::FromInt(0));  // No context.
2415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Save the current handler.
241744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Operand handler_operand =
241844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalOperand(ExternalReference(Isolate::k_handler_address, isolate()));
241944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  push(handler_operand);
2420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Link this handler.
242144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  movq(handler_operand, rsp);
2422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2425e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::PopTryHandler() {
2426e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(0, StackHandlerConstants::kNextOffset);
2427e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Unlink this handler.
242844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Operand handler_operand =
242944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalOperand(ExternalReference(Isolate::k_handler_address, isolate()));
243044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  pop(handler_operand);
2431e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Remove the remaining fields.
2432e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  addq(rsp, Immediate(StackHandlerConstants::kSize - kPointerSize));
2433e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
2434e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2435e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2436e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::Throw(Register value) {
243769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Adjust this code if not the case.
243869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
243969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize);
244069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kContextOffset == 1 * kPointerSize);
244169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize);
244269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kStateOffset == 3 * kPointerSize);
244369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize);
2444e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Keep thrown value in rax.
2445e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!value.is(rax)) {
2446e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    movq(rax, value);
2447e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2448e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
244944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ExternalReference handler_address(Isolate::k_handler_address, isolate());
245044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Operand handler_operand = ExternalOperand(handler_address);
245144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  movq(rsp, handler_operand);
2452e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // get next in chain
245344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  pop(handler_operand);
245469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  pop(rsi);  // Context.
245569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  pop(rbp);  // Frame pointer.
245669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  pop(rdx);  // State.
2457e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
245869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // If the handler is a JS frame, restore the context to the frame.
245969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // (rdx == ENTRY) == (rbp == 0) == (rsi == 0), so we could test any
246069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // of them.
2461257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label skip;
246269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  cmpq(rdx, Immediate(StackHandler::ENTRY));
2463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(equal, &skip, Label::kNear);
246469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi);
2465e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  bind(&skip);
246669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
2467e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ret(0);
2468e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2469e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2470e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2471e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::ThrowUncatchable(UncatchableExceptionType type,
2472e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      Register value) {
247369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Adjust this code if not the case.
247469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
247569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize);
247669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kContextOffset == 1 * kPointerSize);
247769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize);
247869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kStateOffset == 3 * kPointerSize);
247969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize);
2480e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Keep thrown value in rax.
2481e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!value.is(rax)) {
2482e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    movq(rax, value);
2483e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2484e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Fetch top stack handler.
248544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ExternalReference handler_address(Isolate::k_handler_address, isolate());
248644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Load(rsp, handler_address);
2487e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2488e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Unwind the handlers until the ENTRY handler is found.
2489257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label loop, done;
2490e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  bind(&loop);
2491e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Load the type of the current stack handler.
2492e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  const int kStateOffset = StackHandlerConstants::kStateOffset;
2493e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  cmpq(Operand(rsp, kStateOffset), Immediate(StackHandler::ENTRY));
2494257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(equal, &done, Label::kNear);
2495e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Fetch the next handler in the list.
2496e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  const int kNextOffset = StackHandlerConstants::kNextOffset;
2497e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  movq(rsp, Operand(rsp, kNextOffset));
2498e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  jmp(&loop);
2499e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  bind(&done);
2500e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2501e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Set the top handler address to next handler past the current ENTRY handler.
250244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Operand handler_operand = ExternalOperand(handler_address);
250344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  pop(handler_operand);
2504e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2505e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (type == OUT_OF_MEMORY) {
2506e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Set external caught exception to false.
250744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ExternalReference external_caught(
250844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Isolate::k_external_caught_exception_address, isolate());
25098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Set(rax, static_cast<int64_t>(false));
251044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Store(external_caught, rax);
2511e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2512e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Set pending exception and rax to out of memory exception.
251344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ExternalReference pending_exception(Isolate::k_pending_exception_address,
251444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                        isolate());
2515e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    movq(rax, Failure::OutOfMemoryException(), RelocInfo::NONE);
251644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Store(pending_exception, rax);
2517e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2518e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
251969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Discard the context saved in the handler and clear the context pointer.
252069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  pop(rdx);
2521e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Set(rsi, 0);
2522e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
252369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  pop(rbp);  // Restore frame pointer.
252469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  pop(rdx);  // Discard state.
2525e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2526e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ret(0);
2527e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2528e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2529e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Ret() {
2531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ret(0);
2532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::Ret(int bytes_dropped, Register scratch) {
25361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (is_uint16(bytes_dropped)) {
25371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ret(bytes_dropped);
25381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
25391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    pop(scratch);
25401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    addq(rsp, Immediate(bytes_dropped));
25411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    push(scratch);
25421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ret(0);
25431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
25441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
25451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
25461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::FCmp() {
25483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  fucomip();
25498defd9ff6930b4e24729971a61cf7469daf119beSteve Block  fstp(0);
2550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpObjectType(Register heap_object,
2554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   InstanceType type,
2555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   Register map) {
2556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(map, FieldOperand(heap_object, HeapObject::kMapOffset));
2557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CmpInstanceType(map, type);
2558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpInstanceType(Register map, InstanceType type) {
2562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cmpb(FieldOperand(map, Map::kInstanceTypeOffset),
2563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       Immediate(static_cast<int8_t>(type)));
2564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::CheckFastElements(Register map,
25683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                       Label* fail,
25693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                       Label::Distance distance) {
25703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  STATIC_ASSERT(JSObject::FAST_ELEMENTS == 0);
25713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  cmpb(FieldOperand(map, Map::kBitField2Offset),
25723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch       Immediate(Map::kMaximumBitField2FastElementValue));
25733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  j(above, fail, distance);
25743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
25753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
25763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
25773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::CheckMap(Register obj,
25783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Handle<Map> map,
25793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Label* fail,
2580257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                              SmiCheckType smi_check_type) {
2581257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (smi_check_type == DO_SMI_CHECK) {
25823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    JumpIfSmi(obj, fail);
25833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
25843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Cmp(FieldOperand(obj, HeapObject::kMapOffset), map);
25853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  j(not_equal, fail);
25863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
25873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
25883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2589257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::ClampUint8(Register reg) {
2590257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
2591257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  testl(reg, Immediate(0xFFFFFF00));
2592257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(zero, &done, Label::kNear);
2593257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  setcc(negative, reg);  // 1 if negative, 0 if positive.
2594257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  decb(reg);  // 0 if negative, 255 if positive.
2595257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&done);
2596257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2597257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2598257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2599257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::ClampDoubleToUint8(XMMRegister input_reg,
2600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                        XMMRegister temp_xmm_reg,
2601257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                        Register result_reg,
2602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                        Register temp_reg) {
2603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
2604257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Set(result_reg, 0);
2605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  xorps(temp_xmm_reg, temp_xmm_reg);
2606257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ucomisd(input_reg, temp_xmm_reg);
2607257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(below, &done, Label::kNear);
2608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  uint64_t one_half = BitCast<uint64_t, double>(0.5);
2609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Set(temp_reg, one_half);
2610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  movq(temp_xmm_reg, temp_reg);
2611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  addsd(temp_xmm_reg, input_reg);
2612257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  cvttsd2si(result_reg, temp_xmm_reg);
2613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  testl(result_reg, Immediate(0xFFFFFF00));
2614257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(zero, &done, Label::kNear);
2615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Set(result_reg, 255);
2616257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&done);
2617257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2618257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2619257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2620257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::LoadInstanceDescriptors(Register map,
2621257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Register descriptors) {
2622257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  movq(descriptors, FieldOperand(map,
2623257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Map::kInstanceDescriptorsOrBitField3Offset));
2624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label not_smi;
2625257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  JumpIfNotSmi(descriptors, &not_smi, Label::kNear);
2626257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Move(descriptors, isolate()->factory()->empty_descriptor_array());
2627257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&not_smi);
2628257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2629257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2630257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2631257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::DispatchMap(Register obj,
2632257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Handle<Map> map,
2633257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Handle<Code> success,
2634257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 SmiCheckType smi_check_type) {
2635257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label fail;
2636257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (smi_check_type == DO_SMI_CHECK) {
2637257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    JumpIfSmi(obj, &fail);
2638257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2639257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Cmp(FieldOperand(obj, HeapObject::kMapOffset), map);
2640257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(equal, success, RelocInfo::CODE_TARGET);
2641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2642257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&fail);
2643257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2646f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid MacroAssembler::AbortIfNotNumber(Register object) {
2647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label ok;
2648402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Condition is_smi = CheckSmi(object);
2649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(is_smi, &ok, Label::kNear);
2650402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Cmp(FieldOperand(object, HeapObject::kMapOffset),
2651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      isolate()->factory()->heap_number_map());
2652f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Assert(equal, "Operand not a number");
2653402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  bind(&ok);
2654402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
2655402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2656402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2657756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid MacroAssembler::AbortIfSmi(Register object) {
2658756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Condition is_smi = CheckSmi(object);
2659756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Assert(NegateCondition(is_smi), "Operand is a smi");
2660756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
2661756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2662756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2663f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid MacroAssembler::AbortIfNotSmi(Register object) {
266444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Condition is_smi = CheckSmi(object);
266544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Assert(is_smi, "Operand is not a smi");
266644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
266744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
266844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
266944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::AbortIfNotSmi(const Operand& object) {
26706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Condition is_smi = CheckSmi(object);
2671756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Assert(is_smi, "Operand is not a smi");
26726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
26736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
26746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2675e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::AbortIfNotString(Register object) {
2676e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  testb(object, Immediate(kSmiTagMask));
2677e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Assert(not_equal, "Operand is not a string");
2678e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  push(object);
2679e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  movq(object, FieldOperand(object, HeapObject::kMapOffset));
2680e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CmpInstanceType(object, FIRST_NONSTRING_TYPE);
2681e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  pop(object);
2682e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Assert(below, "Operand is not a string");
2683e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2684e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2685e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
26869dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::AbortIfNotRootValue(Register src,
26879dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                         Heap::RootListIndex root_value_index,
26889dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                         const char* message) {
26899dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  ASSERT(!src.is(kScratchRegister));
26909dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  LoadRoot(kScratchRegister, root_value_index);
26919dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  cmpq(src, kScratchRegister);
26929dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  Check(equal, message);
26939dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
26949dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
26959dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
26969dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
2697d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeCondition MacroAssembler::IsObjectStringType(Register heap_object,
2698d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                             Register map,
2699d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                             Register instance_type) {
2700d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  movq(map, FieldOperand(heap_object, HeapObject::kMapOffset));
27014515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  movzxbl(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
270269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kNotStringTag != 0);
2703d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  testb(instance_type, Immediate(kIsNotStringMask));
2704d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  return zero;
2705d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
2706d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2707d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::TryGetFunctionPrototype(Register function,
2709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register result,
2710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Label* miss) {
2711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
2712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  testl(function, Immediate(kSmiTagMask));
2713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(zero, miss);
2714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the function really is a function.
2716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CmpObjectType(function, JS_FUNCTION_TYPE, result);
2717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(not_equal, miss);
2718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure that the function has an instance prototype.
2720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label non_instance;
2721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  testb(FieldOperand(result, Map::kBitFieldOffset),
2722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Immediate(1 << Map::kHasNonInstancePrototype));
2723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_zero, &non_instance, Label::kNear);
2724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the prototype or initial map from the function.
2726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(result,
2727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
2728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the prototype or initial map is the hole, don't return it and
2730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // simply miss the cache instead. This will allow us to allocate a
2731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // prototype object on-demand in the runtime system.
2732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompareRoot(result, Heap::kTheHoleValueRootIndex);
2733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(equal, miss);
2734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the function does not have an initial map, we're done.
2736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
2737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CmpObjectType(result, MAP_TYPE, kScratchRegister);
2738257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_equal, &done, Label::kNear);
2739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the prototype from the initial map.
2741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(result, FieldOperand(result, Map::kPrototypeOffset));
2742257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  jmp(&done, Label::kNear);
2743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Non-instance prototype: Fetch prototype from constructor field
2745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // in initial map.
2746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&non_instance);
2747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(result, FieldOperand(result, Map::kConstructorOffset));
2748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // All done.
2750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&done);
2751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SetCounter(StatsCounter* counter, int value) {
2755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
275644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Operand counter_operand = ExternalOperand(ExternalReference(counter));
27578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    movl(counter_operand, Immediate(value));
2758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::IncrementCounter(StatsCounter* counter, int value) {
2763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(value > 0);
2764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
276544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Operand counter_operand = ExternalOperand(ExternalReference(counter));
2766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (value == 1) {
276744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      incl(counter_operand);
2768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
276944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      addl(counter_operand, Immediate(value));
2770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::DecrementCounter(StatsCounter* counter, int value) {
2776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(value > 0);
2777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
277844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Operand counter_operand = ExternalOperand(ExternalReference(counter));
2779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (value == 1) {
278044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      decl(counter_operand);
2781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
278244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      subl(counter_operand, Immediate(value));
2783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
278880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#ifdef ENABLE_DEBUGGER_SUPPORT
2789402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::DebugBreak() {
2790402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ASSERT(allow_stub_calls());
27919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Set(rax, 0);  // No arguments.
279244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(rbx, ExternalReference(Runtime::kDebugBreak, isolate()));
2793402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CEntryStub ces(1);
2794402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Call(ces.GetCode(), RelocInfo::DEBUG_BREAK);
2795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2796402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#endif  // ENABLE_DEBUGGER_SUPPORT
2797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2799257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SetCallKind(Register dst, CallKind call_kind) {
2800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This macro takes the dst register to make the code more readable
2801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // at the call sites. However, the dst register has to be rcx to
2802257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // follow the calling convention which requires the call type to be
2803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // in rcx.
2804257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(dst.is(rcx));
2805257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (call_kind == CALL_AS_FUNCTION) {
2806257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    LoadSmiConstant(dst, Smi::FromInt(1));
2807257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
2808257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    LoadSmiConstant(dst, Smi::FromInt(0));
2809257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2810257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2811257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2812257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeCode(Register code,
2814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                const ParameterCount& expected,
2815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                const ParameterCount& actual,
2816e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                InvokeFlag flag,
2817257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                const CallWrapper& call_wrapper,
2818257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                CallKind call_kind) {
2819257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
2820e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  InvokePrologue(expected,
2821e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 actual,
2822e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 Handle<Code>::null(),
2823e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 code,
2824e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 &done,
2825e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 flag,
2826257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 Label::kNear,
2827257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 call_wrapper,
2828257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 call_kind);
2829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (flag == CALL_FUNCTION) {
2830257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    call_wrapper.BeforeCall(CallSize(code));
2831257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    SetCallKind(rcx, call_kind);
2832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    call(code);
2833257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    call_wrapper.AfterCall();
2834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(flag == JUMP_FUNCTION);
2836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    SetCallKind(rcx, call_kind);
2837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    jmp(code);
2838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&done);
2840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeCode(Handle<Code> code,
2844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                const ParameterCount& expected,
2845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                const ParameterCount& actual,
2846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                RelocInfo::Mode rmode,
2847e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                InvokeFlag flag,
2848257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                const CallWrapper& call_wrapper,
2849257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                CallKind call_kind) {
2850257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
2851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Register dummy = rax;
2852e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  InvokePrologue(expected,
2853e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 actual,
2854e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 code,
2855e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 dummy,
2856e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 &done,
2857e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 flag,
2858257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 Label::kNear,
2859257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 call_wrapper,
2860257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 call_kind);
2861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (flag == CALL_FUNCTION) {
2862257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    call_wrapper.BeforeCall(CallSize(code));
2863257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    SetCallKind(rcx, call_kind);
2864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Call(code, rmode);
2865257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    call_wrapper.AfterCall();
2866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(flag == JUMP_FUNCTION);
2868257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    SetCallKind(rcx, call_kind);
2869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Jump(code, rmode);
2870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&done);
2872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeFunction(Register function,
2876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    const ParameterCount& actual,
2877e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                    InvokeFlag flag,
2878257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    const CallWrapper& call_wrapper,
2879257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    CallKind call_kind) {
2880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(function.is(rdi));
2881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rdx, FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
2882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rsi, FieldOperand(function, JSFunction::kContextOffset));
2883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movsxlq(rbx,
2884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          FieldOperand(rdx, SharedFunctionInfo::kFormalParameterCountOffset));
2885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Advances rdx to the end of the Code object header, to the start of
2886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the executable code.
2887791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
2888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ParameterCount expected(rbx);
2890257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  InvokeCode(rdx, expected, actual, flag, call_wrapper, call_kind);
2891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2894402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::InvokeFunction(JSFunction* function,
2895402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                    const ParameterCount& actual,
2896e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                    InvokeFlag flag,
2897257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    const CallWrapper& call_wrapper,
2898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    CallKind call_kind) {
2899402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ASSERT(function->is_compiled());
2900402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Get the function and setup the context.
2901402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Move(rdi, Handle<JSFunction>(function));
2902402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
2903402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
29041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (V8::UseCrankshaft()) {
29051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Since Crankshaft can recompile a function, we need to load
29061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // the Code object every time we call the function.
29071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
29081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ParameterCount expected(function->shared()->formal_parameter_count());
2909257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    InvokeCode(rdx, expected, actual, flag, call_wrapper, call_kind);
29101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
29111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Invoke the cached code.
29121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Handle<Code> code(function->code());
29131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ParameterCount expected(function->shared()->formal_parameter_count());
2914e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    InvokeCode(code,
2915e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch               expected,
2916e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch               actual,
2917e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch               RelocInfo::CODE_TARGET,
2918e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch               flag,
2919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch               call_wrapper,
2920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch               call_kind);
2921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::InvokePrologue(const ParameterCount& expected,
2926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    const ParameterCount& actual,
2927257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Handle<Code> code_constant,
2928257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Register code_register,
2929257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Label* done,
2930257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    InvokeFlag flag,
2931257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Label::Distance near_jump,
2932257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    const CallWrapper& call_wrapper,
2933257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    CallKind call_kind) {
2934257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool definitely_matches = false;
2935257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label invoke;
2936257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (expected.is_immediate()) {
2937257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(actual.is_immediate());
2938257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (expected.immediate() == actual.immediate()) {
2939257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      definitely_matches = true;
2940257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
2941257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Set(rax, actual.immediate());
2942257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (expected.immediate() ==
2943257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              SharedFunctionInfo::kDontAdaptArgumentsSentinel) {
2944257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // Don't worry about adapting arguments for built-ins that
2945257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // don't want that done. Skip adaption code by making it look
2946257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // like we have a match between expected and actual number of
2947257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // arguments.
2948257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        definitely_matches = true;
2949257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      } else {
2950257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        Set(rbx, expected.immediate());
2951257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
2952257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
2953257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
2954257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (actual.is_immediate()) {
2955257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Expected is in register, actual is immediate. This is the
2956257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // case when we invoke function values without going through the
2957257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // IC mechanism.
2958257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      cmpq(expected.reg(), Immediate(actual.immediate()));
2959257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      j(equal, &invoke, Label::kNear);
2960257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ASSERT(expected.reg().is(rbx));
2961257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Set(rax, actual.immediate());
2962257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else if (!expected.reg().is(actual.reg())) {
2963257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Both expected and actual are in (different) registers. This
2964257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // is the case when we invoke functions using call and apply.
2965257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      cmpq(expected.reg(), actual.reg());
2966257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      j(equal, &invoke, Label::kNear);
2967257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ASSERT(actual.reg().is(rax));
2968257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ASSERT(expected.reg().is(rbx));
2969257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
2970257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2971257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2972257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!definitely_matches) {
2973257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Handle<Code> adaptor = isolate()->builtins()->ArgumentsAdaptorTrampoline();
2974257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (!code_constant.is_null()) {
2975257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      movq(rdx, code_constant, RelocInfo::EMBEDDED_OBJECT);
2976257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      addq(rdx, Immediate(Code::kHeaderSize - kHeapObjectTag));
2977257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else if (!code_register.is(rdx)) {
2978257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      movq(rdx, code_register);
2979257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
2980257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2981257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (flag == CALL_FUNCTION) {
2982257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      call_wrapper.BeforeCall(CallSize(adaptor));
2983257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      SetCallKind(rcx, call_kind);
2984257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Call(adaptor, RelocInfo::CODE_TARGET);
2985257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      call_wrapper.AfterCall();
2986257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      jmp(done, near_jump);
2987257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
2988257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      SetCallKind(rcx, call_kind);
2989257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Jump(adaptor, RelocInfo::CODE_TARGET);
2990257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
2991257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    bind(&invoke);
29921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
2993402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
2994402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2995402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::EnterFrame(StackFrame::Type type) {
2997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(rbp);
2998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rbp, rsp);
2999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(rsi);  // Context.
30003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Push(Smi::FromInt(type));
3001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT);
3002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(kScratchRegister);
300344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
3004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(kScratchRegister,
3005257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         isolate()->factory()->undefined_value(),
3006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         RelocInfo::EMBEDDED_OBJECT);
3007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    cmpq(Operand(rsp, 0), kScratchRegister);
3008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(not_equal, "code object not properly patched");
3009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LeaveFrame(StackFrame::Type type) {
301444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
30153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Move(kScratchRegister, Smi::FromInt(type));
3016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    cmpq(Operand(rbp, StandardFrameConstants::kMarkerOffset), kScratchRegister);
3017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(equal, "stack frame types must match");
3018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rsp, rbp);
3020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pop(rbp);
3021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
302480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::EnterExitFramePrologue(bool save_rax) {
3025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Setup the frame structure on the stack.
3026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // All constants are relative to the frame pointer of the exit frame.
3027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize);
3028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize);
3029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(ExitFrameConstants::kCallerFPOffset ==  0 * kPointerSize);
3030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(rbp);
3031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rbp, rsp);
3032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
303380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Reserve room for entry stack pointer and push the code object.
30343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize);
3035402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  push(Immediate(0));  // Saved entry sp, patched before call.
3036402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT);
3037402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  push(kScratchRegister);  // Accessed from EditFrame::code_slot.
3038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Save the frame pointer and the context in top.
3040bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (save_rax) {
304144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    movq(r14, rax);  // Backup rax in callee-save register.
3042bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
3043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
304444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Store(ExternalReference(Isolate::k_c_entry_fp_address, isolate()), rbp);
304544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Store(ExternalReference(Isolate::k_context_address, isolate()), rsi);
3046bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
3047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
30491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::EnterExitFrameEpilogue(int arg_stack_space,
30501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                            bool save_doubles) {
3051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef _WIN64
30521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  const int kShadowSpace = 4;
30531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  arg_stack_space += kShadowSpace;
3054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
30551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Optionally save all XMM registers.
30561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (save_doubles) {
30571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    int space = XMMRegister::kNumRegisters * kDoubleSize +
30581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        arg_stack_space * kPointerSize;
30591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    subq(rsp, Immediate(space));
30601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    int offset = -2 * kPointerSize;
30611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; i++) {
30621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      XMMRegister reg = XMMRegister::FromAllocationIndex(i);
30631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      movsd(Operand(rbp, offset - ((i + 1) * kDoubleSize)), reg);
30641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
30651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else if (arg_stack_space > 0) {
30668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    subq(rsp, Immediate(arg_stack_space * kPointerSize));
30678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  }
3068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the required frame alignment for the OS.
307044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const int kFrameAlignment = OS::ActivationFrameAlignment();
3071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (kFrameAlignment > 0) {
3072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(IsPowerOf2(kFrameAlignment));
30738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    ASSERT(is_int8(kFrameAlignment));
30748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    and_(rsp, Immediate(-kFrameAlignment));
3075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the saved entry sp.
3078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(Operand(rbp, ExitFrameConstants::kSPOffset), rsp);
3079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::EnterExitFrame(int arg_stack_space, bool save_doubles) {
308380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  EnterExitFramePrologue(true);
3084bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
308544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Setup argv in callee-saved register r15. It is reused in LeaveExitFrame,
3086bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // so it must be retained across the C-call.
3087bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
308844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lea(r15, Operand(rbp, r14, times_pointer_size, offset));
3089bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
30901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  EnterExitFrameEpilogue(arg_stack_space, save_doubles);
3091bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
3092bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
3093bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
30948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid MacroAssembler::EnterApiExitFrame(int arg_stack_space) {
309580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  EnterExitFramePrologue(false);
30961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  EnterExitFrameEpilogue(arg_stack_space, false);
3097bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
3098bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
3099bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
31001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::LeaveExitFrame(bool save_doubles) {
3101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Registers:
310244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // r15 : argv
31031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (save_doubles) {
31041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    int offset = -2 * kPointerSize;
31051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; i++) {
31061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      XMMRegister reg = XMMRegister::FromAllocationIndex(i);
31071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      movsd(reg, Operand(rbp, offset - ((i + 1) * kDoubleSize)));
31081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
31091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
3110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the return address from the stack and restore the frame pointer.
3111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rcx, Operand(rbp, 1 * kPointerSize));
3112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rbp, Operand(rbp, 0 * kPointerSize));
3113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
31141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Drop everything up to and including the arguments and the receiver
3115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // from the caller stack.
311644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lea(rsp, Operand(r15, 1 * kPointerSize));
3117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
31188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Push the return address to get ready to return.
31198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  push(rcx);
31208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
31218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LeaveExitFrameEpilogue();
31228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
31238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
31248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
31258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid MacroAssembler::LeaveApiExitFrame() {
31268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  movq(rsp, rbp);
31278a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  pop(rbp);
31288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
31298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LeaveExitFrameEpilogue();
31308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
31318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
31328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
31338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid MacroAssembler::LeaveExitFrameEpilogue() {
3134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Restore current context from top and clear it in debug mode.
313544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ExternalReference context_address(Isolate::k_context_address, isolate());
313644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Operand context_operand = ExternalOperand(context_address);
313744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  movq(rsi, context_operand);
3138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
313944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  movq(context_operand, Immediate(0));
3140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
3141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clear the top frame.
314344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ExternalReference c_entry_fp_address(Isolate::k_c_entry_fp_address,
314444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       isolate());
314544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Operand c_entry_fp_operand = ExternalOperand(c_entry_fp_address);
314644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  movq(c_entry_fp_operand, Immediate(0));
3147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
3151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            Register scratch,
3152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            Label* miss) {
3153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label same_contexts;
3154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!holder_reg.is(scratch));
3156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!scratch.is(kScratchRegister));
3157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load current lexical context from the stack frame.
3158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(scratch, Operand(rbp, StandardFrameConstants::kContextOffset));
3159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // When generating debug code, make sure the lexical context is set.
316144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
3162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    cmpq(scratch, Immediate(0));
3163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(not_equal, "we should not have an empty lexical context");
3164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the global context of the current context.
3166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
3167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(scratch, FieldOperand(scratch, offset));
3168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(scratch, FieldOperand(scratch, GlobalObject::kGlobalContextOffset));
3169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check the context is a global context.
317144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
3172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Cmp(FieldOperand(scratch, HeapObject::kMapOffset),
3173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        isolate()->factory()->global_context_map());
3174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(equal, "JSGlobalObject::global_context should be a global context.");
3175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if both contexts are the same.
3178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cmpq(scratch, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset));
3179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(equal, &same_contexts);
3180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compare security tokens.
3182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the security token in the calling global object is
3183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // compatible with the security token in the receiving global
3184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object.
3185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check the context is a global context.
318744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
3188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Preserve original value of holder_reg.
3189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    push(holder_reg);
3190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(holder_reg, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset));
3191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CompareRoot(holder_reg, Heap::kNullValueRootIndex);
3192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(not_equal, "JSGlobalProxy::context() should not be null.");
3193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Read the first word and compare to global_context_map(),
3195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(holder_reg, FieldOperand(holder_reg, HeapObject::kMapOffset));
3196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CompareRoot(holder_reg, Heap::kGlobalContextMapRootIndex);
3197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(equal, "JSGlobalObject::global_context should be a global context.");
3198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    pop(holder_reg);
3199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister,
3202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       FieldOperand(holder_reg, JSGlobalProxy::kContextOffset));
32033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int token_offset =
32043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      Context::kHeaderSize + Context::SECURITY_TOKEN_INDEX * kPointerSize;
3205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(scratch, FieldOperand(scratch, token_offset));
3206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cmpq(scratch, FieldOperand(kScratchRegister, token_offset));
3207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(not_equal, miss);
3208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&same_contexts);
3210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
32133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::LoadFromNumberDictionary(Label* miss,
32143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register elements,
32153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register key,
32163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register r0,
32173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register r1,
32183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register r2,
32193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register result) {
32203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Register use:
32213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
32223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // elements - holds the slow-case elements of the receiver on entry.
32233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //            Unchanged unless 'result' is the same register.
32243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
32253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // key      - holds the smi key on entry.
32263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //            Unchanged unless 'result' is the same register.
32273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
32283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Scratch registers:
32293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
32303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // r0 - holds the untagged key on entry and holds the hash once computed.
32313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
32323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // r1 - used to hold the capacity mask of the dictionary
32333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
32343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // r2 - used for the index into the dictionary.
32353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
32363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // result - holds the result on exit if the load succeeded.
32373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //          Allowed to be the same as 'key' or 'result'.
32383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //          Unchanged on bailout so 'key' or 'result' can be used
32393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //          in further computation.
32403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
32413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label done;
32423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
32433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Compute the hash code from the untagged key.  This must be kept in sync
32443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // with ComputeIntegerHash in utils.h.
32453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
32463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // hash = ~hash + (hash << 15);
32473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  movl(r1, r0);
32483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  notl(r0);
32493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  shll(r1, Immediate(15));
32503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  addl(r0, r1);
32513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // hash = hash ^ (hash >> 12);
32523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  movl(r1, r0);
32533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  shrl(r1, Immediate(12));
32543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  xorl(r0, r1);
32553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // hash = hash + (hash << 2);
32563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  leal(r0, Operand(r0, r0, times_4, 0));
32573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // hash = hash ^ (hash >> 4);
32583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  movl(r1, r0);
32593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  shrl(r1, Immediate(4));
32603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  xorl(r0, r1);
32613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // hash = hash * 2057;
32623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  imull(r0, r0, Immediate(2057));
32633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // hash = hash ^ (hash >> 16);
32643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  movl(r1, r0);
32653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  shrl(r1, Immediate(16));
32663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  xorl(r0, r1);
32673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
32683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Compute capacity mask.
32693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  SmiToInteger32(r1,
32703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                 FieldOperand(elements, NumberDictionary::kCapacityOffset));
32713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  decl(r1);
32723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
32733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Generate an unrolled loop that performs a few probes before giving up.
32743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const int kProbes = 4;
32753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (int i = 0; i < kProbes; i++) {
32763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Use r2 for index calculations and keep the hash intact in r0.
32773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    movq(r2, r0);
32783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Compute the masked index: (hash + i + i * i) & mask.
32793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (i > 0) {
32803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      addl(r2, Immediate(NumberDictionary::GetProbeOffset(i)));
32813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
32823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    and_(r2, r1);
32833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
32843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Scale the index by multiplying by the entry size.
32853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ASSERT(NumberDictionary::kEntrySize == 3);
32863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    lea(r2, Operand(r2, r2, times_2, 0));  // r2 = r2 * 3
32873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
32883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Check if the key matches.
32893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    cmpq(key, FieldOperand(elements,
32903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                           r2,
32913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                           times_pointer_size,
32923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                           NumberDictionary::kElementsStartOffset));
32933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (i != (kProbes - 1)) {
32943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      j(equal, &done);
32953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
32963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      j(not_equal, miss);
32973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
32983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
32993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
33003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bind(&done);
33013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the value is a normal propety.
33023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const int kDetailsOffset =
33033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      NumberDictionary::kElementsStartOffset + 2 * kPointerSize;
33043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT_EQ(NORMAL, 0);
33053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset),
33063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch       Smi::FromInt(PropertyDetails::TypeField::mask()));
33073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  j(not_zero, miss);
33083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
33093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Get the value at the masked, scaled index.
33103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const int kValueOffset =
33113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      NumberDictionary::kElementsStartOffset + kPointerSize;
33123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  movq(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset));
33133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
33143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
33153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LoadAllocationTopHelper(Register result,
3317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register scratch,
3318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             AllocationFlags flags) {
3319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference new_space_allocation_top =
332044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::new_space_allocation_top_address(isolate());
3321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Just return if allocation top is already known.
3323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((flags & RESULT_CONTAINS_TOP) != 0) {
3324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // No use of scratch if allocation top is provided.
33256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(!scratch.is_valid());
3326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
3327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Assert that result actually contains top on entry.
332844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Operand top_operand = ExternalOperand(new_space_allocation_top);
332944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    cmpq(result, top_operand);
3330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(equal, "Unexpected allocation top");
3331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
3332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
3333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
33356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Move address of new object to result. Use scratch register if available,
33366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // and keep address in scratch until call to UpdateAllocationTopHelper.
33376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (scratch.is_valid()) {
333844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    LoadAddress(scratch, new_space_allocation_top);
3339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(result, Operand(scratch, 0));
33406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
334144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Load(result, new_space_allocation_top);
3342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::UpdateAllocationTopHelper(Register result_end,
3347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                               Register scratch) {
334844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
3349d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    testq(result_end, Immediate(kObjectAlignmentMask));
3350d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Check(zero, "Unaligned allocation in new space");
3351d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
3352d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference new_space_allocation_top =
335444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::new_space_allocation_top_address(isolate());
3355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update new top.
335744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (scratch.is_valid()) {
335844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Scratch already contains address of allocation top.
335944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    movq(Operand(scratch, 0), result_end);
3360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
336144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Store(new_space_allocation_top, result_end);
3362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(int object_size,
3367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register result,
3368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register result_end,
3369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch,
3370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Label* gc_required,
3371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        AllocationFlags flags) {
33725913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  if (!FLAG_inline_new) {
337344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (emit_debug_code()) {
33745913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // Trash the registers to simulate an allocation failure.
33755913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      movl(result, Immediate(0x7091));
33765913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (result_end.is_valid()) {
33775913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        movl(result_end, Immediate(0x7191));
33785913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
33795913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (scratch.is_valid()) {
33805913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        movl(scratch, Immediate(0x7291));
33815913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
33825913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    }
33835913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    jmp(gc_required);
33845913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    return;
33855913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
3386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!result.is(result_end));
3387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load address of new object into result.
33898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LoadAllocationTopHelper(result, scratch, flags);
3390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate new top and bail out if new space is exhausted.
3392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference new_space_allocation_limit =
339344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::new_space_allocation_limit_address(isolate());
33946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
33956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Register top_reg = result_end.is_valid() ? result_end : result;
33966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
33971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (!top_reg.is(result)) {
33981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    movq(top_reg, result);
33996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
34001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addq(top_reg, Immediate(object_size));
34011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  j(carry, gc_required);
340244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Operand limit_operand = ExternalOperand(new_space_allocation_limit);
340344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  cmpq(top_reg, limit_operand);
3404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(above, gc_required);
3405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update allocation top.
34076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  UpdateAllocationTopHelper(top_reg, scratch);
3408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
34096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (top_reg.is(result)) {
34106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if ((flags & TAG_OBJECT) != 0) {
34116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      subq(result, Immediate(object_size - kHeapObjectTag));
34126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
34136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      subq(result, Immediate(object_size));
34146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
34156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else if ((flags & TAG_OBJECT) != 0) {
34166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Tag the result if requested.
3417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    addq(result, Immediate(kHeapObjectTag));
3418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(int header_size,
3423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        ScaleFactor element_size,
3424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register element_count,
3425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register result,
3426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register result_end,
3427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch,
3428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Label* gc_required,
3429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        AllocationFlags flags) {
34305913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  if (!FLAG_inline_new) {
343144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (emit_debug_code()) {
34325913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // Trash the registers to simulate an allocation failure.
34335913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      movl(result, Immediate(0x7091));
34345913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      movl(result_end, Immediate(0x7191));
34355913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (scratch.is_valid()) {
34365913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        movl(scratch, Immediate(0x7291));
34375913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
34385913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // Register element_count is not modified by the function.
34395913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    }
34405913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    jmp(gc_required);
34415913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    return;
34425913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
3443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!result.is(result_end));
3444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load address of new object into result.
34468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LoadAllocationTopHelper(result, scratch, flags);
3447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate new top and bail out if new space is exhausted.
3449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference new_space_allocation_limit =
345044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::new_space_allocation_limit_address(isolate());
34511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // We assume that element_count*element_size + header_size does not
34531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // overflow.
34541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  lea(result_end, Operand(element_count, element_size, header_size));
34551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addq(result_end, result);
34561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  j(carry, gc_required);
345744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Operand limit_operand = ExternalOperand(new_space_allocation_limit);
345844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  cmpq(result_end, limit_operand);
3459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(above, gc_required);
3460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update allocation top.
3462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  UpdateAllocationTopHelper(result_end, scratch);
3463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Tag the result if requested.
3465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((flags & TAG_OBJECT) != 0) {
3466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    addq(result, Immediate(kHeapObjectTag));
3467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(Register object_size,
3472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register result,
3473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register result_end,
3474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch,
3475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Label* gc_required,
3476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        AllocationFlags flags) {
34775913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  if (!FLAG_inline_new) {
347844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (emit_debug_code()) {
34795913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // Trash the registers to simulate an allocation failure.
34805913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      movl(result, Immediate(0x7091));
34815913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      movl(result_end, Immediate(0x7191));
34825913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (scratch.is_valid()) {
34835913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        movl(scratch, Immediate(0x7291));
34845913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
34855913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // object_size is left unchanged by this function.
34865913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    }
34875913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    jmp(gc_required);
34885913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    return;
34895913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
34905913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  ASSERT(!result.is(result_end));
34915913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck
3492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load address of new object into result.
34938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LoadAllocationTopHelper(result, scratch, flags);
3494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate new top and bail out if new space is exhausted.
3496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference new_space_allocation_limit =
349744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::new_space_allocation_limit_address(isolate());
3498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!object_size.is(result_end)) {
3499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(result_end, object_size);
3500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addq(result_end, result);
35021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  j(carry, gc_required);
350344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Operand limit_operand = ExternalOperand(new_space_allocation_limit);
350444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  cmpq(result_end, limit_operand);
3505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(above, gc_required);
3506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update allocation top.
3508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  UpdateAllocationTopHelper(result_end, scratch);
3509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Tag the result if requested.
3511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((flags & TAG_OBJECT) != 0) {
3512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    addq(result, Immediate(kHeapObjectTag));
3513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::UndoAllocationInNewSpace(Register object) {
3518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference new_space_allocation_top =
351944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::new_space_allocation_top_address(isolate());
3520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure the object has no tag before resetting top.
3522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  and_(object, Immediate(~kHeapObjectTagMask));
352344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Operand top_operand = ExternalOperand(new_space_allocation_top);
3524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
352544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  cmpq(object, top_operand);
3526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Check(below, "Undo allocation of non allocated memory");
3527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
352844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  movq(top_operand, object);
3529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
35323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::AllocateHeapNumber(Register result,
35333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                        Register scratch,
35343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                        Label* gc_required) {
35353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Allocate heap number in new space.
35363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  AllocateInNewSpace(HeapNumber::kSize,
35373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                     result,
35383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                     scratch,
35393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                     no_reg,
35403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                     gc_required,
35413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                     TAG_OBJECT);
35423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
35433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Set the map.
35443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  LoadRoot(kScratchRegister, Heap::kHeapNumberMapRootIndex);
35453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
35463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
35473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
35483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3549e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::AllocateTwoByteString(Register result,
3550e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                           Register length,
3551e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                           Register scratch1,
3552e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                           Register scratch2,
3553e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                           Register scratch3,
3554e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                           Label* gc_required) {
3555e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Calculate the number of bytes needed for the characters in the string while
3556e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // observing object alignment.
35576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const int kHeaderAlignment = SeqTwoByteString::kHeaderSize &
35586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               kObjectAlignmentMask;
3559e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(kShortSize == 2);
3560e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // scratch1 = length * 2 + kObjectAlignmentMask.
35616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  lea(scratch1, Operand(length, length, times_1, kObjectAlignmentMask +
35626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                kHeaderAlignment));
3563e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  and_(scratch1, Immediate(~kObjectAlignmentMask));
35646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (kHeaderAlignment > 0) {
35656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    subq(scratch1, Immediate(kHeaderAlignment));
35666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3567e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3568e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Allocate two byte string in new space.
3569e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  AllocateInNewSpace(SeqTwoByteString::kHeaderSize,
3570e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     times_1,
3571e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch1,
3572e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     result,
3573e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch2,
3574e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch3,
3575e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     gc_required,
3576e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     TAG_OBJECT);
3577e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3578e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Set the map, length and hash field.
3579e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LoadRoot(kScratchRegister, Heap::kStringMapRootIndex);
3580e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
35816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Integer32ToSmi(scratch1, length);
35826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  movq(FieldOperand(result, String::kLengthOffset), scratch1);
35837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  movq(FieldOperand(result, String::kHashFieldOffset),
3584e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke       Immediate(String::kEmptyHashField));
3585e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3586e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3587e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3588e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::AllocateAsciiString(Register result,
3589e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                         Register length,
3590e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                         Register scratch1,
3591e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                         Register scratch2,
3592e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                         Register scratch3,
3593e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                         Label* gc_required) {
3594e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Calculate the number of bytes needed for the characters in the string while
3595e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // observing object alignment.
35966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const int kHeaderAlignment = SeqAsciiString::kHeaderSize &
35976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               kObjectAlignmentMask;
3598e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movl(scratch1, length);
3599e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(kCharSize == 1);
36006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  addq(scratch1, Immediate(kObjectAlignmentMask + kHeaderAlignment));
3601e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  and_(scratch1, Immediate(~kObjectAlignmentMask));
36026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (kHeaderAlignment > 0) {
36036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    subq(scratch1, Immediate(kHeaderAlignment));
36046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3605e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3606e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Allocate ascii string in new space.
3607e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  AllocateInNewSpace(SeqAsciiString::kHeaderSize,
3608e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     times_1,
3609e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch1,
3610e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     result,
3611e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch2,
3612e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch3,
3613e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     gc_required,
3614e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     TAG_OBJECT);
3615e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3616e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Set the map, length and hash field.
3617e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LoadRoot(kScratchRegister, Heap::kAsciiStringMapRootIndex);
3618e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
36196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Integer32ToSmi(scratch1, length);
36206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  movq(FieldOperand(result, String::kLengthOffset), scratch1);
36217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  movq(FieldOperand(result, String::kHashFieldOffset),
3622e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke       Immediate(String::kEmptyHashField));
3623e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3624e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3625e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3626e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::AllocateConsString(Register result,
3627e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                        Register scratch1,
3628e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                        Register scratch2,
3629e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                        Label* gc_required) {
3630e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Allocate heap number in new space.
3631e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  AllocateInNewSpace(ConsString::kSize,
3632e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     result,
3633e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch1,
3634e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch2,
3635e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     gc_required,
3636e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     TAG_OBJECT);
3637e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3638e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Set the map. The other fields are left uninitialized.
3639e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LoadRoot(kScratchRegister, Heap::kConsStringMapRootIndex);
3640e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
3641e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3642e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3643e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3644e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::AllocateAsciiConsString(Register result,
3645e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                             Register scratch1,
3646e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                             Register scratch2,
3647e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                             Label* gc_required) {
3648e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Allocate heap number in new space.
3649e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  AllocateInNewSpace(ConsString::kSize,
3650e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     result,
3651e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch1,
3652e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch2,
3653e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     gc_required,
3654e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     TAG_OBJECT);
3655e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3656e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Set the map. The other fields are left uninitialized.
3657e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LoadRoot(kScratchRegister, Heap::kConsAsciiStringMapRootIndex);
3658e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
3659e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3660e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3661e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
366244f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Copy memory, byte-by-byte, from source to destination.  Not optimized for
366344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// long or aligned copies.  The contents of scratch and length are destroyed.
366444f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Destination is incremented by length, source, length and scratch are
366544f0eee88ff00398ff7f715fab053374d808c90dSteve Block// clobbered.
366644f0eee88ff00398ff7f715fab053374d808c90dSteve Block// A simpler loop is faster on small copies, but slower on large ones.
366744f0eee88ff00398ff7f715fab053374d808c90dSteve Block// The cld() instruction must have been emitted, to set the direction flag(),
366844f0eee88ff00398ff7f715fab053374d808c90dSteve Block// before calling this function.
366944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CopyBytes(Register destination,
367044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               Register source,
367144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               Register length,
367244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               int min_length,
367344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               Register scratch) {
367444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(min_length >= 0);
367544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (FLAG_debug_code) {
367644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    cmpl(length, Immediate(min_length));
367744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Assert(greater_equal, "Invalid min_length");
367844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
367944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label loop, done, short_string, short_loop;
368044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
368144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const int kLongStringLimit = 20;
368244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (min_length <= kLongStringLimit) {
368344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    cmpl(length, Immediate(kLongStringLimit));
368444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    j(less_equal, &short_string);
368544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
368644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
368744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(source.is(rsi));
368844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(destination.is(rdi));
368944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(length.is(rcx));
369044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
369144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Because source is 8-byte aligned in our uses of this function,
369244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // we keep source aligned for the rep movs operation by copying the odd bytes
369344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // at the end of the ranges.
369444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  movq(scratch, length);
369544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  shrl(length, Immediate(3));
369644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  repmovsq();
369744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Move remaining bytes of length.
369844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  andl(scratch, Immediate(0x7));
369944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  movq(length, Operand(source, scratch, times_1, -8));
370044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  movq(Operand(destination, scratch, times_1, -8), length);
370144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  addq(destination, scratch);
370244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
370344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (min_length <= kLongStringLimit) {
370444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    jmp(&done);
370544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
370644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    bind(&short_string);
370744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (min_length == 0) {
370844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      testl(length, length);
370944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      j(zero, &done);
371044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
371144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    lea(scratch, Operand(destination, length, times_1, 0));
371244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
371344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    bind(&short_loop);
371444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    movb(length, Operand(source, 0));
371544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    movb(Operand(destination, 0), length);
371644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    incq(source);
371744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    incq(destination);
371844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    cmpq(destination, scratch);
371944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    j(not_equal, &short_loop);
372044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
372144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    bind(&done);
372244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
372344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
372444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
372544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3726d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::LoadContext(Register dst, int context_chain_length) {
3727d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (context_chain_length > 0) {
3728d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Move up the chain of contexts to the context containing the slot.
37293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    movq(dst, Operand(rsi, Context::SlotOffset(Context::PREVIOUS_INDEX)));
3730d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    for (int i = 1; i < context_chain_length; i++) {
37313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      movq(dst, Operand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX)));
3732d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
3733e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
3734e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Slot is in the current function context.  Move it into the
3735e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // destination register in case we store into it (the write barrier
3736e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // cannot be allowed to destroy the context in rsi).
3737e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    movq(dst, rsi);
3738e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
3739e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
37403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // We should not have found a with context by walking the context
37413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // chain (i.e., the static scope chain and runtime context chain do
37423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // not agree).  A variable occurring in such a scope should have
37433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // slot type LOOKUP and not CONTEXT.
374444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
37453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    CompareRoot(FieldOperand(dst, HeapObject::kMapOffset),
37463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                Heap::kWithContextMapRootIndex);
37473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Check(not_equal, "Variable resolved to with context.");
3748d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
3749d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
3750d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
375144f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef _WIN64
375244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic const int kRegisterPassedArguments = 4;
375344f0eee88ff00398ff7f715fab053374d808c90dSteve Block#else
375444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic const int kRegisterPassedArguments = 6;
375544f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
37567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid MacroAssembler::LoadGlobalFunction(int index, Register function) {
3758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Load the global or builtins object from the current context.
3759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  movq(function, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
3760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Load the global context from the global or builtins object.
3761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  movq(function, FieldOperand(function, GlobalObject::kGlobalContextOffset));
3762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Load the function from the global context.
3763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  movq(function, Operand(function, Context::SlotOffset(index)));
3764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
3768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  Register map) {
3769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Load the initial map.  The global functions all have initial maps.
3770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  movq(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
377144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
3772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Label ok, fail;
3773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CheckMap(map, isolate()->factory()->meta_map(), &fail, DO_SMI_CHECK);
3774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    jmp(&ok);
3775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    bind(&fail);
3776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Abort("Global functions must have initial map");
3777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    bind(&ok);
3778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
37824515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkeint MacroAssembler::ArgumentStackSlotsForCFunctionCall(int num_arguments) {
37837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // On Windows 64 stack slots are reserved by the caller for all arguments
37847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // including the ones passed in registers, and space is always allocated for
37857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // the four register arguments even if the function takes fewer than four
37867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // arguments.
37877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // On AMD64 ABI (Linux/Mac) the first six arguments are passed in registers
37887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // and the caller does not reserve stack slots for them.
37894515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  ASSERT(num_arguments >= 0);
37904515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke#ifdef _WIN64
379144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const int kMinimumStackSlots = kRegisterPassedArguments;
37927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (num_arguments < kMinimumStackSlots) return kMinimumStackSlots;
37937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  return num_arguments;
37944515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke#else
37957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (num_arguments < kRegisterPassedArguments) return 0;
37967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  return num_arguments - kRegisterPassedArguments;
37974515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke#endif
37984515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
37994515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
38007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
38014515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid MacroAssembler::PrepareCallCFunction(int num_arguments) {
38024515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  int frame_alignment = OS::ActivationFrameAlignment();
38034515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  ASSERT(frame_alignment != 0);
38044515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  ASSERT(num_arguments >= 0);
380544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
38064515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // Make stack end at alignment and allocate space for arguments and old rsp.
38074515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  movq(kScratchRegister, rsp);
38084515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  ASSERT(IsPowerOf2(frame_alignment));
38094515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  int argument_slots_on_stack =
38104515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      ArgumentStackSlotsForCFunctionCall(num_arguments);
38114515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  subq(rsp, Immediate((argument_slots_on_stack + 1) * kPointerSize));
38124515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  and_(rsp, Immediate(-frame_alignment));
38134515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  movq(Operand(rsp, argument_slots_on_stack * kPointerSize), kScratchRegister);
38144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
38154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
38164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
38174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid MacroAssembler::CallCFunction(ExternalReference function,
38184515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                                   int num_arguments) {
381944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(rax, function);
38204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  CallCFunction(rax, num_arguments);
38214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
38224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
38234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
38244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid MacroAssembler::CallCFunction(Register function, int num_arguments) {
38256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check stack alignment.
382644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
38276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CheckStackAlignment();
38286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
38296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
38304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  call(function);
38314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  ASSERT(OS::ActivationFrameAlignment() != 0);
38324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  ASSERT(num_arguments >= 0);
38334515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  int argument_slots_on_stack =
38344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      ArgumentStackSlotsForCFunctionCall(num_arguments);
38354515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  movq(rsp, Operand(rsp, argument_slots_on_stack * kPointerSize));
38364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
38374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
3838d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCodePatcher::CodePatcher(byte* address, int size)
38408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    : address_(address),
38418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      size_(size),
38428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      masm_(Isolate::Current(), address, size + Assembler::kGap) {
3843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a new macro assembler pointing to the address of the code to patch.
3844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The size is adjusted with kGap on order for the assembler to generate size
3845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // bytes of instructions without failing with buffer size constraints.
3846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
3847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCodePatcher::~CodePatcher() {
3851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Indicate that code has changed.
3852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CPU::FlushICache(address_, size_);
3853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the code was patched as expected.
3855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(masm_.pc_ == address_ + size_);
3856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
3857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
3860f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3861f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_X64
3862