1f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com// Copyright 2012 the V8 project authors. All rights reserved.
25ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// Redistribution and use in source and binary forms, with or without
35ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// modification, are permitted provided that the following conditions are
45ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// met:
55ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org//
65ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org//     * Redistributions of source code must retain the above copyright
75ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org//       notice, this list of conditions and the following disclaimer.
85ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org//     * Redistributions in binary form must reproduce the above
95ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org//       copyright notice, this list of conditions and the following
105ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org//       disclaimer in the documentation and/or other materials provided
115ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org//       with the distribution.
125ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org//     * Neither the name of Google Inc. nor the names of its
135ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org//       contributors may be used to endorse or promote products derived
145ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org//       from this software without specific prior written permission.
155ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org//
165ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
175ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
185ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
195ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
205ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
215ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
225ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
235ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
245ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
265ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org
2871affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org#include "v8.h"
2971affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org
3093a47f4837f2137c8d8349250fd8e91da3108126jkummerow@chromium.org#if V8_TARGET_ARCH_X64
319dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
3271affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org#include "bootstrapper.h"
3344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org#include "codegen.h"
34c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org#include "cpu-profiler.h"
35eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org#include "assembler-x64.h"
36e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org#include "macro-assembler-x64.h"
37b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org#include "serialize.h"
38eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org#include "debug.h"
395ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org#include "heap.h"
40ed29eb2bdad388c1ce751d68bd4fe6f4f5a7cbc8machenbach@chromium.org#include "isolate-inl.h"
4171affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org
4271affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgnamespace v8 {
4371affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgnamespace internal {
4471affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org
45c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.orgMacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size)
46c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org    : Assembler(arg_isolate, buffer, size),
479d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com      generating_stub_(false),
48c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      has_frame_(false),
49c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org      root_array_available_(true) {
50c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  if (isolate() != NULL) {
51c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org    code_object_ = Handle<Object>(isolate()->heap()->undefined_value(),
52c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org                                  isolate());
53c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  }
54ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org}
55ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
56ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
57000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.orgstatic const int kInvalidRootRegisterDelta = -1;
58000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.org
59000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.org
60000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.orgintptr_t MacroAssembler::RootRegisterDelta(ExternalReference other) {
61000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.org  if (predictable_code_size() &&
62000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.org      (other.address() < reinterpret_cast<Address>(isolate()) ||
63000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.org       other.address() >= reinterpret_cast<Address>(isolate() + 1))) {
64000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.org    return kInvalidRootRegisterDelta;
65000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.org  }
66ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  Address roots_register_value = kRootRegisterBias +
67000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.org      reinterpret_cast<Address>(isolate()->heap()->roots_array_start());
68ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  intptr_t delta = other.address() - roots_register_value;
69ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  return delta;
70ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org}
71ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
72ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
73ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgOperand MacroAssembler::ExternalOperand(ExternalReference target,
74ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org                                        Register scratch) {
75ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  if (root_array_available_ && !Serializer::enabled()) {
76000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.org    intptr_t delta = RootRegisterDelta(target);
77000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.org    if (delta != kInvalidRootRegisterDelta && is_int32(delta)) {
78ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      Serializer::TooLateToEnableNow();
797979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org      return Operand(kRootRegister, static_cast<int32_t>(delta));
80ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    }
81ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  }
82e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  Move(scratch, target);
83ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  return Operand(scratch, 0);
84ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org}
85ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
86ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
87ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgvoid MacroAssembler::Load(Register destination, ExternalReference source) {
88ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  if (root_array_available_ && !Serializer::enabled()) {
89000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.org    intptr_t delta = RootRegisterDelta(source);
90000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.org    if (delta != kInvalidRootRegisterDelta && is_int32(delta)) {
91ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      Serializer::TooLateToEnableNow();
92ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      movq(destination, Operand(kRootRegister, static_cast<int32_t>(delta)));
93ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      return;
94ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    }
95ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  }
96ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // Safe code.
97ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  if (destination.is(rax)) {
98ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    load_rax(source);
99ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  } else {
100e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    Move(kScratchRegister, source);
101ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    movq(destination, Operand(kScratchRegister, 0));
102ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  }
103ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org}
104ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
105ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
106ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgvoid MacroAssembler::Store(ExternalReference destination, Register source) {
107ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  if (root_array_available_ && !Serializer::enabled()) {
108000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.org    intptr_t delta = RootRegisterDelta(destination);
109000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.org    if (delta != kInvalidRootRegisterDelta && is_int32(delta)) {
110ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      Serializer::TooLateToEnableNow();
111ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      movq(Operand(kRootRegister, static_cast<int32_t>(delta)), source);
112ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      return;
113ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    }
114ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  }
115ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // Safe code.
116ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  if (source.is(rax)) {
117ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    store_rax(destination);
118ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  } else {
119e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    Move(kScratchRegister, destination);
120ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    movq(Operand(kScratchRegister, 0), source);
121ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  }
122ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org}
123ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
124ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
125ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgvoid MacroAssembler::LoadAddress(Register destination,
126ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org                                 ExternalReference source) {
127ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  if (root_array_available_ && !Serializer::enabled()) {
128000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.org    intptr_t delta = RootRegisterDelta(source);
129000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.org    if (delta != kInvalidRootRegisterDelta && is_int32(delta)) {
130ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      Serializer::TooLateToEnableNow();
131ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      lea(destination, Operand(kRootRegister, static_cast<int32_t>(delta)));
132ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      return;
133ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    }
134ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  }
135ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // Safe code.
136e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  Move(destination, source);
137ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org}
138ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
139ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
140ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgint MacroAssembler::LoadAddressSize(ExternalReference source) {
141ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  if (root_array_available_ && !Serializer::enabled()) {
142ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    // This calculation depends on the internals of LoadAddress.
143ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    // It's correctness is ensured by the asserts in the Call
144ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    // instruction below.
145000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.org    intptr_t delta = RootRegisterDelta(source);
146000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.org    if (delta != kInvalidRootRegisterDelta && is_int32(delta)) {
147ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      Serializer::TooLateToEnableNow();
148ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      // Operand is lea(scratch, Operand(kRootRegister, delta));
149ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      // Opcodes : REX.W 8D ModRM Disp8/Disp32  - 4 or 7.
150ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      int size = 4;
151ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      if (!is_int8(static_cast<int32_t>(delta))) {
152ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org        size += 3;  // Need full four-byte displacement in lea.
153ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      }
154ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      return size;
155ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    }
156ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  }
157ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // Size of movq(destination, src);
158594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  return Assembler::kMoveAddressIntoScratchRegisterInstructionLength;
15971affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org}
16071affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org
161e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
162ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.comvoid MacroAssembler::PushAddress(ExternalReference source) {
163ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  int64_t address = reinterpret_cast<int64_t>(source.address());
164ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  if (is_int32(address) && !Serializer::enabled()) {
165ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com    if (emit_debug_code()) {
166e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org      movq(kScratchRegister, kZapValue, RelocInfo::NONE64);
167ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com    }
168ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com    push(Immediate(static_cast<int32_t>(address)));
169ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com    return;
170ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  }
171ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  LoadAddress(kScratchRegister, source);
172ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  push(kScratchRegister);
173ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com}
174ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com
175ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com
1769d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.comvoid MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index) {
177ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  ASSERT(root_array_available_);
1788f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  movq(destination, Operand(kRootRegister,
1798f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org                            (index << kPointerSizeLog2) - kRootRegisterBias));
1808f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org}
1818f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org
1828f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org
1838f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.orgvoid MacroAssembler::LoadRootIndexed(Register destination,
1848f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org                                     Register variable_offset,
1858f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org                                     int fixed_offset) {
186ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  ASSERT(root_array_available_);
1878f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  movq(destination,
1888f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org       Operand(kRootRegister,
1898f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org               variable_offset, times_pointer_size,
1908f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org               (fixed_offset << kPointerSizeLog2) - kRootRegisterBias));
19118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
19218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
19318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
194720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.orgvoid MacroAssembler::StoreRoot(Register source, Heap::RootListIndex index) {
195ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  ASSERT(root_array_available_);
1968f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  movq(Operand(kRootRegister, (index << kPointerSizeLog2) - kRootRegisterBias),
1978f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org       source);
198720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org}
199720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org
200720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org
20118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid MacroAssembler::PushRoot(Heap::RootListIndex index) {
202ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  ASSERT(root_array_available_);
2038f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  push(Operand(kRootRegister, (index << kPointerSizeLog2) - kRootRegisterBias));
20418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
20518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
20618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
2079d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.comvoid MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) {
208ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  ASSERT(root_array_available_);
2098f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  cmpq(with, Operand(kRootRegister,
2108f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org                     (index << kPointerSizeLog2) - kRootRegisterBias));
21118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
21218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
213b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org
21483aa54905e559090bea7771b83f188762cfcf082ricow@chromium.orgvoid MacroAssembler::CompareRoot(const Operand& with,
21583aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org                                 Heap::RootListIndex index) {
216ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  ASSERT(root_array_available_);
21783aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  ASSERT(!with.AddressUsesRegister(kScratchRegister));
218c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  LoadRoot(kScratchRegister, index);
219c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  cmpq(with, kScratchRegister);
220c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org}
221c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org
222c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org
223c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid MacroAssembler::RememberedSetHelper(Register object,  // For debug tests.
224c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                         Register addr,
225c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                         Register scratch,
226c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                         SaveFPRegsMode save_fp,
227c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                         RememberedSetFinalAction and_then) {
228000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.org  if (emit_debug_code()) {
229c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Label ok;
230c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    JumpIfNotInNewSpace(object, scratch, &ok, Label::kNear);
231c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    int3();
232c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    bind(&ok);
233c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
234c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Load store buffer top.
235c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  LoadRoot(scratch, Heap::kStoreBufferTopRootIndex);
236c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Store pointer to buffer.
237c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  movq(Operand(scratch, 0), addr);
238c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Increment buffer top.
239c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  addq(scratch, Immediate(kPointerSize));
240c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Write back new top of buffer.
241c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  StoreRoot(scratch, Heap::kStoreBufferTopRootIndex);
242c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Call stub on end of buffer.
243c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Label done;
244c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Check for end of buffer.
245c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  testq(scratch, Immediate(StoreBuffer::kStoreBufferOverflowBit));
246c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (and_then == kReturnAtEnd) {
247c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Label buffer_overflowed;
248c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    j(not_equal, &buffer_overflowed, Label::kNear);
249c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    ret(0);
250c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    bind(&buffer_overflowed);
251c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  } else {
252c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    ASSERT(and_then == kFallThroughAtEnd);
253c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    j(equal, &done, Label::kNear);
254c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
255c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  StoreBufferOverflowStub store_buffer_overflow =
256c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      StoreBufferOverflowStub(save_fp);
257c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  CallStub(&store_buffer_overflow);
258c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (and_then == kReturnAtEnd) {
259c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    ret(0);
260c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  } else {
261c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    ASSERT(and_then == kFallThroughAtEnd);
262c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    bind(&done);
263ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  }
26430ce411529579186181838984710b0b0980857aaricow@chromium.org}
26530ce411529579186181838984710b0b0980857aaricow@chromium.org
26630ce411529579186181838984710b0b0980857aaricow@chromium.org
26783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgvoid MacroAssembler::InNewSpace(Register object,
26883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                Register scratch,
26983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                Condition cc,
27083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                Label* branch,
271c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                Label::Distance distance) {
27283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  if (Serializer::enabled()) {
27383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    // Can't do arithmetic on external references if it might get serialized.
27483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    // The mask isn't really an address.  We load it as an external reference in
27583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    // case the size of the new space is different between the snapshot maker
27683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    // and the running system.
27783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    if (scratch.is(object)) {
278e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org      Move(kScratchRegister, ExternalReference::new_space_mask(isolate()));
27983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      and_(scratch, kScratchRegister);
28083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    } else {
281e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org      Move(scratch, ExternalReference::new_space_mask(isolate()));
28283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      and_(scratch, object);
28383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    }
284e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    Move(kScratchRegister, ExternalReference::new_space_start(isolate()));
28583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    cmpq(scratch, kScratchRegister);
286c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    j(cc, branch, distance);
28783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  } else {
288c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org    ASSERT(is_int32(static_cast<int64_t>(isolate()->heap()->NewSpaceMask())));
28983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    intptr_t new_space_start =
290c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org        reinterpret_cast<intptr_t>(isolate()->heap()->NewSpaceStart());
291e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    movq(kScratchRegister, reinterpret_cast<Address>(-new_space_start),
292e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org         RelocInfo::NONE64);
29383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    if (scratch.is(object)) {
29483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      addq(scratch, kScratchRegister);
29583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    } else {
29683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      lea(scratch, Operand(object, kScratchRegister, times_1, 0));
29783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    }
298c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org    and_(scratch,
299c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org         Immediate(static_cast<int32_t>(isolate()->heap()->NewSpaceMask())));
300c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    j(cc, branch, distance);
30183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  }
30283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
30383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
30483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
305c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid MacroAssembler::RecordWriteField(
306c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Register object,
307c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    int offset,
308c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Register value,
309c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Register dst,
310c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    SaveFPRegsMode save_fp,
311c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    RememberedSetAction remembered_set_action,
312c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    SmiCheck smi_check) {
31330ce411529579186181838984710b0b0980857aaricow@chromium.org  // First, check if a write barrier is even needed. The tests below
314c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // catch stores of Smis.
315b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org  Label done;
316b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org
317c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Skip barrier if writing a smi.
318c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (smi_check == INLINE_SMI_CHECK) {
319c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    JumpIfSmi(value, &done);
320c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
321c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
322c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Although the object register is tagged, the offset is relative to the start
323c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // of the object, so so offset must be a multiple of kPointerSize.
324c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(IsAligned(offset, kPointerSize));
325c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
326c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  lea(dst, FieldOperand(object, offset));
327c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (emit_debug_code()) {
328c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Label ok;
329c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    testb(dst, Immediate((1 << kPointerSizeLog2) - 1));
330c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    j(zero, &ok, Label::kNear);
331c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    int3();
332c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    bind(&ok);
333c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
334c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
335c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  RecordWrite(
336c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      object, dst, value, save_fp, remembered_set_action, OMIT_SMI_CHECK);
337c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
3389d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  bind(&done);
339b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
340c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Clobber clobbered input registers when running with the debug-code flag
341c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // turned on to provoke errors.
342badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  if (emit_debug_code()) {
343e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    movq(value, kZapValue, RelocInfo::NONE64);
344e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    movq(dst, kZapValue, RelocInfo::NONE64);
345b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
3469d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com}
3479d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
3489d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
349394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.comvoid MacroAssembler::RecordWriteArray(Register object,
350394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                      Register value,
351394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                      Register index,
352394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                      SaveFPRegsMode save_fp,
353394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                      RememberedSetAction remembered_set_action,
354394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                      SmiCheck smi_check) {
355394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // First, check if a write barrier is even needed. The tests below
356394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // catch stores of Smis.
357394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  Label done;
358394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
359394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Skip barrier if writing a smi.
360394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  if (smi_check == INLINE_SMI_CHECK) {
361394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    JumpIfSmi(value, &done);
362394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  }
363394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
364394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Array access: calculate the destination address. Index is not a smi.
365394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  Register dst = index;
366394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  lea(dst, Operand(object, index, times_pointer_size,
367394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                   FixedArray::kHeaderSize - kHeapObjectTag));
368394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
369394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  RecordWrite(
370394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      object, dst, value, save_fp, remembered_set_action, OMIT_SMI_CHECK);
371394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
372394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  bind(&done);
373394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
374394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Clobber clobbered input registers when running with the debug-code flag
375394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // turned on to provoke errors.
376394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  if (emit_debug_code()) {
377e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    movq(value, kZapValue, RelocInfo::NONE64);
378e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    movq(index, kZapValue, RelocInfo::NONE64);
379394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  }
380394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com}
381394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
382394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
38369ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.orgvoid MacroAssembler::RecordWrite(Register object,
38469ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org                                 Register address,
385c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                 Register value,
386c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                 SaveFPRegsMode fp_mode,
387c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                 RememberedSetAction remembered_set_action,
388c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                 SmiCheck smi_check) {
389c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(!object.is(value));
390c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(!object.is(address));
391c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(!value.is(address));
392c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  AssertNotSmi(object);
393c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
394c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (remembered_set_action == OMIT_REMEMBERED_SET &&
395c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      !FLAG_incremental_marking) {
396c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    return;
39769ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  }
39869ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org
399000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.org  if (emit_debug_code()) {
400c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Label ok;
401c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    cmpq(value, Operand(address, 0));
402c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    j(equal, &ok, Label::kNear);
403c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    int3();
404c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    bind(&ok);
405c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
40669ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org
407f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  // Count number of write barriers in generated code.
408f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  isolate()->counters()->write_barriers_static()->Increment();
409f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1);
410f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org
411c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // First, check if a write barrier is even needed. The tests below
412c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // catch stores of smis and stores into the young generation.
4139d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  Label done;
414b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
415c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (smi_check == INLINE_SMI_CHECK) {
416c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Skip barrier if writing a smi.
417c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    JumpIfSmi(value, &done);
418b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
419b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
420c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  CheckPageFlag(value,
421c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                value,  // Used as scratch.
422c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                MemoryChunk::kPointersToHereAreInterestingMask,
423c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                zero,
424c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                &done,
425c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                Label::kNear);
426b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org
427c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  CheckPageFlag(object,
428c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                value,  // Used as scratch.
429c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                MemoryChunk::kPointersFromHereAreInterestingMask,
430c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                zero,
431c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                &done,
432c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                Label::kNear);
433e88a9edffbbdbc4ccc9872560ac4d9ea6b188fbdwhesse@chromium.org
434c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  RecordWriteStub stub(object, value, address, remembered_set_action, fp_mode);
435c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  CallStub(&stub);
436b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org
437b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org  bind(&done);
438b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
439c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Clobber clobbered registers when running with the debug-code flag
440b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // turned on to provoke errors.
441badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  if (emit_debug_code()) {
442e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    movq(address, kZapValue, RelocInfo::NONE64);
443e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    movq(value, kZapValue, RelocInfo::NONE64);
444b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
4455aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org}
4465aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
447c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
448594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.orgvoid MacroAssembler::Assert(Condition cc, BailoutReason reason) {
449594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  if (emit_debug_code()) Check(cc, reason);
450eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org}
451eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
452eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
4530b9f850f0e9dc624b9e0c5254393112ecc7f8bc9ricow@chromium.orgvoid MacroAssembler::AssertFastElements(Register elements) {
454badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  if (emit_debug_code()) {
45583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Label ok;
4560b9f850f0e9dc624b9e0c5254393112ecc7f8bc9ricow@chromium.org    CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
4570b9f850f0e9dc624b9e0c5254393112ecc7f8bc9ricow@chromium.org                Heap::kFixedArrayMapRootIndex);
45883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    j(equal, &ok, Label::kNear);
4590b9f850f0e9dc624b9e0c5254393112ecc7f8bc9ricow@chromium.org    CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
46084bcc559ac20fb04f806e97d28a314b20b58fd60svenpanne@chromium.org                Heap::kFixedDoubleArrayMapRootIndex);
46184bcc559ac20fb04f806e97d28a314b20b58fd60svenpanne@chromium.org    j(equal, &ok, Label::kNear);
46284bcc559ac20fb04f806e97d28a314b20b58fd60svenpanne@chromium.org    CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
4630b9f850f0e9dc624b9e0c5254393112ecc7f8bc9ricow@chromium.org                Heap::kFixedCOWArrayMapRootIndex);
46483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    j(equal, &ok, Label::kNear);
465594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    Abort(kJSObjectWithFastElementsMapHasSlowElements);
4660b9f850f0e9dc624b9e0c5254393112ecc7f8bc9ricow@chromium.org    bind(&ok);
4670b9f850f0e9dc624b9e0c5254393112ecc7f8bc9ricow@chromium.org  }
4680b9f850f0e9dc624b9e0c5254393112ecc7f8bc9ricow@chromium.org}
4690b9f850f0e9dc624b9e0c5254393112ecc7f8bc9ricow@chromium.org
4700b9f850f0e9dc624b9e0c5254393112ecc7f8bc9ricow@chromium.org
471594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.orgvoid MacroAssembler::Check(Condition cc, BailoutReason reason) {
47283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label L;
47383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  j(cc, &L, Label::kNear);
474594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  Abort(reason);
475c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Control will not return here.
476eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  bind(&L);
477eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org}
478eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
479eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
480c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.orgvoid MacroAssembler::CheckStackAlignment() {
481c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org  int frame_alignment = OS::ActivationFrameAlignment();
482c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org  int frame_alignment_mask = frame_alignment - 1;
483c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org  if (frame_alignment > kPointerSize) {
484c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org    ASSERT(IsPowerOf2(frame_alignment));
48583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Label alignment_as_expected;
486c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org    testq(rsp, Immediate(frame_alignment_mask));
48783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    j(zero, &alignment_as_expected, Label::kNear);
488c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org    // Abort if stack is not aligned.
489c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org    int3();
490c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org    bind(&alignment_as_expected);
491c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org  }
492c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org}
493c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org
494c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org
4955aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.orgvoid MacroAssembler::NegativeZeroTest(Register result,
4965aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org                                      Register op,
4975aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org                                      Label* then_label) {
49883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label ok;
4990b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  testl(result, result);
50083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  j(not_zero, &ok, Label::kNear);
5010b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  testl(op, op);
5025aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  j(sign, then_label);
5035aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  bind(&ok);
5045aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org}
5055aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
5065aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
507594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.orgvoid MacroAssembler::Abort(BailoutReason reason) {
508eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // We want to pass the msg string like a smi to avoid GC
509eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // problems, however msg is not guaranteed to be aligned
510eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // properly. Instead, we pass an aligned pointer that is
511eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // a proper v8 smi, but also pass the alignment difference
512eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // from the real pointer as a smi.
513594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  const char* msg = GetBailoutReason(reason);
514eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  intptr_t p1 = reinterpret_cast<intptr_t>(msg);
515eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  intptr_t p0 = (p1 & ~kSmiTagMask) + kSmiTag;
516f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // Note: p0 might not be a valid Smi _value_, but it has a valid Smi tag.
517eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  ASSERT(reinterpret_cast<Object*>(p0)->IsSmi());
518eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org#ifdef DEBUG
519eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  if (msg != NULL) {
520eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    RecordComment("Abort message: ");
521eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    RecordComment(msg);
522eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  }
5231e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
5241e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  if (FLAG_trap_on_abort) {
5251e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org    int3();
5261e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org    return;
5271e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  }
528eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org#endif
5291e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
530eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  push(rax);
531e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  movq(kScratchRegister, reinterpret_cast<Smi*>(p0), RelocInfo::NONE64);
532eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  push(kScratchRegister);
533e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  movq(kScratchRegister, Smi::FromInt(static_cast<int>(p1 - p0)),
5344cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org       RelocInfo::NONE64);
535eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  push(kScratchRegister);
536c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
537c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (!has_frame_) {
538c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // We don't actually want to generate a pile of code for this, so just
539c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // claim there is a stack frame, without generating one.
540c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    FrameScope scope(this, StackFrame::NONE);
541c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    CallRuntime(Runtime::kAbort, 2);
542c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  } else {
543c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    CallRuntime(Runtime::kAbort, 2);
544c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
545c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Control will not return here.
546ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org  int3();
547eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org}
548eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
549eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
550471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.orgvoid MacroAssembler::CallStub(CodeStub* stub, TypeFeedbackId ast_id) {
551c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(AllowThisStubCall(stub));  // Calls are not allowed in some stubs
5528432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  Call(stub->GetCode(isolate()), RelocInfo::CODE_TARGET, ast_id);
553eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org}
554eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
555eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
55613bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.orgvoid MacroAssembler::TailCallStub(CodeStub* stub) {
5578432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  Jump(stub->GetCode(isolate()), RelocInfo::CODE_TARGET);
55813bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org}
55913bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org
56013bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org
561eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.orgvoid MacroAssembler::StubReturn(int argc) {
562eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  ASSERT(argc >= 1 && generating_stub());
563eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  ret((argc - 1) * kPointerSize);
564eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org}
565eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
566eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
567c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.combool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
5688a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  return has_frame_ || !stub->SometimesSetsUpAFrame();
569c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
570c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
571c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
572eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.orgvoid MacroAssembler::IllegalOperation(int num_arguments) {
573eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  if (num_arguments > 0) {
574eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    addq(rsp, Immediate(num_arguments * kPointerSize));
575eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  }
57618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  LoadRoot(rax, Heap::kUndefinedValueRootIndex);
577eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org}
578eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
579eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
580d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.orgvoid MacroAssembler::IndexFromHash(Register hash, Register index) {
581d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  // The assert checks that the constants for the maximum number of digits
582d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  // for an array index cached in the hash field and the number of bits
583d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  // reserved for it does not conflict.
584d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
585d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org         (1 << String::kArrayIndexValueBits));
586d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  // We want the smi-tagged index in key. Even if we subsequently go to
587d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  // the slow case, converting the key to a smi is always valid.
588d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  // key: string key
589d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  // hash: key's hash field, including its array index value.
590d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  and_(hash, Immediate(String::kArrayIndexValueMask));
591d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  shr(hash, Immediate(String::kHashShift));
592d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  // Here we actually clobber the key which will be used if calling into
593d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  // runtime later. However as the new key is the numeric value of a string key
594d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  // there is no difference in using either key.
595d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  Integer32ToSmi(index, hash);
596d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org}
597d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org
598d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org
599ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgvoid MacroAssembler::CallRuntime(const Runtime::Function* f,
600fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org                                 int num_arguments,
601fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org                                 SaveFPRegsMode save_doubles) {
602eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // If the expected number of arguments of the runtime function is
603eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // constant, we check that the actual number of arguments match the
604eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // expectation.
605eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  if (f->nargs >= 0 && f->nargs != num_arguments) {
606eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    IllegalOperation(num_arguments);
607eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    return;
608eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  }
609eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
610b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // TODO(1236192): Most runtime routines don't need the number of
611b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // arguments passed in because it is constant. At some point we
612b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // should remove this need and make the runtime routine entry code
613b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // smarter.
61432d961d4454609ab4251a760fc46b19f661da90clrn@chromium.org  Set(rax, num_arguments);
615ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  LoadAddress(rbx, ExternalReference(f, isolate()));
616fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  CEntryStub ces(f->result_size, save_doubles);
617b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  CallStub(&ces);
618eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org}
619eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
620eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
6215c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid MacroAssembler::CallExternalReference(const ExternalReference& ext,
6225c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                           int num_arguments) {
62332d961d4454609ab4251a760fc46b19f661da90clrn@chromium.org  Set(rax, num_arguments);
624ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  LoadAddress(rbx, ext);
6255c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6265c838251403b0be9a882540f1922577abba4c872ager@chromium.org  CEntryStub stub(1);
6275c838251403b0be9a882540f1922577abba4c872ager@chromium.org  CallStub(&stub);
6285c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
6295c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6305c838251403b0be9a882540f1922577abba4c872ager@chromium.org
631ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.orgvoid MacroAssembler::TailCallExternalReference(const ExternalReference& ext,
632ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org                                               int num_arguments,
633ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org                                               int result_size) {
6340b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  // ----------- S t a t e -------------
635c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org  //  -- rsp[0]                 : return address
636c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org  //  -- rsp[8]                 : argument num_arguments - 1
6370b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  //  ...
6380b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  //  -- rsp[8 * num_arguments] : argument 0 (receiver)
6390b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  // -----------------------------------
6400b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
641eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // TODO(1236192): Most runtime routines don't need the number of
642eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // arguments passed in because it is constant. At some point we
643eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // should remove this need and make the runtime routine entry code
644eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // smarter.
64532d961d4454609ab4251a760fc46b19f661da90clrn@chromium.org  Set(rax, num_arguments);
646ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org  JumpToExternalReference(ext, result_size);
647eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org}
648eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
649eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
650ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.orgvoid MacroAssembler::TailCallRuntime(Runtime::FunctionId fid,
651ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org                                     int num_arguments,
652ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org                                     int result_size) {
653ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  TailCallExternalReference(ExternalReference(fid, isolate()),
654ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org                            num_arguments,
655ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org                            result_size);
656ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org}
657ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org
658ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org
659e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.orgstatic int Offset(ExternalReference ref0, ExternalReference ref1) {
660e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org  int64_t offset = (ref0.address() - ref1.address());
661e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org  // Check that fits into int.
662e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org  ASSERT(static_cast<int>(offset) == offset);
663e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org  return static_cast<int>(offset);
664e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org}
665e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org
666e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org
667662436e7b124b3535773535c671c53db322070b5verwaest@chromium.orgvoid MacroAssembler::PrepareCallApiFunction(int arg_stack_space) {
6684a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  EnterApiExitFrame(arg_stack_space);
669e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org}
670e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org
671e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org
672528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.orgvoid MacroAssembler::CallApiFunctionAndReturn(
673528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    Address function_address,
674528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    Address thunk_address,
675528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    Register thunk_last_arg,
676528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    int stack_space,
677528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    Operand return_value_operand,
678528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    Operand* context_restore_operand) {
679303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  Label prologue;
680303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  Label promote_scheduled_exception;
681528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Label exception_handled;
682303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  Label delete_allocated_handles;
683303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  Label leave_exit_frame;
684e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org  Label write_back;
685e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org
686160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  Factory* factory = isolate()->factory();
687303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  ExternalReference next_address =
68809d7ab5aba54ebac170eac755664c45eefb0be7dulan@chromium.org      ExternalReference::handle_scope_next_address(isolate());
689303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  const int kNextOffset = 0;
690303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  const int kLimitOffset = Offset(
69109d7ab5aba54ebac170eac755664c45eefb0be7dulan@chromium.org      ExternalReference::handle_scope_limit_address(isolate()),
692303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org      next_address);
693303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  const int kLevelOffset = Offset(
69409d7ab5aba54ebac170eac755664c45eefb0be7dulan@chromium.org      ExternalReference::handle_scope_level_address(isolate()),
695303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org      next_address);
696303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  ExternalReference scheduled_exception_address =
697ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      ExternalReference::scheduled_exception_address(isolate());
698303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org
699303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  // Allocate HandleScope in callee-save registers.
700303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  Register prev_next_address_reg = r14;
701303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  Register prev_limit_reg = rbx;
702b08986cb66c3f6687247cb6da186c1e73057e399whesse@chromium.org  Register base_reg = r15;
703e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  Move(base_reg, next_address);
704303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  movq(prev_next_address_reg, Operand(base_reg, kNextOffset));
705303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  movq(prev_limit_reg, Operand(base_reg, kLimitOffset));
706303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  addl(Operand(base_reg, kLevelOffset), Immediate(1));
70783130cfc204d3ffed6832a7ef149b19328a58b33svenpanne@chromium.org
70883130cfc204d3ffed6832a7ef149b19328a58b33svenpanne@chromium.org  if (FLAG_log_timer_events) {
70983130cfc204d3ffed6832a7ef149b19328a58b33svenpanne@chromium.org    FrameScope frame(this, StackFrame::MANUAL);
71083130cfc204d3ffed6832a7ef149b19328a58b33svenpanne@chromium.org    PushSafepointRegisters();
711ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    PrepareCallCFunction(1);
712ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    LoadAddress(arg_reg_1, ExternalReference::isolate_address(isolate()));
713ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    CallCFunction(ExternalReference::log_enter_external_function(isolate()), 1);
71483130cfc204d3ffed6832a7ef149b19328a58b33svenpanne@chromium.org    PopSafepointRegisters();
71583130cfc204d3ffed6832a7ef149b19328a58b33svenpanne@chromium.org  }
71683130cfc204d3ffed6832a7ef149b19328a58b33svenpanne@chromium.org
717b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org
718b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  Label profiler_disabled;
719b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  Label end_profiler_check;
720b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  bool* is_profiling_flag =
721b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org      isolate()->cpu_profiler()->is_profiling_address();
722b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  STATIC_ASSERT(sizeof(*is_profiling_flag) == 1);
723b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  movq(rax, is_profiling_flag, RelocInfo::EXTERNAL_REFERENCE);
724b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  cmpb(Operand(rax, 0), Immediate(0));
725b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  j(zero, &profiler_disabled);
726b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org
727b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  // Third parameter is the address of the actual getter function.
728b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  movq(thunk_last_arg, function_address, RelocInfo::EXTERNAL_REFERENCE);
729b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  movq(rax, thunk_address, RelocInfo::EXTERNAL_REFERENCE);
730b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  jmp(&end_profiler_check);
731b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org
732b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  bind(&profiler_disabled);
733303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  // Call the api function!
734c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  movq(rax, reinterpret_cast<Address>(function_address),
7354cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org       RelocInfo::EXTERNAL_REFERENCE);
736b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org
737b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  bind(&end_profiler_check);
738b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org
739b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  // Call the api function!
740303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  call(rax);
741e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org
74283130cfc204d3ffed6832a7ef149b19328a58b33svenpanne@chromium.org  if (FLAG_log_timer_events) {
74383130cfc204d3ffed6832a7ef149b19328a58b33svenpanne@chromium.org    FrameScope frame(this, StackFrame::MANUAL);
74483130cfc204d3ffed6832a7ef149b19328a58b33svenpanne@chromium.org    PushSafepointRegisters();
745ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    PrepareCallCFunction(1);
746ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    LoadAddress(arg_reg_1, ExternalReference::isolate_address(isolate()));
747ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    CallCFunction(ExternalReference::log_leave_external_function(isolate()), 1);
74883130cfc204d3ffed6832a7ef149b19328a58b33svenpanne@chromium.org    PopSafepointRegisters();
74983130cfc204d3ffed6832a7ef149b19328a58b33svenpanne@chromium.org  }
75083130cfc204d3ffed6832a7ef149b19328a58b33svenpanne@chromium.org
751bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  // Load the value from ReturnValue
752528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  movq(rax, return_value_operand);
753303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  bind(&prologue);
754303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org
755303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  // No more valid handles (the result handle was the last one). Restore
756303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  // previous handle scope.
757303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  subl(Operand(base_reg, kLevelOffset), Immediate(1));
758303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  movq(Operand(base_reg, kNextOffset), prev_next_address_reg);
759303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  cmpq(prev_limit_reg, Operand(base_reg, kLimitOffset));
760303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  j(not_equal, &delete_allocated_handles);
761303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  bind(&leave_exit_frame);
762303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org
763303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  // Check if the function scheduled an exception.
764e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  Move(rsi, scheduled_exception_address);
765160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  Cmp(Operand(rsi, 0), factory->the_hole_value());
766303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  j(not_equal, &promote_scheduled_exception);
767528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  bind(&exception_handled);
768303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org
76967255bead6b3c379ed821d8371271e34779602cajkummerow@chromium.org#if ENABLE_EXTRA_CHECKS
77067255bead6b3c379ed821d8371271e34779602cajkummerow@chromium.org  // Check if the function returned a valid JavaScript value.
77167255bead6b3c379ed821d8371271e34779602cajkummerow@chromium.org  Label ok;
77267255bead6b3c379ed821d8371271e34779602cajkummerow@chromium.org  Register return_value = rax;
77367255bead6b3c379ed821d8371271e34779602cajkummerow@chromium.org  Register map = rcx;
77467255bead6b3c379ed821d8371271e34779602cajkummerow@chromium.org
77567255bead6b3c379ed821d8371271e34779602cajkummerow@chromium.org  JumpIfSmi(return_value, &ok, Label::kNear);
77667255bead6b3c379ed821d8371271e34779602cajkummerow@chromium.org  movq(map, FieldOperand(return_value, HeapObject::kMapOffset));
77767255bead6b3c379ed821d8371271e34779602cajkummerow@chromium.org
77867255bead6b3c379ed821d8371271e34779602cajkummerow@chromium.org  CmpInstanceType(map, FIRST_NONSTRING_TYPE);
77967255bead6b3c379ed821d8371271e34779602cajkummerow@chromium.org  j(below, &ok, Label::kNear);
78067255bead6b3c379ed821d8371271e34779602cajkummerow@chromium.org
78167255bead6b3c379ed821d8371271e34779602cajkummerow@chromium.org  CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE);
78267255bead6b3c379ed821d8371271e34779602cajkummerow@chromium.org  j(above_equal, &ok, Label::kNear);
78367255bead6b3c379ed821d8371271e34779602cajkummerow@chromium.org
78467255bead6b3c379ed821d8371271e34779602cajkummerow@chromium.org  CompareRoot(map, Heap::kHeapNumberMapRootIndex);
78567255bead6b3c379ed821d8371271e34779602cajkummerow@chromium.org  j(equal, &ok, Label::kNear);
78667255bead6b3c379ed821d8371271e34779602cajkummerow@chromium.org
78767255bead6b3c379ed821d8371271e34779602cajkummerow@chromium.org  CompareRoot(return_value, Heap::kUndefinedValueRootIndex);
78867255bead6b3c379ed821d8371271e34779602cajkummerow@chromium.org  j(equal, &ok, Label::kNear);
78967255bead6b3c379ed821d8371271e34779602cajkummerow@chromium.org
79067255bead6b3c379ed821d8371271e34779602cajkummerow@chromium.org  CompareRoot(return_value, Heap::kTrueValueRootIndex);
79167255bead6b3c379ed821d8371271e34779602cajkummerow@chromium.org  j(equal, &ok, Label::kNear);
79267255bead6b3c379ed821d8371271e34779602cajkummerow@chromium.org
79367255bead6b3c379ed821d8371271e34779602cajkummerow@chromium.org  CompareRoot(return_value, Heap::kFalseValueRootIndex);
79467255bead6b3c379ed821d8371271e34779602cajkummerow@chromium.org  j(equal, &ok, Label::kNear);
79567255bead6b3c379ed821d8371271e34779602cajkummerow@chromium.org
79667255bead6b3c379ed821d8371271e34779602cajkummerow@chromium.org  CompareRoot(return_value, Heap::kNullValueRootIndex);
79767255bead6b3c379ed821d8371271e34779602cajkummerow@chromium.org  j(equal, &ok, Label::kNear);
79867255bead6b3c379ed821d8371271e34779602cajkummerow@chromium.org
799594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  Abort(kAPICallReturnedInvalidObject);
80067255bead6b3c379ed821d8371271e34779602cajkummerow@chromium.org
80167255bead6b3c379ed821d8371271e34779602cajkummerow@chromium.org  bind(&ok);
80267255bead6b3c379ed821d8371271e34779602cajkummerow@chromium.org#endif
80367255bead6b3c379ed821d8371271e34779602cajkummerow@chromium.org
804528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  bool restore_context = context_restore_operand != NULL;
805528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  if (restore_context) {
806528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    movq(rsi, *context_restore_operand);
807528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  }
808528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  LeaveApiExitFrame(!restore_context);
8094a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  ret(stack_space * kPointerSize);
810e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org
811b6d052d4d08b0de341804f273713741dee560c5everwaest@chromium.org  bind(&promote_scheduled_exception);
812528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  {
813528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    FrameScope frame(this, StackFrame::INTERNAL);
814528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    CallRuntime(Runtime::kPromoteScheduledException, 0);
815528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  }
816528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  jmp(&exception_handled);
817b6d052d4d08b0de341804f273713741dee560c5everwaest@chromium.org
818303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  // HandleScope limit has changed. Delete allocated extensions.
819303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  bind(&delete_allocated_handles);
820303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  movq(Operand(base_reg, kLimitOffset), prev_limit_reg);
821303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  movq(prev_limit_reg, rax);
822ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  LoadAddress(arg_reg_1, ExternalReference::isolate_address(isolate()));
823ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  LoadAddress(rax,
824ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org              ExternalReference::delete_handle_scope_extensions(isolate()));
825303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  call(rax);
826303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  movq(rax, prev_limit_reg);
827303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  jmp(&leave_exit_frame);
828e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org}
829e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org
830e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org
831ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.orgvoid MacroAssembler::JumpToExternalReference(const ExternalReference& ext,
832ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org                                             int result_size) {
833eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // Set the entry point and jump to the C entry runtime stub.
834ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  LoadAddress(rbx, ext);
835a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org  CEntryStub ces(result_size);
8368432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  jmp(ces.GetCode(isolate()), RelocInfo::CODE_TARGET);
83771affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org}
83871affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org
839e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
8403a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgvoid MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
8413a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                                   InvokeFlag flag,
842fb144a0716afe7ab8bf245f2391a9e53b3db3c89fschneider@chromium.org                                   const CallWrapper& call_wrapper) {
843c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // You can't call a builtin without a valid frame.
844c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(flag == JUMP_FUNCTION || has_frame());
8455aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
8465c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Rely on the assertion to check that the number of provided
8475c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // arguments match the expected number of arguments. Fake a
8485c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // parameter count to avoid emitting code to do the check.
8495c838251403b0be9a882540f1922577abba4c872ager@chromium.org  ParameterCount expected(0);
8505c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GetBuiltinEntry(rdx, id);
851d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org  InvokeCode(rdx, expected, expected, flag, call_wrapper, CALL_AS_METHOD);
8525aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org}
8535aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
8545c838251403b0be9a882540f1922577abba4c872ager@chromium.org
855145eff58d4f6ac0dcc53abb556dbf3cac6c3280aerik.corry@gmail.comvoid MacroAssembler::GetBuiltinFunction(Register target,
856145eff58d4f6ac0dcc53abb556dbf3cac6c3280aerik.corry@gmail.com                                        Builtins::JavaScript id) {
857c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org  // Load the builtins object into target register.
85846839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  movq(target, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
859c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org  movq(target, FieldOperand(target, GlobalObject::kBuiltinsOffset));
860145eff58d4f6ac0dcc53abb556dbf3cac6c3280aerik.corry@gmail.com  movq(target, FieldOperand(target,
861145eff58d4f6ac0dcc53abb556dbf3cac6c3280aerik.corry@gmail.com                            JSBuiltinsObject::OffsetOfFunctionWithId(id)));
862145eff58d4f6ac0dcc53abb556dbf3cac6c3280aerik.corry@gmail.com}
863c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org
864c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org
865145eff58d4f6ac0dcc53abb556dbf3cac6c3280aerik.corry@gmail.comvoid MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
866145eff58d4f6ac0dcc53abb556dbf3cac6c3280aerik.corry@gmail.com  ASSERT(!target.is(rdi));
867145eff58d4f6ac0dcc53abb556dbf3cac6c3280aerik.corry@gmail.com  // Load the JavaScript builtin function from the builtins object.
868145eff58d4f6ac0dcc53abb556dbf3cac6c3280aerik.corry@gmail.com  GetBuiltinFunction(rdi, id);
869145eff58d4f6ac0dcc53abb556dbf3cac6c3280aerik.corry@gmail.com  movq(target, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
8705aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org}
8715aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
8725aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
8731456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org#define REG(Name) { kRegister_ ## Name ## _Code }
8741456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org
8751456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgstatic const Register saved_regs[] = {
8761456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  REG(rax), REG(rcx), REG(rdx), REG(rbx), REG(rbp), REG(rsi), REG(rdi), REG(r8),
8771456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  REG(r9), REG(r10), REG(r11)
8781456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org};
8791456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org
8801456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org#undef REG
8811456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org
882c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comstatic const int kNumberOfSavedRegs = sizeof(saved_regs) / sizeof(Register);
883c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
884c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
885c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid MacroAssembler::PushCallerSaved(SaveFPRegsMode fp_mode,
886c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                     Register exclusion1,
887c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                     Register exclusion2,
888c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                     Register exclusion3) {
889c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // We don't allow a GC during a store buffer overflow so there is no need to
890c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // store the registers in any particular way, but we do have to store and
891c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // restore them.
892c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  for (int i = 0; i < kNumberOfSavedRegs; i++) {
893c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Register reg = saved_regs[i];
894c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    if (!reg.is(exclusion1) && !reg.is(exclusion2) && !reg.is(exclusion3)) {
895c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      push(reg);
896c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
897c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
898c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // R12 to r15 are callee save on all platforms.
899c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (fp_mode == kSaveFPRegs) {
90094b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org    subq(rsp, Immediate(kDoubleSize * XMMRegister::kMaxNumRegisters));
90194b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org    for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
902c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      XMMRegister reg = XMMRegister::from_code(i);
903c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      movsd(Operand(rsp, i * kDoubleSize), reg);
904c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
905c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
906c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
907c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
908c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
909c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid MacroAssembler::PopCallerSaved(SaveFPRegsMode fp_mode,
910c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                    Register exclusion1,
911c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                    Register exclusion2,
912c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                    Register exclusion3) {
913c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (fp_mode == kSaveFPRegs) {
91494b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org    for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
915c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      XMMRegister reg = XMMRegister::from_code(i);
916c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      movsd(reg, Operand(rsp, i * kDoubleSize));
917c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
91894b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org    addq(rsp, Immediate(kDoubleSize * XMMRegister::kMaxNumRegisters));
919c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
920c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  for (int i = kNumberOfSavedRegs - 1; i >= 0; i--) {
921c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Register reg = saved_regs[i];
922c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    if (!reg.is(exclusion1) && !reg.is(exclusion2) && !reg.is(exclusion3)) {
923c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      pop(reg);
924c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
925c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
926c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
927c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
928c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
929528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.orgvoid MacroAssembler::Cvtlsi2sd(XMMRegister dst, Register src) {
930528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  xorps(dst, dst);
931528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  cvtlsi2sd(dst, src);
932528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org}
933528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
934528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
935528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.orgvoid MacroAssembler::Cvtlsi2sd(XMMRegister dst, const Operand& src) {
936528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  xorps(dst, dst);
937528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  cvtlsi2sd(dst, src);
938528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org}
939528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
940528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
941d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.orgvoid MacroAssembler::Load(Register dst, const Operand& src, Representation r) {
942dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org  ASSERT(!r.IsDouble());
943935a7790c70d49e252069bc2d34eaa72f8c6677fmachenbach@chromium.org  if (r.IsInteger8()) {
944935a7790c70d49e252069bc2d34eaa72f8c6677fmachenbach@chromium.org    movsxbq(dst, src);
945935a7790c70d49e252069bc2d34eaa72f8c6677fmachenbach@chromium.org  } else if (r.IsUInteger8()) {
946d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    movzxbl(dst, src);
947935a7790c70d49e252069bc2d34eaa72f8c6677fmachenbach@chromium.org  } else if (r.IsInteger16()) {
948935a7790c70d49e252069bc2d34eaa72f8c6677fmachenbach@chromium.org    movsxwq(dst, src);
949935a7790c70d49e252069bc2d34eaa72f8c6677fmachenbach@chromium.org  } else if (r.IsUInteger16()) {
950935a7790c70d49e252069bc2d34eaa72f8c6677fmachenbach@chromium.org    movzxwl(dst, src);
951d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  } else if (r.IsInteger32()) {
952d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    movl(dst, src);
953d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  } else {
954d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    movq(dst, src);
955d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  }
956d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org}
957d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org
958d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org
959d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.orgvoid MacroAssembler::Store(const Operand& dst, Register src, Representation r) {
960dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org  ASSERT(!r.IsDouble());
961935a7790c70d49e252069bc2d34eaa72f8c6677fmachenbach@chromium.org  if (r.IsInteger8() || r.IsUInteger8()) {
962d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    movb(dst, src);
963935a7790c70d49e252069bc2d34eaa72f8c6677fmachenbach@chromium.org  } else if (r.IsInteger16() || r.IsUInteger16()) {
964935a7790c70d49e252069bc2d34eaa72f8c6677fmachenbach@chromium.org    movw(dst, src);
965d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  } else if (r.IsInteger32()) {
966d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    movl(dst, src);
967d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  } else {
968d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    movq(dst, src);
969d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  }
970d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org}
971d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org
972d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org
973e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.orgvoid MacroAssembler::Set(Register dst, int64_t x) {
97468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  if (x == 0) {
97569ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    xorl(dst, dst);
976e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  } else if (is_uint32(x)) {
977c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org    movl(dst, Immediate(static_cast<uint32_t>(x)));
978a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org  } else if (is_int32(x)) {
979a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org    movq(dst, Immediate(static_cast<int32_t>(x)));
980e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  } else {
981e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    movq(dst, x);
982e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  }
983e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org}
984e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
985e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
986e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.orgvoid MacroAssembler::Set(const Operand& dst, int64_t x) {
9875ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org  if (is_int32(x)) {
988c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org    movq(dst, Immediate(static_cast<int32_t>(x)));
989e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  } else {
990a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org    Set(kScratchRegister, x);
99168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    movq(dst, kScratchRegister);
992e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  }
993e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org}
994e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
9957a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org
996dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org// ----------------------------------------------------------------------------
997dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org// Smi tagging, untagging and tag detection.
998dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
999dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgbool MacroAssembler::IsUnsafeInt(const int32_t x) {
10007a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org  static const int kMaxBits = 17;
10017a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org  return !is_intn(x, kMaxBits);
10027a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org}
10037a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org
10047a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org
10057a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.orgvoid MacroAssembler::SafeMove(Register dst, Smi* src) {
10067a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org  ASSERT(!dst.is(kScratchRegister));
1007662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  ASSERT(SmiValuesAre32Bits());  // JIT cookie can be converted to Smi.
10087a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org  if (IsUnsafeInt(src->value()) && jit_cookie() != 0) {
10097a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org    Move(dst, Smi::FromInt(src->value() ^ jit_cookie()));
10107a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org    Move(kScratchRegister, Smi::FromInt(jit_cookie()));
10117a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org    xor_(dst, kScratchRegister);
10127a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org  } else {
10137a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org    Move(dst, src);
10147a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org  }
10157a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org}
10167a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org
10177a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org
10187a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.orgvoid MacroAssembler::SafePush(Smi* src) {
1019662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  ASSERT(SmiValuesAre32Bits());  // JIT cookie can be converted to Smi.
10207a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org  if (IsUnsafeInt(src->value()) && jit_cookie() != 0) {
10217a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org    Push(Smi::FromInt(src->value() ^ jit_cookie()));
10227a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org    Move(kScratchRegister, Smi::FromInt(jit_cookie()));
10237a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org    xor_(Operand(rsp, 0), kScratchRegister);
10247a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org  } else {
10257a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org    Push(src);
10267a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org  }
10277a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org}
10287a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org
10297a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org
103069ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.orgRegister MacroAssembler::GetSmiConstant(Smi* source) {
103169ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  int value = source->value();
103269ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  if (value == 0) {
103369ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    xorl(kScratchRegister, kScratchRegister);
103469ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    return kScratchRegister;
103569ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  }
103669ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  if (value == 1) {
103769ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    return kSmiConstantRegister;
103869ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  }
103969ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  LoadSmiConstant(kScratchRegister, source);
104069ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  return kScratchRegister;
104169ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org}
104269ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org
1043e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
104469ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.orgvoid MacroAssembler::LoadSmiConstant(Register dst, Smi* source) {
1045badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  if (emit_debug_code()) {
1046e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    movq(dst, Smi::FromInt(kSmiConstantRegisterValue), RelocInfo::NONE64);
104769ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    cmpq(dst, kSmiConstantRegister);
10488a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org    Assert(equal, kUninitializedKSmiConstantRegister);
104969ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  }
1050b08986cb66c3f6687247cb6da186c1e73057e399whesse@chromium.org  int value = source->value();
1051b08986cb66c3f6687247cb6da186c1e73057e399whesse@chromium.org  if (value == 0) {
105269ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    xorl(dst, dst);
105369ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    return;
105469ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  }
105569ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  bool negative = value < 0;
105669ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  unsigned int uvalue = negative ? -value : value;
105769ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org
105869ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  switch (uvalue) {
105969ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    case 9:
106069ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org      lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_8, 0));
106169ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org      break;
106269ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    case 8:
106369ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org      xorl(dst, dst);
106469ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org      lea(dst, Operand(dst, kSmiConstantRegister, times_8, 0));
106569ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org      break;
106669ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    case 4:
106769ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org      xorl(dst, dst);
106869ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org      lea(dst, Operand(dst, kSmiConstantRegister, times_4, 0));
106969ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org      break;
107069ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    case 5:
107169ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org      lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_4, 0));
107269ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org      break;
107369ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    case 3:
107469ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org      lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_2, 0));
107569ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org      break;
107669ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    case 2:
107769ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org      lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_1, 0));
107869ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org      break;
107969ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    case 1:
108069ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org      movq(dst, kSmiConstantRegister);
108169ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org      break;
108269ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    case 0:
108369ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org      UNREACHABLE();
108469ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org      return;
108569ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    default:
1086e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org      movq(dst, source, RelocInfo::NONE64);
108769ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org      return;
108869ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  }
108969ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  if (negative) {
109069ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    neg(dst);
109169ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  }
109269ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org}
109369ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org
10944af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
1095c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.orgvoid MacroAssembler::Integer32ToSmi(Register dst, Register src) {
109680c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  STATIC_ASSERT(kSmiTag == 0);
10974af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  if (!dst.is(src)) {
10984af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org    movl(dst, src);
10994af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  }
11009d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  shl(dst, Immediate(kSmiShift));
11014af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org}
11024af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
11034af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
11045ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.orgvoid MacroAssembler::Integer32ToSmiField(const Operand& dst, Register src) {
1105badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  if (emit_debug_code()) {
11065ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org    testb(dst, Immediate(0x01));
110783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Label ok;
110883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    j(zero, &ok, Label::kNear);
11098a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org    Abort(kInteger32ToSmiFieldWritingToNonSmiLocation);
11105ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org    bind(&ok);
11115ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org  }
11125ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org  ASSERT(kSmiShift % kBitsPerByte == 0);
11135ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org  movl(Operand(dst, kSmiShift / kBitsPerByte), src);
11145ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org}
11155ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org
11165ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org
11179d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.comvoid MacroAssembler::Integer64PlusConstantToSmi(Register dst,
11189d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com                                                Register src,
11199d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com                                                int constant) {
11209d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  if (dst.is(src)) {
11217979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    addl(dst, Immediate(constant));
11229d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  } else {
11237979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    leal(dst, Operand(src, constant));
11249d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  }
11259d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  shl(dst, Immediate(kSmiShift));
11264af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org}
11274af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
11284af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
11294af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.orgvoid MacroAssembler::SmiToInteger32(Register dst, Register src) {
113080c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  STATIC_ASSERT(kSmiTag == 0);
11314af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  if (!dst.is(src)) {
11329d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    movq(dst, src);
11334af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  }
11349d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  shr(dst, Immediate(kSmiShift));
11354af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org}
11364af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
11374af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
113830ce411529579186181838984710b0b0980857aaricow@chromium.orgvoid MacroAssembler::SmiToInteger32(Register dst, const Operand& src) {
113930ce411529579186181838984710b0b0980857aaricow@chromium.org  movl(dst, Operand(src, kSmiShift / kBitsPerByte));
114030ce411529579186181838984710b0b0980857aaricow@chromium.org}
114130ce411529579186181838984710b0b0980857aaricow@chromium.org
114230ce411529579186181838984710b0b0980857aaricow@chromium.org
11434af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.orgvoid MacroAssembler::SmiToInteger64(Register dst, Register src) {
114480c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  STATIC_ASSERT(kSmiTag == 0);
11459d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  if (!dst.is(src)) {
11469d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    movq(dst, src);
11474af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  }
11489d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  sar(dst, Immediate(kSmiShift));
11494af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org}
11504af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
11514af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
11525ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.orgvoid MacroAssembler::SmiToInteger64(Register dst, const Operand& src) {
11535ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org  movsxlq(dst, Operand(src, kSmiShift / kBitsPerByte));
11545ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org}
11555ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org
11565ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org
11579d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.comvoid MacroAssembler::SmiTest(Register src) {
1158ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  AssertSmi(src);
11599d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  testq(src, src);
11604af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org}
11614af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
11624af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
1163badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.orgvoid MacroAssembler::SmiCompare(Register smi1, Register smi2) {
1164c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  AssertSmi(smi1);
1165c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  AssertSmi(smi2);
1166badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  cmpq(smi1, smi2);
11674af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org}
11684af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
11694af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
11709d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.comvoid MacroAssembler::SmiCompare(Register dst, Smi* src) {
1171c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  AssertSmi(dst);
1172badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  Cmp(dst, src);
1173badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org}
1174badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org
1175badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org
1176badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.orgvoid MacroAssembler::Cmp(Register dst, Smi* src) {
11779d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  ASSERT(!dst.is(kScratchRegister));
11789d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  if (src->value() == 0) {
11799d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    testq(dst, dst);
11809d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  } else {
1181ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org    Register constant_reg = GetSmiConstant(src);
1182ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org    cmpq(dst, constant_reg);
11834af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  }
11844af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org}
11854af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
11864af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
11879155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.orgvoid MacroAssembler::SmiCompare(Register dst, const Operand& src) {
1188c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  AssertSmi(dst);
1189c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  AssertSmi(src);
1190ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  cmpq(dst, src);
1191ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org}
1192ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org
1193ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org
11949d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.comvoid MacroAssembler::SmiCompare(const Operand& dst, Register src) {
1195c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  AssertSmi(dst);
1196c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  AssertSmi(src);
11979d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  cmpq(dst, src);
1198c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org}
1199c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org
1200c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org
12019d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.comvoid MacroAssembler::SmiCompare(const Operand& dst, Smi* src) {
1202c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  AssertSmi(dst);
120330ce411529579186181838984710b0b0980857aaricow@chromium.org  cmpl(Operand(dst, kSmiShift / kBitsPerByte), Immediate(src->value()));
12044af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org}
12054af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
12064af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
1207badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.orgvoid MacroAssembler::Cmp(const Operand& dst, Smi* src) {
1208badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  // The Operand cannot use the smi register.
1209badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  Register smi_reg = GetSmiConstant(src);
1210badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  ASSERT(!dst.AddressUsesRegister(smi_reg));
1211badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  cmpq(dst, smi_reg);
1212badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org}
1213badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org
1214badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org
12155ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.orgvoid MacroAssembler::SmiCompareInteger32(const Operand& dst, Register src) {
12165ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org  cmpl(Operand(dst, kSmiShift / kBitsPerByte), src);
12175ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org}
12185ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org
12195ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org
12209d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.comvoid MacroAssembler::PositiveSmiTimesPowerOfTwoToInteger64(Register dst,
12219d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com                                                           Register src,
12229d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com                                                           int power) {
12239d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  ASSERT(power >= 0);
12249d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  ASSERT(power < 64);
12259d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  if (power == 0) {
12269d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    SmiToInteger64(dst, src);
12279d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    return;
12289d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  }
12299d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  if (!dst.is(src)) {
12309d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    movq(dst, src);
12319d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  }
12329d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  if (power < kSmiShift) {
12339d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    sar(dst, Immediate(kSmiShift - power));
12349d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  } else if (power > kSmiShift) {
12359d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    shl(dst, Immediate(power - kSmiShift));
12369d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  }
12374af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org}
12384af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
12394af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
124030ce411529579186181838984710b0b0980857aaricow@chromium.orgvoid MacroAssembler::PositiveSmiDivPowerOfTwoToInteger32(Register dst,
124130ce411529579186181838984710b0b0980857aaricow@chromium.org                                                         Register src,
124230ce411529579186181838984710b0b0980857aaricow@chromium.org                                                         int power) {
124330ce411529579186181838984710b0b0980857aaricow@chromium.org  ASSERT((0 <= power) && (power < 32));
124430ce411529579186181838984710b0b0980857aaricow@chromium.org  if (dst.is(src)) {
124530ce411529579186181838984710b0b0980857aaricow@chromium.org    shr(dst, Immediate(power + kSmiShift));
124630ce411529579186181838984710b0b0980857aaricow@chromium.org  } else {
124730ce411529579186181838984710b0b0980857aaricow@chromium.org    UNIMPLEMENTED();  // Not used.
124830ce411529579186181838984710b0b0980857aaricow@chromium.org  }
124930ce411529579186181838984710b0b0980857aaricow@chromium.org}
125030ce411529579186181838984710b0b0980857aaricow@chromium.org
125130ce411529579186181838984710b0b0980857aaricow@chromium.org
125283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgvoid MacroAssembler::SmiOrIfSmis(Register dst, Register src1, Register src2,
125383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                 Label* on_not_smis,
125483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                 Label::Distance near_jump) {
125583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  if (dst.is(src1) || dst.is(src2)) {
125683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    ASSERT(!src1.is(kScratchRegister));
125783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    ASSERT(!src2.is(kScratchRegister));
125883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    movq(kScratchRegister, src1);
125983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    or_(kScratchRegister, src2);
126083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    JumpIfNotSmi(kScratchRegister, on_not_smis, near_jump);
126183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    movq(dst, kScratchRegister);
126283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  } else {
126383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    movq(dst, src1);
126483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    or_(dst, src2);
126583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    JumpIfNotSmi(dst, on_not_smis, near_jump);
126683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  }
126783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
126883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
126983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
12709d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.comCondition MacroAssembler::CheckSmi(Register src) {
127180c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  STATIC_ASSERT(kSmiTag == 0);
12724af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  testb(src, Immediate(kSmiTagMask));
12739d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  return zero;
12744af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org}
12754af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
12764af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
12770a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.orgCondition MacroAssembler::CheckSmi(const Operand& src) {
127880c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  STATIC_ASSERT(kSmiTag == 0);
12790a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  testb(src, Immediate(kSmiTagMask));
12800a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  return zero;
12810a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org}
12820a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
12830a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
1284eb7c144137bd7d461d4996f752f1353a0856fac1ricow@chromium.orgCondition MacroAssembler::CheckNonNegativeSmi(Register src) {
128580c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  STATIC_ASSERT(kSmiTag == 0);
12868f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  // Test that both bits of the mask 0x8000000000000001 are zero.
12879d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  movq(kScratchRegister, src);
12889d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  rol(kScratchRegister, Immediate(1));
128969ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  testb(kScratchRegister, Immediate(3));
12904af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  return zero;
12914af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org}
12924af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
12934af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
12944af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.orgCondition MacroAssembler::CheckBothSmi(Register first, Register second) {
12954af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  if (first.is(second)) {
12964af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org    return CheckSmi(first);
12974af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  }
129880c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  STATIC_ASSERT(kSmiTag == 0 && kHeapObjectTag == 1 && kHeapObjectTagMask == 3);
129932d961d4454609ab4251a760fc46b19f661da90clrn@chromium.org  leal(kScratchRegister, Operand(first, second, times_1, 0));
130032d961d4454609ab4251a760fc46b19f661da90clrn@chromium.org  testb(kScratchRegister, Immediate(0x03));
13019d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  return zero;
13024af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org}
13034af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
13044af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
1305eb7c144137bd7d461d4996f752f1353a0856fac1ricow@chromium.orgCondition MacroAssembler::CheckBothNonNegativeSmi(Register first,
1306eb7c144137bd7d461d4996f752f1353a0856fac1ricow@chromium.org                                                  Register second) {
1307b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  if (first.is(second)) {
1308eb7c144137bd7d461d4996f752f1353a0856fac1ricow@chromium.org    return CheckNonNegativeSmi(first);
1309b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
131040b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  movq(kScratchRegister, first);
131140b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  or_(kScratchRegister, second);
1312b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  rol(kScratchRegister, Immediate(1));
1313eb7c144137bd7d461d4996f752f1353a0856fac1ricow@chromium.org  testl(kScratchRegister, Immediate(3));
1314b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  return zero;
1315b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
1316b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
1317b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
1318c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.orgCondition MacroAssembler::CheckEitherSmi(Register first,
1319c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org                                         Register second,
1320c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org                                         Register scratch) {
1321b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  if (first.is(second)) {
1322b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    return CheckSmi(first);
1323b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
1324c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org  if (scratch.is(second)) {
1325c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org    andl(scratch, first);
1326c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org  } else {
1327c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org    if (!scratch.is(first)) {
1328c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org      movl(scratch, first);
1329c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org    }
1330c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org    andl(scratch, second);
1331c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org  }
1332c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org  testb(scratch, Immediate(kSmiTagMask));
1333b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  return zero;
1334b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
1335b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
1336b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
13374af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.orgCondition MacroAssembler::CheckIsMinSmi(Register src) {
133869ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  ASSERT(!src.is(kScratchRegister));
133969ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  // If we overflow by subtracting one, it's the minimal smi value.
134069ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  cmpq(src, kSmiConstantRegister);
134169ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  return overflow;
13424af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org}
13434af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
1344c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org
13454af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.orgCondition MacroAssembler::CheckInteger32ValidSmiValue(Register src) {
13469d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  // A 32-bit integer value can always be converted to a smi.
13479d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  return always;
13484af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org}
13494af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
13504af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
13513811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.orgCondition MacroAssembler::CheckUInteger32ValidSmiValue(Register src) {
13523811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  // An unsigned 32-bit integer value is valid as long as the high bit
13533811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  // is not set.
135469ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  testl(src, src);
135569ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  return positive;
13563811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org}
13573811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
13583811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
13590ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.orgvoid MacroAssembler::CheckSmiToIndicator(Register dst, Register src) {
13600ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  if (dst.is(src)) {
13610ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    andl(dst, Immediate(kSmiTagMask));
13620ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  } else {
13630ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    movl(dst, Immediate(kSmiTagMask));
13640ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    andl(dst, src);
13650ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  }
13660ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org}
13670ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org
13680ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org
13690ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.orgvoid MacroAssembler::CheckSmiToIndicator(Register dst, const Operand& src) {
13700ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  if (!(src.AddressUsesRegister(dst))) {
13710ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    movl(dst, Immediate(kSmiTagMask));
13720ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    andl(dst, src);
13730ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  } else {
13740ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    movl(dst, src);
13750ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    andl(dst, Immediate(kSmiTagMask));
13760ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  }
13770ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org}
13780ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org
13790ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org
138083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgvoid MacroAssembler::JumpIfNotValidSmiValue(Register src,
138183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                            Label* on_invalid,
138283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                            Label::Distance near_jump) {
138383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Condition is_valid = CheckInteger32ValidSmiValue(src);
138483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  j(NegateCondition(is_valid), on_invalid, near_jump);
138583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
138683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
138783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
138883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgvoid MacroAssembler::JumpIfUIntNotValidSmiValue(Register src,
138983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                                Label* on_invalid,
139083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                                Label::Distance near_jump) {
139183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Condition is_valid = CheckUInteger32ValidSmiValue(src);
139283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  j(NegateCondition(is_valid), on_invalid, near_jump);
139383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
139483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
139583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
139683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgvoid MacroAssembler::JumpIfSmi(Register src,
139783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                               Label* on_smi,
139883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                               Label::Distance near_jump) {
139983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Condition smi = CheckSmi(src);
140083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  j(smi, on_smi, near_jump);
140183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
140283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
140383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
140483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgvoid MacroAssembler::JumpIfNotSmi(Register src,
140583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                  Label* on_not_smi,
140683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                  Label::Distance near_jump) {
140783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Condition smi = CheckSmi(src);
140883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  j(NegateCondition(smi), on_not_smi, near_jump);
140983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
141083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
141183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
141283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgvoid MacroAssembler::JumpUnlessNonNegativeSmi(
141383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Register src, Label* on_not_smi_or_negative,
141483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Label::Distance near_jump) {
141583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Condition non_negative_smi = CheckNonNegativeSmi(src);
141683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  j(NegateCondition(non_negative_smi), on_not_smi_or_negative, near_jump);
141783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
141883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
141983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
142083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgvoid MacroAssembler::JumpIfSmiEqualsConstant(Register src,
142183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                             Smi* constant,
142283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                             Label* on_equals,
142383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                             Label::Distance near_jump) {
142483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  SmiCompare(src, constant);
142583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  j(equal, on_equals, near_jump);
142683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
142783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
142883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
142983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgvoid MacroAssembler::JumpIfNotBothSmi(Register src1,
143083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                      Register src2,
143183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                      Label* on_not_both_smi,
143283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                      Label::Distance near_jump) {
143383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Condition both_smi = CheckBothSmi(src1, src2);
143483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  j(NegateCondition(both_smi), on_not_both_smi, near_jump);
143583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
143683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
143783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
143883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgvoid MacroAssembler::JumpUnlessBothNonNegativeSmi(Register src1,
143983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                                  Register src2,
144083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                                  Label* on_not_both_smi,
144183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                                  Label::Distance near_jump) {
144283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Condition both_smi = CheckBothNonNegativeSmi(src1, src2);
144383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  j(NegateCondition(both_smi), on_not_both_smi, near_jump);
144483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
144583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
144683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
14479d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.comvoid MacroAssembler::SmiAddConstant(Register dst, Register src, Smi* constant) {
14489d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  if (constant->value() == 0) {
14499d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    if (!dst.is(src)) {
14509d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com      movq(dst, src);
14519d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    }
145269ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    return;
14539d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  } else if (dst.is(src)) {
14549d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    ASSERT(!dst.is(kScratchRegister));
145569ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    switch (constant->value()) {
145669ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org      case 1:
145769ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org        addq(dst, kSmiConstantRegister);
145869ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org        return;
145969ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org      case 2:
146069ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org        lea(dst, Operand(src, kSmiConstantRegister, times_2, 0));
146169ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org        return;
146269ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org      case 4:
146369ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org        lea(dst, Operand(src, kSmiConstantRegister, times_4, 0));
146469ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org        return;
146569ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org      case 8:
146669ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org        lea(dst, Operand(src, kSmiConstantRegister, times_8, 0));
146769ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org        return;
146869ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org      default:
146969ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org        Register constant_reg = GetSmiConstant(constant);
147069ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org        addq(dst, constant_reg);
147169ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org        return;
147269ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    }
14734af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  } else {
147469ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    switch (constant->value()) {
147569ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org      case 1:
147669ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org        lea(dst, Operand(src, kSmiConstantRegister, times_1, 0));
147769ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org        return;
147869ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org      case 2:
147969ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org        lea(dst, Operand(src, kSmiConstantRegister, times_2, 0));
148069ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org        return;
148169ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org      case 4:
148269ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org        lea(dst, Operand(src, kSmiConstantRegister, times_4, 0));
148369ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org        return;
148469ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org      case 8:
148569ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org        lea(dst, Operand(src, kSmiConstantRegister, times_8, 0));
148669ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org        return;
148769ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org      default:
148869ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org        LoadSmiConstant(dst, constant);
148969ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org        addq(dst, src);
149069ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org        return;
149169ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    }
14924af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  }
14934af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org}
14944af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
14954af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
14969dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.comvoid MacroAssembler::SmiAddConstant(const Operand& dst, Smi* constant) {
14979dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  if (constant->value() != 0) {
149830ce411529579186181838984710b0b0980857aaricow@chromium.org    addl(Operand(dst, kSmiShift / kBitsPerByte), Immediate(constant->value()));
14999dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  }
15009dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com}
15019dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
15029dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
150383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgvoid MacroAssembler::SmiAddConstant(Register dst,
150483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                    Register src,
150583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                    Smi* constant,
1506e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org                                    SmiOperationExecutionMode mode,
1507e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org                                    Label* bailout_label,
150883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                    Label::Distance near_jump) {
150983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  if (constant->value() == 0) {
151083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    if (!dst.is(src)) {
151183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      movq(dst, src);
151283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    }
151383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  } else if (dst.is(src)) {
151483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    ASSERT(!dst.is(kScratchRegister));
151583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    LoadSmiConstant(kScratchRegister, constant);
1516d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    addq(dst, kScratchRegister);
1517e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    if (mode.Contains(BAILOUT_ON_NO_OVERFLOW)) {
1518e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org      j(no_overflow, bailout_label, near_jump);
1519e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org      ASSERT(mode.Contains(PRESERVE_SOURCE_REGISTER));
1520e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org      subq(dst, kScratchRegister);
1521e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    } else if (mode.Contains(BAILOUT_ON_OVERFLOW)) {
1522e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org      if (mode.Contains(PRESERVE_SOURCE_REGISTER)) {
1523e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org        Label done;
1524e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org        j(no_overflow, &done, Label::kNear);
1525e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org        subq(dst, kScratchRegister);
1526e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org        jmp(bailout_label, near_jump);
1527e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org        bind(&done);
1528e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org      } else {
1529e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org        // Bailout if overflow without reserving src.
1530e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org        j(overflow, bailout_label, near_jump);
1531e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org      }
1532e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    } else {
1533e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org      CHECK(mode.IsEmpty());
1534e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    }
153583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  } else {
1536e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    ASSERT(mode.Contains(PRESERVE_SOURCE_REGISTER));
1537e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    ASSERT(mode.Contains(BAILOUT_ON_OVERFLOW));
153883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    LoadSmiConstant(dst, constant);
153983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    addq(dst, src);
1540e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    j(overflow, bailout_label, near_jump);
154183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  }
154283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
154383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
154483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
15459d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.comvoid MacroAssembler::SmiSubConstant(Register dst, Register src, Smi* constant) {
15469d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  if (constant->value() == 0) {
15474af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org    if (!dst.is(src)) {
15489d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com      movq(dst, src);
15494af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org    }
15509d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  } else if (dst.is(src)) {
15519d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    ASSERT(!dst.is(kScratchRegister));
155269ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    Register constant_reg = GetSmiConstant(constant);
155369ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    subq(dst, constant_reg);
15549d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  } else {
15559d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    if (constant->value() == Smi::kMinValue) {
155669ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org      LoadSmiConstant(dst, constant);
15575ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org      // Adding and subtracting the min-value gives the same result, it only
15585ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org      // differs on the overflow bit, which we don't check here.
15595ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org      addq(dst, src);
15604af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org    } else {
15615ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org      // Subtract by adding the negation.
156269ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org      LoadSmiConstant(dst, Smi::FromInt(-constant->value()));
15639d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com      addq(dst, src);
15644af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org    }
15654af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  }
15664af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org}
15674af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
15684af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
156983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgvoid MacroAssembler::SmiSubConstant(Register dst,
157083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                    Register src,
157183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                    Smi* constant,
1572e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org                                    SmiOperationExecutionMode mode,
1573e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org                                    Label* bailout_label,
157483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                    Label::Distance near_jump) {
157583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  if (constant->value() == 0) {
157683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    if (!dst.is(src)) {
157783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      movq(dst, src);
157883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    }
157983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  } else if (dst.is(src)) {
158083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    ASSERT(!dst.is(kScratchRegister));
1581e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    LoadSmiConstant(kScratchRegister, constant);
1582e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    subq(dst, kScratchRegister);
1583e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    if (mode.Contains(BAILOUT_ON_NO_OVERFLOW)) {
1584e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org      j(no_overflow, bailout_label, near_jump);
1585e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org      ASSERT(mode.Contains(PRESERVE_SOURCE_REGISTER));
1586e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org      addq(dst, kScratchRegister);
1587e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    } else if (mode.Contains(BAILOUT_ON_OVERFLOW)) {
1588e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org      if (mode.Contains(PRESERVE_SOURCE_REGISTER)) {
1589e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org        Label done;
1590e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org        j(no_overflow, &done, Label::kNear);
1591e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org        addq(dst, kScratchRegister);
1592e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org        jmp(bailout_label, near_jump);
1593e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org        bind(&done);
1594e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org      } else {
1595e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org        // Bailout if overflow without reserving src.
1596e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org        j(overflow, bailout_label, near_jump);
1597e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org      }
159883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    } else {
1599e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org      CHECK(mode.IsEmpty());
160083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    }
160183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  } else {
1602e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    ASSERT(mode.Contains(PRESERVE_SOURCE_REGISTER));
1603e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    ASSERT(mode.Contains(BAILOUT_ON_OVERFLOW));
160483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    if (constant->value() == Smi::kMinValue) {
1605e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org      ASSERT(!dst.is(kScratchRegister));
1606e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org      movq(dst, src);
1607e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org      LoadSmiConstant(kScratchRegister, constant);
1608e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org      subq(dst, kScratchRegister);
1609e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org      j(overflow, bailout_label, near_jump);
161083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    } else {
161183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      // Subtract by adding the negation.
161283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      LoadSmiConstant(dst, Smi::FromInt(-(constant->value())));
161383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      addq(dst, src);
1614e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org      j(overflow, bailout_label, near_jump);
161583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    }
161683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  }
161783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
161883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
161983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
162083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgvoid MacroAssembler::SmiNeg(Register dst,
162183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                            Register src,
162283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                            Label* on_smi_result,
162383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                            Label::Distance near_jump) {
162483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  if (dst.is(src)) {
162583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    ASSERT(!dst.is(kScratchRegister));
162683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    movq(kScratchRegister, src);
162783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    neg(dst);  // Low 32 bits are retained as zero by negation.
162883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    // Test if result is zero or Smi::kMinValue.
162983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    cmpq(dst, kScratchRegister);
163083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    j(not_equal, on_smi_result, near_jump);
163183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    movq(src, kScratchRegister);
163283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  } else {
163383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    movq(dst, src);
163483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    neg(dst);
163583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    cmpq(dst, src);
163683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    // If the result is zero or Smi::kMinValue, negation failed to create a smi.
163783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    j(not_equal, on_smi_result, near_jump);
163883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  }
163983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
164083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
164183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
1642d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.orgtemplate<class T>
1643d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.orgstatic void SmiAddHelper(MacroAssembler* masm,
1644d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org                         Register dst,
1645d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org                         Register src1,
1646d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org                         T src2,
1647d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org                         Label* on_not_smi_result,
1648d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org                         Label::Distance near_jump) {
1649d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  if (dst.is(src1)) {
1650d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    Label done;
1651d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    masm->addq(dst, src2);
1652d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    masm->j(no_overflow, &done, Label::kNear);
1653d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    // Restore src1.
1654d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    masm->subq(dst, src2);
1655d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    masm->jmp(on_not_smi_result, near_jump);
1656d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    masm->bind(&done);
1657d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  } else {
1658d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    masm->movq(dst, src1);
1659d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    masm->addq(dst, src2);
1660d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    masm->j(overflow, on_not_smi_result, near_jump);
1661d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  }
1662d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org}
1663d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org
1664d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org
166583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgvoid MacroAssembler::SmiAdd(Register dst,
166683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                            Register src1,
166783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                            Register src2,
166883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                            Label* on_not_smi_result,
166983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                            Label::Distance near_jump) {
167083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT_NOT_NULL(on_not_smi_result);
167183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT(!dst.is(src2));
1672d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  SmiAddHelper<Register>(this, dst, src1, src2, on_not_smi_result, near_jump);
167383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
167483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
167583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
167683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgvoid MacroAssembler::SmiAdd(Register dst,
167783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                            Register src1,
167883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                            const Operand& src2,
167983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                            Label* on_not_smi_result,
168083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                            Label::Distance near_jump) {
168183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT_NOT_NULL(on_not_smi_result);
1682d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  ASSERT(!src2.AddressUsesRegister(dst));
1683d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  SmiAddHelper<Operand>(this, dst, src1, src2, on_not_smi_result, near_jump);
168483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
168583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
168683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
1687c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.orgvoid MacroAssembler::SmiAdd(Register dst,
1688c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org                            Register src1,
1689c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org                            Register src2) {
1690c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org  // No overflow checking. Use only when it's known that
1691c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org  // overflowing is impossible.
16927979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  if (!dst.is(src1)) {
1693160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org    if (emit_debug_code()) {
1694160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org      movq(kScratchRegister, src1);
1695160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org      addq(kScratchRegister, src2);
1696594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org      Check(no_overflow, kSmiAdditionOverflow);
1697160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org    }
1698160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org    lea(dst, Operand(src1, src2, times_1, 0));
1699160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  } else {
1700160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org    addq(dst, src2);
1701594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    Assert(no_overflow, kSmiAdditionOverflow);
17024af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  }
17034af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org}
17044af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
17054af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
1706c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.orgtemplate<class T>
1707c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.orgstatic void SmiSubHelper(MacroAssembler* masm,
1708c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org                         Register dst,
1709c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org                         Register src1,
1710c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org                         T src2,
1711c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org                         Label* on_not_smi_result,
1712c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org                         Label::Distance near_jump) {
171383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  if (dst.is(src1)) {
1714c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org    Label done;
1715c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org    masm->subq(dst, src2);
1716c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org    masm->j(no_overflow, &done, Label::kNear);
1717c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org    // Restore src1.
1718c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org    masm->addq(dst, src2);
1719c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org    masm->jmp(on_not_smi_result, near_jump);
1720c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org    masm->bind(&done);
172183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  } else {
1722c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org    masm->movq(dst, src1);
1723c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org    masm->subq(dst, src2);
1724c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org    masm->j(overflow, on_not_smi_result, near_jump);
172583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  }
172683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
172783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
172883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
1729c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.orgvoid MacroAssembler::SmiSub(Register dst,
1730c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org                            Register src1,
1731c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org                            Register src2,
1732c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org                            Label* on_not_smi_result,
1733c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org                            Label::Distance near_jump) {
1734c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org  ASSERT_NOT_NULL(on_not_smi_result);
1735c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org  ASSERT(!dst.is(src2));
1736c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org  SmiSubHelper<Register>(this, dst, src1, src2, on_not_smi_result, near_jump);
17374af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org}
17384af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
17394af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
1740c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.orgvoid MacroAssembler::SmiSub(Register dst,
17414af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                            Register src1,
174283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                            const Operand& src2,
174383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                            Label* on_not_smi_result,
174483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                            Label::Distance near_jump) {
174583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT_NOT_NULL(on_not_smi_result);
1746c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org  ASSERT(!src2.AddressUsesRegister(dst));
1747c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org  SmiSubHelper<Operand>(this, dst, src1, src2, on_not_smi_result, near_jump);
174883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
174983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
175083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
1751c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.orgtemplate<class T>
1752c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.orgstatic void SmiSubNoOverflowHelper(MacroAssembler* masm,
1753c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org                                   Register dst,
1754c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org                                   Register src1,
1755c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org                                   T src2) {
1756c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org  // No overflow checking. Use only when it's known that
1757c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org  // overflowing is impossible (e.g., subtracting two positive smis).
17587979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  if (!dst.is(src1)) {
1759c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org    masm->movq(dst, src1);
17604af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  }
1761c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org  masm->subq(dst, src2);
1762c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org  masm->Assert(no_overflow, kSmiSubtractionOverflow);
1763c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org}
1764c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org
1765c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org
1766c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.orgvoid MacroAssembler::SmiSub(Register dst, Register src1, Register src2) {
1767c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org  ASSERT(!dst.is(src2));
1768c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org  SmiSubNoOverflowHelper<Register>(this, dst, src1, src2);
1769c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org}
1770c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org
1771c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org
1772c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.orgvoid MacroAssembler::SmiSub(Register dst,
1773c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org                            Register src1,
1774c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org                            const Operand& src2) {
1775c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org  SmiSubNoOverflowHelper<Operand>(this, dst, src1, src2);
17764af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org}
17774af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
17784af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
177983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgvoid MacroAssembler::SmiMul(Register dst,
178083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                            Register src1,
178183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                            Register src2,
178283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                            Label* on_not_smi_result,
178383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                            Label::Distance near_jump) {
178483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT(!dst.is(src2));
178583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT(!dst.is(kScratchRegister));
178683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT(!src1.is(kScratchRegister));
178783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT(!src2.is(kScratchRegister));
178883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
178983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  if (dst.is(src1)) {
179083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Label failure, zero_correct_result;
179183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    movq(kScratchRegister, src1);  // Create backup for later testing.
179283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    SmiToInteger64(dst, src1);
179383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    imul(dst, src2);
179483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    j(overflow, &failure, Label::kNear);
179583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
179683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    // Check for negative zero result.  If product is zero, and one
179783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    // argument is negative, go to slow case.
179883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Label correct_result;
179983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    testq(dst, dst);
180083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    j(not_zero, &correct_result, Label::kNear);
180183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
180283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    movq(dst, kScratchRegister);
180383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    xor_(dst, src2);
180483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    // Result was positive zero.
180583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    j(positive, &zero_correct_result, Label::kNear);
180683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
180783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    bind(&failure);  // Reused failure exit, restores src1.
180883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    movq(src1, kScratchRegister);
180983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    jmp(on_not_smi_result, near_jump);
181083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
181183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    bind(&zero_correct_result);
181283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Set(dst, 0);
181383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
181483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    bind(&correct_result);
181583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  } else {
181683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    SmiToInteger64(dst, src1);
181783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    imul(dst, src2);
181883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    j(overflow, on_not_smi_result, near_jump);
181983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    // Check for negative zero result.  If product is zero, and one
182083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    // argument is negative, go to slow case.
182183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Label correct_result;
182283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    testq(dst, dst);
182383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    j(not_zero, &correct_result, Label::kNear);
182483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    // One of src1 and src2 is zero, the check whether the other is
182583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    // negative.
182683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    movq(kScratchRegister, src1);
182783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    xor_(kScratchRegister, src2);
182883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    j(negative, on_not_smi_result, near_jump);
182983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    bind(&correct_result);
183083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  }
183183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
183283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
183383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
183483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgvoid MacroAssembler::SmiDiv(Register dst,
183583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                            Register src1,
183683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                            Register src2,
183783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                            Label* on_not_smi_result,
183883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                            Label::Distance near_jump) {
183983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT(!src1.is(kScratchRegister));
184083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT(!src2.is(kScratchRegister));
184183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT(!dst.is(kScratchRegister));
184283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT(!src2.is(rax));
184383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT(!src2.is(rdx));
184483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT(!src1.is(rdx));
184583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
184683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // Check for 0 divisor (result is +/-Infinity).
184783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  testq(src2, src2);
184883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  j(zero, on_not_smi_result, near_jump);
184983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
185083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  if (src1.is(rax)) {
185183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    movq(kScratchRegister, src1);
185283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  }
185383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  SmiToInteger32(rax, src1);
185483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // We need to rule out dividing Smi::kMinValue by -1, since that would
185583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // overflow in idiv and raise an exception.
185683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // We combine this with negative zero test (negative zero only happens
185783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // when dividing zero by a negative number).
185883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
185983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // We overshoot a little and go to slow case if we divide min-value
186083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // by any negative value, not just -1.
186183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label safe_div;
186283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  testl(rax, Immediate(0x7fffffff));
186383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  j(not_zero, &safe_div, Label::kNear);
186483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  testq(src2, src2);
186583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  if (src1.is(rax)) {
186683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    j(positive, &safe_div, Label::kNear);
186783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    movq(src1, kScratchRegister);
186883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    jmp(on_not_smi_result, near_jump);
186983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  } else {
187083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    j(negative, on_not_smi_result, near_jump);
187183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  }
187283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  bind(&safe_div);
187383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
187483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  SmiToInteger32(src2, src2);
187583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // Sign extend src1 into edx:eax.
187683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  cdq();
187783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  idivl(src2);
187883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Integer32ToSmi(src2, src2);
187983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // Check that the remainder is zero.
188083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  testl(rdx, rdx);
188183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  if (src1.is(rax)) {
188283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Label smi_result;
188383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    j(zero, &smi_result, Label::kNear);
188483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    movq(src1, kScratchRegister);
188583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    jmp(on_not_smi_result, near_jump);
188683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    bind(&smi_result);
188783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  } else {
188883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    j(not_zero, on_not_smi_result, near_jump);
188983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  }
189083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  if (!dst.is(src1) && src1.is(rax)) {
189183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    movq(src1, kScratchRegister);
189283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  }
189383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Integer32ToSmi(dst, rax);
189483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
189583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
189683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
189783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgvoid MacroAssembler::SmiMod(Register dst,
189883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                            Register src1,
189983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                            Register src2,
190083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                            Label* on_not_smi_result,
190183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                            Label::Distance near_jump) {
190283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT(!dst.is(kScratchRegister));
190383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT(!src1.is(kScratchRegister));
190483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT(!src2.is(kScratchRegister));
190583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT(!src2.is(rax));
190683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT(!src2.is(rdx));
190783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT(!src1.is(rdx));
190883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT(!src1.is(src2));
190983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
191083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  testq(src2, src2);
191183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  j(zero, on_not_smi_result, near_jump);
191283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
191383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  if (src1.is(rax)) {
191483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    movq(kScratchRegister, src1);
191583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  }
191683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  SmiToInteger32(rax, src1);
191783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  SmiToInteger32(src2, src2);
191883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
191983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // Test for the edge case of dividing Smi::kMinValue by -1 (will overflow).
192083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label safe_div;
192183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  cmpl(rax, Immediate(Smi::kMinValue));
192283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  j(not_equal, &safe_div, Label::kNear);
192383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  cmpl(src2, Immediate(-1));
192483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  j(not_equal, &safe_div, Label::kNear);
192583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // Retag inputs and go slow case.
192683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Integer32ToSmi(src2, src2);
192783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  if (src1.is(rax)) {
192883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    movq(src1, kScratchRegister);
192983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  }
193083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  jmp(on_not_smi_result, near_jump);
193183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  bind(&safe_div);
193283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
193383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // Sign extend eax into edx:eax.
193483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  cdq();
193583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  idivl(src2);
193683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // Restore smi tags on inputs.
193783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Integer32ToSmi(src2, src2);
193883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  if (src1.is(rax)) {
193983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    movq(src1, kScratchRegister);
194083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  }
194183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // Check for a negative zero result.  If the result is zero, and the
194283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // dividend is negative, go slow to return a floating point negative zero.
194383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label smi_result;
194483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  testl(rdx, rdx);
194583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  j(not_zero, &smi_result, Label::kNear);
194683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  testq(src1, src1);
194783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  j(negative, on_not_smi_result, near_jump);
194883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  bind(&smi_result);
194983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Integer32ToSmi(dst, rdx);
195083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
195183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
195283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
19534af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.orgvoid MacroAssembler::SmiNot(Register dst, Register src) {
19549d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  ASSERT(!dst.is(kScratchRegister));
19559d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  ASSERT(!src.is(kScratchRegister));
19569d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  // Set tag and padding bits before negating, so that they are zero afterwards.
19579d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  movl(kScratchRegister, Immediate(~0));
19584af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  if (dst.is(src)) {
19599d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    xor_(dst, kScratchRegister);
19604af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  } else {
19619d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    lea(dst, Operand(src, kScratchRegister, times_1, 0));
19624af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  }
19639d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  not_(dst);
19644af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org}
19654af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
19664af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
19674af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.orgvoid MacroAssembler::SmiAnd(Register dst, Register src1, Register src2) {
19689d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  ASSERT(!dst.is(src2));
19694af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  if (!dst.is(src1)) {
19709d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    movq(dst, src1);
19714af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  }
19724af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  and_(dst, src2);
19734af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org}
19744af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
19754af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
19769d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.comvoid MacroAssembler::SmiAndConstant(Register dst, Register src, Smi* constant) {
19779d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  if (constant->value() == 0) {
19785d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    Set(dst, 0);
19799d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  } else if (dst.is(src)) {
19809d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    ASSERT(!dst.is(kScratchRegister));
198169ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    Register constant_reg = GetSmiConstant(constant);
198269ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    and_(dst, constant_reg);
19839d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  } else {
198469ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    LoadSmiConstant(dst, constant);
19859d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    and_(dst, src);
19864af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  }
19874af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org}
19884af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
19894af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
19904af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.orgvoid MacroAssembler::SmiOr(Register dst, Register src1, Register src2) {
19914af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  if (!dst.is(src1)) {
199244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    ASSERT(!src1.is(src2));
19939d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    movq(dst, src1);
19944af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  }
19954af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  or_(dst, src2);
19964af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org}
19974af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
19984af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
19999d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.comvoid MacroAssembler::SmiOrConstant(Register dst, Register src, Smi* constant) {
20009d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  if (dst.is(src)) {
20019d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    ASSERT(!dst.is(kScratchRegister));
200269ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    Register constant_reg = GetSmiConstant(constant);
200369ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    or_(dst, constant_reg);
20049d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  } else {
200569ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    LoadSmiConstant(dst, constant);
20069d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    or_(dst, src);
20074af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  }
20084af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org}
20094af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
20109d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
20114af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.orgvoid MacroAssembler::SmiXor(Register dst, Register src1, Register src2) {
20124af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  if (!dst.is(src1)) {
201344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    ASSERT(!src1.is(src2));
20149d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    movq(dst, src1);
20154af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  }
20164af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  xor_(dst, src2);
20174af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org}
20184af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
20194af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
20209d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.comvoid MacroAssembler::SmiXorConstant(Register dst, Register src, Smi* constant) {
20219d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  if (dst.is(src)) {
20229d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    ASSERT(!dst.is(kScratchRegister));
202369ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    Register constant_reg = GetSmiConstant(constant);
202469ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    xor_(dst, constant_reg);
20259d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  } else {
202669ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    LoadSmiConstant(dst, constant);
20279d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    xor_(dst, src);
20284af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  }
20294af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org}
20304af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
20314af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
20324af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.orgvoid MacroAssembler::SmiShiftArithmeticRightConstant(Register dst,
20334af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                                                     Register src,
20344af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                                                     int shift_value) {
20359d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  ASSERT(is_uint5(shift_value));
20364af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  if (shift_value > 0) {
20374af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org    if (dst.is(src)) {
20389d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com      sar(dst, Immediate(shift_value + kSmiShift));
20399d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com      shl(dst, Immediate(kSmiShift));
20404af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org    } else {
20414af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org      UNIMPLEMENTED();  // Not used.
20424af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org    }
20434af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  }
20444af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org}
20454af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
20464af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
20474af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.orgvoid MacroAssembler::SmiShiftLeftConstant(Register dst,
20484af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                                          Register src,
2049720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org                                          int shift_value) {
20509d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  if (!dst.is(src)) {
20519d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    movq(dst, src);
20529d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  }
20539d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  if (shift_value > 0) {
20549d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    shl(dst, Immediate(shift_value));
20554af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  }
20564af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org}
20574af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
20584af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
205983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgvoid MacroAssembler::SmiShiftLogicalRightConstant(
206083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Register dst, Register src, int shift_value,
206183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Label* on_not_smi_result, Label::Distance near_jump) {
206283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // Logic right shift interprets its result as an *unsigned* number.
206383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  if (dst.is(src)) {
206483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    UNIMPLEMENTED();  // Not used.
206583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  } else {
206683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    movq(dst, src);
206783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    if (shift_value == 0) {
206883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      testq(dst, dst);
206983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      j(negative, on_not_smi_result, near_jump);
207083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    }
207183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    shr(dst, Immediate(shift_value + kSmiShift));
207283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    shl(dst, Immediate(kSmiShift));
207383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  }
207483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
207583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
207683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
20774af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.orgvoid MacroAssembler::SmiShiftLeft(Register dst,
20784af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                                  Register src1,
2079720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org                                  Register src2) {
20804af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  ASSERT(!dst.is(rcx));
20819d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  // Untag shift amount.
20829d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  if (!dst.is(src1)) {
20839d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    movq(dst, src1);
20844af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  }
20859d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  SmiToInteger32(rcx, src2);
20869d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  // Shift amount specified by lower 5 bits, not six as the shl opcode.
20879d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  and_(rcx, Immediate(0x1f));
2088c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  shl_cl(dst);
20894af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org}
20904af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
20914af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
209283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgvoid MacroAssembler::SmiShiftLogicalRight(Register dst,
209383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                          Register src1,
209483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                          Register src2,
209583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                          Label* on_not_smi_result,
209683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                          Label::Distance near_jump) {
209783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT(!dst.is(kScratchRegister));
209883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT(!src1.is(kScratchRegister));
209983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT(!src2.is(kScratchRegister));
210083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT(!dst.is(rcx));
210183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // dst and src1 can be the same, because the one case that bails out
210283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // is a shift by 0, which leaves dst, and therefore src1, unchanged.
210383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  if (src1.is(rcx) || src2.is(rcx)) {
210483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    movq(kScratchRegister, rcx);
210583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  }
210683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  if (!dst.is(src1)) {
210783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    movq(dst, src1);
210883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  }
210983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  SmiToInteger32(rcx, src2);
211083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  orl(rcx, Immediate(kSmiShift));
211183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  shr_cl(dst);  // Shift is rcx modulo 0x1f + 32.
211283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  shl(dst, Immediate(kSmiShift));
211383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  testq(dst, dst);
211483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  if (src1.is(rcx) || src2.is(rcx)) {
211583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Label positive_result;
211683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    j(positive, &positive_result, Label::kNear);
211783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    if (src1.is(rcx)) {
211883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      movq(src1, kScratchRegister);
211983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    } else {
212083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      movq(src2, kScratchRegister);
212183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    }
212283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    jmp(on_not_smi_result, near_jump);
212383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    bind(&positive_result);
212483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  } else {
212583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    // src2 was zero and src1 negative.
212683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    j(negative, on_not_smi_result, near_jump);
212783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  }
212883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
212983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
213083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
21314af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.orgvoid MacroAssembler::SmiShiftArithmeticRight(Register dst,
21324af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                                             Register src1,
21334af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                                             Register src2) {
21349d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  ASSERT(!dst.is(kScratchRegister));
21359d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  ASSERT(!src1.is(kScratchRegister));
21369d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  ASSERT(!src2.is(kScratchRegister));
21374af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  ASSERT(!dst.is(rcx));
21389d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  if (src1.is(rcx)) {
21399d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    movq(kScratchRegister, src1);
21409d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  } else if (src2.is(rcx)) {
21419d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    movq(kScratchRegister, src2);
21429d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  }
21439d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  if (!dst.is(src1)) {
21449d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    movq(dst, src1);
21459d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  }
21464af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  SmiToInteger32(rcx, src2);
21479d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  orl(rcx, Immediate(kSmiShift));
2148c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  sar_cl(dst);  // Shift 32 + original rcx & 0x1f.
21499d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  shl(dst, Immediate(kSmiShift));
21509d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  if (src1.is(rcx)) {
21519d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    movq(src1, kScratchRegister);
21529d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  } else if (src2.is(rcx)) {
21539d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    movq(src2, kScratchRegister);
21549d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  }
21554af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org}
21564af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
21574af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
215883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgvoid MacroAssembler::SelectNonSmi(Register dst,
215983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                  Register src1,
216083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                  Register src2,
216183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                  Label* on_not_smis,
216283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                  Label::Distance near_jump) {
216383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT(!dst.is(kScratchRegister));
216483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT(!src1.is(kScratchRegister));
216583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT(!src2.is(kScratchRegister));
216683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT(!dst.is(src1));
216783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT(!dst.is(src2));
216883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // Both operands must not be smis.
216983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org#ifdef DEBUG
21708a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  Condition not_both_smis = NegateCondition(CheckBothSmi(src1, src2));
21718a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  Check(not_both_smis, kBothRegistersWereSmisInSelectNonSmi);
217283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org#endif
217380c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  STATIC_ASSERT(kSmiTag == 0);
217483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT_EQ(0, Smi::FromInt(0));
217583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  movl(kScratchRegister, Immediate(kSmiTagMask));
217683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  and_(kScratchRegister, src1);
217783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  testl(kScratchRegister, src2);
217883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // If non-zero then both are smis.
217983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  j(not_zero, on_not_smis, near_jump);
218083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
218183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // Exactly one operand is a smi.
218283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT_EQ(1, static_cast<int>(kSmiTagMask));
218383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // kScratchRegister still holds src1 & kSmiTag, which is either zero or one.
218483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  subq(kScratchRegister, Immediate(1));
218583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // If src1 is a smi, then scratch register all 1s, else it is all 0s.
218683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  movq(dst, src1);
218783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  xor_(dst, src2);
218883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  and_(dst, kScratchRegister);
218983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // If src1 is a smi, dst holds src1 ^ src2, else it is zero.
219083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  xor_(dst, src1);
219183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // If src1 is a smi, dst is src2, else it is src1, i.e., the non-smi.
219283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
219383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
219483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
21959d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.comSmiIndex MacroAssembler::SmiToIndex(Register dst,
21969d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com                                    Register src,
21979d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com                                    int shift) {
21984af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  ASSERT(is_uint6(shift));
21999d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  // There is a possible optimization if shift is in the range 60-63, but that
22009d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  // will (and must) never happen.
22019d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  if (!dst.is(src)) {
22029d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    movq(dst, src);
22039d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  }
22049d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  if (shift < kSmiShift) {
22059d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    sar(dst, Immediate(kSmiShift - shift));
22069d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  } else {
22079d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    shl(dst, Immediate(shift - kSmiShift));
22089d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  }
22094af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  return SmiIndex(dst, times_1);
22104af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org}
22114af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
22124af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.orgSmiIndex MacroAssembler::SmiToNegativeIndex(Register dst,
22134af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                                            Register src,
22144af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                                            int shift) {
22154af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Register src holds a positive smi.
22164af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  ASSERT(is_uint6(shift));
22179d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  if (!dst.is(src)) {
22189d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    movq(dst, src);
22194af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  }
22204af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  neg(dst);
22219d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  if (shift < kSmiShift) {
22229d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    sar(dst, Immediate(kSmiShift - shift));
22239d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  } else {
22249d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    shl(dst, Immediate(shift - kSmiShift));
22259d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  }
22264af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  return SmiIndex(dst, times_1);
22274af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org}
22284af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
22294af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
22307979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.orgvoid MacroAssembler::AddSmiField(Register dst, const Operand& src) {
22317979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  ASSERT_EQ(0, kSmiShift % kBitsPerByte);
22327979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  addl(dst, Operand(src, kSmiShift / kBitsPerByte));
22337979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org}
22347979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
22357979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
2236dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgvoid MacroAssembler::Push(Smi* source) {
2237dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  intptr_t smi = reinterpret_cast<intptr_t>(source);
2238dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  if (is_int32(smi)) {
2239dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    push(Immediate(static_cast<int32_t>(smi)));
2240dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  } else {
2241dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    Register constant = GetSmiConstant(source);
2242dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    push(constant);
2243dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  }
2244dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org}
2245dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
2246dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
2247662436e7b124b3535773535c671c53db322070b5verwaest@chromium.orgvoid MacroAssembler::PushInt64AsTwoSmis(Register src, Register scratch) {
2248662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  movq(scratch, src);
2249662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  // High bits.
2250662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  shr(src, Immediate(64 - kSmiShift));
2251662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  shl(src, Immediate(kSmiShift));
2252662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  push(src);
2253662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  // Low bits.
2254662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  shl(scratch, Immediate(kSmiShift));
2255662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  push(scratch);
2256662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org}
2257662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org
2258662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org
2259662436e7b124b3535773535c671c53db322070b5verwaest@chromium.orgvoid MacroAssembler::PopInt64AsTwoSmis(Register dst, Register scratch) {
2260662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  pop(scratch);
2261662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  // Low bits.
2262662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  shr(scratch, Immediate(kSmiShift));
2263662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  pop(dst);
2264662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  shr(dst, Immediate(kSmiShift));
2265662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  // High bits.
2266662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  shl(dst, Immediate(64 - kSmiShift));
2267662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  or_(dst, scratch);
2268662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org}
2269662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org
2270662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org
2271dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgvoid MacroAssembler::Test(const Operand& src, Smi* source) {
2272dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  testl(Operand(src, kIntSize), Immediate(source->value()));
2273dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org}
2274dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
2275dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
2276dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org// ----------------------------------------------------------------------------
2277dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
2278dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
2279528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.orgvoid MacroAssembler::LookupNumberStringCache(Register object,
2280528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                                             Register result,
2281528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                                             Register scratch1,
2282528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                                             Register scratch2,
2283528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                                             Label* not_found) {
2284528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // Use of registers. Register result is used as a temporary.
2285528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Register number_string_cache = result;
2286528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Register mask = scratch1;
2287528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Register scratch = scratch2;
2288528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
2289528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // Load the number string cache.
2290528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex);
2291528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
2292528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // Make the hash mask from the length of the number string cache. It
2293528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // contains two elements (number and string) for each cache entry.
2294528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  SmiToInteger32(
2295528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org      mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset));
2296528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  shrl(mask, Immediate(1));
2297528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  subq(mask, Immediate(1));  // Make mask.
2298528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
2299528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // Calculate the entry in the number string cache. The hash value in the
2300528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // number string cache for smis is just the smi value, and the hash for
2301528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // doubles is the xor of the upper and lower words. See
2302528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // Heap::GetNumberStringCache.
2303528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Label is_smi;
2304528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Label load_result_from_cache;
2305528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  JumpIfSmi(object, &is_smi);
2306528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  CheckMap(object,
2307528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org           isolate()->factory()->heap_number_map(),
2308528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org           not_found,
2309528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org           DONT_DO_SMI_CHECK);
2310528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
2311528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  STATIC_ASSERT(8 == kDoubleSize);
2312528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  movl(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4));
2313528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  xor_(scratch, FieldOperand(object, HeapNumber::kValueOffset));
2314528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  and_(scratch, mask);
2315528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // Each entry in string cache consists of two pointer sized fields,
2316528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // but times_twice_pointer_size (multiplication by 16) scale factor
2317528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // is not supported by addrmode on x64 platform.
2318528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // So we have to premultiply entry index before lookup.
2319528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  shl(scratch, Immediate(kPointerSizeLog2 + 1));
2320528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
2321528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Register index = scratch;
2322528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Register probe = mask;
2323528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  movq(probe,
2324528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org       FieldOperand(number_string_cache,
2325528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                    index,
2326528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                    times_1,
2327528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                    FixedArray::kHeaderSize));
2328528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  JumpIfSmi(probe, not_found);
2329528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  movsd(xmm0, FieldOperand(object, HeapNumber::kValueOffset));
2330528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  ucomisd(xmm0, FieldOperand(probe, HeapNumber::kValueOffset));
2331528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  j(parity_even, not_found);  // Bail out if NaN is involved.
2332528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  j(not_equal, not_found);  // The cache did not contain this value.
2333528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  jmp(&load_result_from_cache);
2334528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
2335528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  bind(&is_smi);
2336528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  SmiToInteger32(scratch, object);
2337528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  and_(scratch, mask);
2338528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // Each entry in string cache consists of two pointer sized fields,
2339528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // but times_twice_pointer_size (multiplication by 16) scale factor
2340528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // is not supported by addrmode on x64 platform.
2341528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // So we have to premultiply entry index before lookup.
2342528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  shl(scratch, Immediate(kPointerSizeLog2 + 1));
2343528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
2344528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // Check if the entry is the smi we are looking for.
2345528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  cmpq(object,
2346528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org       FieldOperand(number_string_cache,
2347528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                    index,
2348528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                    times_1,
2349528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                    FixedArray::kHeaderSize));
2350528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  j(not_equal, not_found);
2351528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
2352528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // Get the result from the cache.
2353528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  bind(&load_result_from_cache);
2354528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  movq(result,
2355528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org       FieldOperand(number_string_cache,
2356528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                    index,
2357528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                    times_1,
2358528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                    FixedArray::kHeaderSize + kPointerSize));
2359528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  IncrementCounter(isolate()->counters()->number_to_string_native(), 1);
2360528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org}
2361528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
2362528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
236383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgvoid MacroAssembler::JumpIfNotString(Register object,
236483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                     Register object_map,
236583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                     Label* not_string,
236683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                     Label::Distance near_jump) {
236783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Condition is_smi = CheckSmi(object);
236883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  j(is_smi, not_string, near_jump);
236983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  CmpObjectType(object, FIRST_NONSTRING_TYPE, object_map);
237083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  j(above_equal, not_string, near_jump);
237183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
237283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
237383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
237483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgvoid MacroAssembler::JumpIfNotBothSequentialAsciiStrings(
237583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Register first_object,
237683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Register second_object,
237783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Register scratch1,
237883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Register scratch2,
237983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Label* on_fail,
238083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Label::Distance near_jump) {
238183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // Check that both objects are not smis.
238283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Condition either_smi = CheckEitherSmi(first_object, second_object);
238383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  j(either_smi, on_fail, near_jump);
238483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
238583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // Load instance type for both strings.
238683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  movq(scratch1, FieldOperand(first_object, HeapObject::kMapOffset));
238783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  movq(scratch2, FieldOperand(second_object, HeapObject::kMapOffset));
238883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  movzxbl(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset));
238983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  movzxbl(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset));
239083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
23912efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  // Check that both are flat ASCII strings.
239283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT(kNotStringTag != 0);
239383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  const int kFlatAsciiStringMask =
239446a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org      kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
2395c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org  const int kFlatAsciiStringTag =
2396c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org      kStringTag | kOneByteStringTag | kSeqStringTag;
239783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
239883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  andl(scratch1, Immediate(kFlatAsciiStringMask));
239983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  andl(scratch2, Immediate(kFlatAsciiStringMask));
240083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // Interleave the bits to check both scratch1 and scratch2 in one test.
240146a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org  ASSERT_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3));
240246a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org  lea(scratch1, Operand(scratch1, scratch2, times_8, 0));
240383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  cmpl(scratch1,
240446a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org       Immediate(kFlatAsciiStringTag + (kFlatAsciiStringTag << 3)));
240583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  j(not_equal, on_fail, near_jump);
240683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
240783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
240883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
240983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgvoid MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii(
241083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Register instance_type,
241183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Register scratch,
241283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Label* failure,
241383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Label::Distance near_jump) {
241483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  if (!scratch.is(instance_type)) {
241583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    movl(scratch, instance_type);
241683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  }
241783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
241883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  const int kFlatAsciiStringMask =
241983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
242083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
242183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  andl(scratch, Immediate(kFlatAsciiStringMask));
2422e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  cmpl(scratch, Immediate(kStringTag | kSeqStringTag | kOneByteStringTag));
242383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  j(not_equal, failure, near_jump);
242483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
242583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
242683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
242783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgvoid MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialAscii(
242883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Register first_object_instance_type,
242983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Register second_object_instance_type,
243083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Register scratch1,
243183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Register scratch2,
243283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Label* on_fail,
243383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Label::Distance near_jump) {
243483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // Load instance type for both strings.
243583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  movq(scratch1, first_object_instance_type);
243683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  movq(scratch2, second_object_instance_type);
243783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
24382efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  // Check that both are flat ASCII strings.
243983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT(kNotStringTag != 0);
244046a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org  const int kFlatAsciiStringMask =
244146a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org      kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
2442c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org  const int kFlatAsciiStringTag =
2443c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org      kStringTag | kOneByteStringTag | kSeqStringTag;
244483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
244583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  andl(scratch1, Immediate(kFlatAsciiStringMask));
244683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  andl(scratch2, Immediate(kFlatAsciiStringMask));
244783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // Interleave the bits to check both scratch1 and scratch2 in one test.
244846a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org  ASSERT_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3));
244946a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org  lea(scratch1, Operand(scratch1, scratch2, times_8, 0));
245083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  cmpl(scratch1,
245146a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org       Immediate(kFlatAsciiStringTag + (kFlatAsciiStringTag << 3)));
245283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  j(not_equal, on_fail, near_jump);
245383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
245483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
245583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
24561510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.orgtemplate<class T>
24571510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.orgstatic void JumpIfNotUniqueNameHelper(MacroAssembler* masm,
24581510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org                                      T operand_or_register,
24591510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org                                      Label* not_unique_name,
24601510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org                                      Label::Distance distance) {
2461ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
2462ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  Label succeed;
2463ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  masm->testb(operand_or_register,
2464ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org              Immediate(kIsNotStringMask | kIsNotInternalizedMask));
2465ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  masm->j(zero, &succeed, Label::kNear);
2466ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  masm->cmpb(operand_or_register, Immediate(static_cast<uint8_t>(SYMBOL_TYPE)));
2467ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  masm->j(not_equal, not_unique_name, distance);
2468ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
2469ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  masm->bind(&succeed);
24701510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org}
24711510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
24721510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
24731510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.orgvoid MacroAssembler::JumpIfNotUniqueName(Operand operand,
24741510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org                                         Label* not_unique_name,
24751510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org                                         Label::Distance distance) {
24761510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  JumpIfNotUniqueNameHelper<Operand>(this, operand, not_unique_name, distance);
24771510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org}
24781510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
24791510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
24801510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.orgvoid MacroAssembler::JumpIfNotUniqueName(Register reg,
24811510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org                                         Label* not_unique_name,
24821510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org                                         Label::Distance distance) {
24831510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  JumpIfNotUniqueNameHelper<Register>(this, reg, not_unique_name, distance);
24841510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org}
24851510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
24867979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
24874a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.orgvoid MacroAssembler::Move(Register dst, Register src) {
24884a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  if (!dst.is(src)) {
24894a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    movq(dst, src);
24904a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  }
24914a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org}
24924a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
24934a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
24945aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.orgvoid MacroAssembler::Move(Register dst, Handle<Object> source) {
249579e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org  AllowDeferredHandleDereference smi_check;
24965aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  if (source->IsSmi()) {
24979d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    Move(dst, Smi::cast(*source));
24985aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  } else {
2499c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org    MoveHeapObject(dst, source);
25005aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  }
25015aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org}
25025aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
25035aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
25045aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.orgvoid MacroAssembler::Move(const Operand& dst, Handle<Object> source) {
250579e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org  AllowDeferredHandleDereference smi_check;
250668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  if (source->IsSmi()) {
25079d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    Move(dst, Smi::cast(*source));
250868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  } else {
2509c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org    MoveHeapObject(kScratchRegister, source);
251068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    movq(dst, kScratchRegister);
251168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
25125aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org}
25135aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
25145aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
25155aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.orgvoid MacroAssembler::Cmp(Register dst, Handle<Object> source) {
251679e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org  AllowDeferredHandleDereference smi_check;
25179d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  if (source->IsSmi()) {
2518badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org    Cmp(dst, Smi::cast(*source));
25199d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  } else {
2520c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org    MoveHeapObject(kScratchRegister, source);
25219d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    cmpq(dst, kScratchRegister);
25229d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  }
25235aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org}
25245aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
25255aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
25263e87580939cb78c5802369f723680d4a16cc2902ager@chromium.orgvoid MacroAssembler::Cmp(const Operand& dst, Handle<Object> source) {
252779e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org  AllowDeferredHandleDereference smi_check;
252868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  if (source->IsSmi()) {
2529badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org    Cmp(dst, Smi::cast(*source));
253068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  } else {
2531c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org    MoveHeapObject(kScratchRegister, source);
253268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    cmpq(dst, kScratchRegister);
253368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
25343e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org}
25353e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org
25363e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org
25375aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.orgvoid MacroAssembler::Push(Handle<Object> source) {
253879e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org  AllowDeferredHandleDereference smi_check;
253968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  if (source->IsSmi()) {
25409d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    Push(Smi::cast(*source));
254168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  } else {
2542c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org    MoveHeapObject(kScratchRegister, source);
254368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    push(kScratchRegister);
254468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
25455aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org}
25465aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
25475aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
2548c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.orgvoid MacroAssembler::MoveHeapObject(Register result,
2549c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org                                    Handle<Object> object) {
255079e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org  AllowDeferredHandleDereference using_raw_address;
2551c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  ASSERT(object->IsHeapObject());
255264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  if (isolate()->heap()->InNewSpace(*object)) {
255341728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org    Handle<Cell> cell = isolate()->factory()->NewCell(object);
255441728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org    movq(result, cell, RelocInfo::CELL);
255564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    movq(result, Operand(result, 0));
255664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  } else {
2557c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org    movq(result, object, RelocInfo::EMBEDDED_OBJECT);
255864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  }
255964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org}
256064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
256164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
256241728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.orgvoid MacroAssembler::LoadGlobalCell(Register dst, Handle<Cell> cell) {
256364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  if (dst.is(rax)) {
256479e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org    AllowDeferredHandleDereference embedding_raw_address;
256541728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org    load_rax(cell.location(), RelocInfo::CELL);
256664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  } else {
256741728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org    movq(dst, cell, RelocInfo::CELL);
256864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    movq(dst, Operand(dst, 0));
256964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  }
257064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org}
257164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
257264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
257313bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.orgvoid MacroAssembler::Drop(int stack_elements) {
257413bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  if (stack_elements > 0) {
257513bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org    addq(rsp, Immediate(stack_elements * kPointerSize));
257613bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  }
257713bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org}
257813bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org
257913bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org
2580394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.comvoid MacroAssembler::TestBit(const Operand& src, int bits) {
2581394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  int byte_offset = bits / kBitsPerByte;
2582394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  int bit_in_byte = bits & (kBitsPerByte - 1);
2583394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  testb(Operand(src, byte_offset), Immediate(1 << bit_in_byte));
2584394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com}
2585394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
2586394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
2587eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.orgvoid MacroAssembler::Jump(ExternalReference ext) {
2588ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  LoadAddress(kScratchRegister, ext);
2589eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  jmp(kScratchRegister);
2590eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org}
2591eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
2592eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
2593eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.orgvoid MacroAssembler::Jump(Address destination, RelocInfo::Mode rmode) {
2594eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  movq(kScratchRegister, destination, rmode);
2595eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  jmp(kScratchRegister);
2596eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org}
2597eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
2598eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
25995aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.orgvoid MacroAssembler::Jump(Handle<Code> code_object, RelocInfo::Mode rmode) {
2600c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // TODO(X64): Inline this
2601c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  jmp(code_object, rmode);
26025aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org}
26035aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
26045aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
2605ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgint MacroAssembler::CallSize(ExternalReference ext) {
2606ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // Opcode for call kScratchRegister is: Rex.B FF D4 (three bytes).
2607594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  return LoadAddressSize(ext) +
2608594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org         Assembler::kCallScratchRegisterInstructionLength;
2609ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org}
2610ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
2611ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
2612eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.orgvoid MacroAssembler::Call(ExternalReference ext) {
2613eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org#ifdef DEBUG
2614ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  int end_position = pc_offset() + CallSize(ext);
2615eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org#endif
2616ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  LoadAddress(kScratchRegister, ext);
2617eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  call(kScratchRegister);
2618eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org#ifdef DEBUG
2619ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  CHECK_EQ(end_position, pc_offset());
2620eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org#endif
2621eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org}
2622eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
2623eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
2624eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.orgvoid MacroAssembler::Call(Address destination, RelocInfo::Mode rmode) {
2625eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org#ifdef DEBUG
2626ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  int end_position = pc_offset() + CallSize(destination, rmode);
2627eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org#endif
2628eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  movq(kScratchRegister, destination, rmode);
2629eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  call(kScratchRegister);
2630eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org#ifdef DEBUG
2631ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  CHECK_EQ(pc_offset(), end_position);
2632eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org#endif
2633eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org}
2634eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
2635eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
26368e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.orgvoid MacroAssembler::Call(Handle<Code> code_object,
26378e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org                          RelocInfo::Mode rmode,
2638471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org                          TypeFeedbackId ast_id) {
2639eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org#ifdef DEBUG
2640ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  int end_position = pc_offset() + CallSize(code_object);
2641eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org#endif
2642c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  ASSERT(RelocInfo::IsCodeTarget(rmode) ||
2643c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org      rmode == RelocInfo::CODE_AGE_SEQUENCE);
26448e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  call(code_object, rmode, ast_id);
2645eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org#ifdef DEBUG
2646ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  CHECK_EQ(end_position, pc_offset());
2647eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org#endif
26485aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org}
26495aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
26505aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
26510a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.orgvoid MacroAssembler::Pushad() {
26520a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  push(rax);
26530a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  push(rcx);
26540a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  push(rdx);
26550a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  push(rbx);
26560a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  // Not pushing rsp or rbp.
26570a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  push(rsi);
26580a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  push(rdi);
26590a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  push(r8);
26600a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  push(r9);
26610a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  // r10 is kScratchRegister.
26620a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  push(r11);
2663b08986cb66c3f6687247cb6da186c1e73057e399whesse@chromium.org  // r12 is kSmiConstantRegister.
26640a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  // r13 is kRootRegister.
26650a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  push(r14);
2666b08986cb66c3f6687247cb6da186c1e73057e399whesse@chromium.org  push(r15);
266749edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  STATIC_ASSERT(11 == kNumSafepointSavedRegisters);
266849edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  // Use lea for symmetry with Popad.
26693a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  int sp_delta =
26703a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      (kNumSafepointRegisters - kNumSafepointSavedRegisters) * kPointerSize;
26713a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  lea(rsp, Operand(rsp, -sp_delta));
26720a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org}
26730a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
26740a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
26750a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.orgvoid MacroAssembler::Popad() {
267649edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  // Popad must not change the flags, so use lea instead of addq.
26773a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  int sp_delta =
26783a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      (kNumSafepointRegisters - kNumSafepointSavedRegisters) * kPointerSize;
26793a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  lea(rsp, Operand(rsp, sp_delta));
2680b08986cb66c3f6687247cb6da186c1e73057e399whesse@chromium.org  pop(r15);
26810a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  pop(r14);
26820a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  pop(r11);
26830a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  pop(r9);
26840a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  pop(r8);
26850a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  pop(rdi);
26860a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  pop(rsi);
26870a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  pop(rbx);
26880a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  pop(rdx);
26890a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  pop(rcx);
26900a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  pop(rax);
26910a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org}
26920a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
26930a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
26940ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.orgvoid MacroAssembler::Dropad() {
269549edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  addq(rsp, Immediate(kNumSafepointRegisters * kPointerSize));
26960ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org}
26970ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org
26980ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org
26990ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org// Order general registers are pushed by Pushad:
2700b08986cb66c3f6687247cb6da186c1e73057e399whesse@chromium.org// rax, rcx, rdx, rbx, rsi, rdi, r8, r9, r11, r14, r15.
27011456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int
27021456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgMacroAssembler::kSafepointPushRegisterIndices[Register::kNumRegisters] = {
27030ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    0,
27040ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    1,
27050ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    2,
27060ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    3,
27070ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    -1,
27080ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    -1,
27090ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    4,
27100ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    5,
27110ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    6,
27120ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    7,
27130ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    -1,
27140ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    8,
27150ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    -1,
2716b08986cb66c3f6687247cb6da186c1e73057e399whesse@chromium.org    -1,
2717b08986cb66c3f6687247cb6da186c1e73057e399whesse@chromium.org    9,
2718b08986cb66c3f6687247cb6da186c1e73057e399whesse@chromium.org    10
27190ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org};
27200ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org
27210ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org
272246839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.orgvoid MacroAssembler::StoreToSafepointRegisterSlot(Register dst,
272346839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org                                                  const Immediate& imm) {
272446839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  movq(SafepointRegisterSlot(dst), imm);
272546839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org}
272646839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org
272746839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org
27283a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgvoid MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Register src) {
27293a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  movq(SafepointRegisterSlot(dst), src);
27303a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org}
27313a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
27323a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
27335d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.orgvoid MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) {
27345d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  movq(dst, SafepointRegisterSlot(src));
27355d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org}
27365d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org
27375d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org
27383a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgOperand MacroAssembler::SafepointRegisterSlot(Register reg) {
27393a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  return Operand(rsp, SafepointRegisterStackIndex(reg.code()) * kPointerSize);
27403a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org}
27413a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
27423a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
274378d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.orgvoid MacroAssembler::PushTryHandler(StackHandler::Kind kind,
274404e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org                                    int handler_index) {
2745eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // Adjust this code if not the case.
2746d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize +
2747d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org                                                kFPOnStackSize);
274804e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
274904e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
275004e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
275104e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
275204e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
275304e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org
275404e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // We will build up the handler from the bottom by pushing on the stack.
275578d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org  // First push the frame pointer and context.
275678d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org  if (kind == StackHandler::JS_ENTRY) {
275704e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org    // The frame pointer does not point to a JS frame so we save NULL for
275804e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org    // rbp. We expect the code throwing an exception to check rbp before
275904e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org    // dereferencing it to restore the context.
2760eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    push(Immediate(0));  // NULL frame pointer.
27614acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org    Push(Smi::FromInt(0));  // No context.
276278d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org  } else {
276378d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org    push(rbp);
276478d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org    push(rsi);
2765e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  }
276604e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org
276704e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // Push the state and the code object.
276878d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org  unsigned state =
276978d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      StackHandler::IndexField::encode(handler_index) |
277078d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      StackHandler::KindField::encode(kind);
277104e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  push(Immediate(state));
277204e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  Push(CodeObject());
277304e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org
277404e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // Link the current handler as the next handler.
277504e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
277604e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  push(ExternalOperand(handler_address));
277704e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // Set this new handler as the current one.
277804e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  movq(ExternalOperand(handler_address), rsp);
2779e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org}
2780e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
2781e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
278213bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.orgvoid MacroAssembler::PopTryHandler() {
278304e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
278404e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
278504e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  pop(ExternalOperand(handler_address));
278613bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  addq(rsp, Immediate(StackHandlerConstants::kSize - kPointerSize));
278713bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org}
278813bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org
278913bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org
279004e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.orgvoid MacroAssembler::JumpToHandlerEntry() {
279104e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // Compute the handler entry address and jump to it.  The handler table is
279204e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // a fixed array of (smi-tagged) code offsets.
279304e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // rax = exception, rdi = code object, rdx = state.
279404e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  movq(rbx, FieldOperand(rdi, Code::kHandlerTableOffset));
279504e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  shr(rdx, Immediate(StackHandler::kKindWidth));
27961510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  movq(rdx,
27971510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org       FieldOperand(rbx, rdx, times_pointer_size, FixedArray::kHeaderSize));
279804e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  SmiToInteger64(rdx, rdx);
279904e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  lea(rdi, FieldOperand(rdi, rdx, times_1, Code::kHeaderSize));
280004e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  jmp(rdi);
280104e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org}
280204e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org
280304e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org
280449edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.orgvoid MacroAssembler::Throw(Register value) {
28054acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org  // Adjust this code if not the case.
2806d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize +
2807d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org                                                kFPOnStackSize);
280804e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
280904e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
281004e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
281104e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
281204e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
281304e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org
281404e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // The exception is expected in rax.
281549edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  if (!value.is(rax)) {
281649edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org    movq(rax, value);
281749edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  }
281804e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // Drop the stack pointer to the top of the top handler.
281983e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org  ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
282004e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  movq(rsp, ExternalOperand(handler_address));
282104e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // Restore the next handler.
282204e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  pop(ExternalOperand(handler_address));
282304e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org
282404e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // Remove the code object and state, compute the handler address in rdi.
282504e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  pop(rdi);  // Code object.
282604e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  pop(rdx);  // Offset and state.
282704e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org
282804e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // Restore the context and frame pointer.
28294acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org  pop(rsi);  // Context.
28304acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org  pop(rbp);  // Frame pointer.
283149edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
28324acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org  // If the handler is a JS frame, restore the context to the frame.
283304e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // (kind == ENTRY) == (rbp == 0) == (rsi == 0), so we could test either
283404e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // rbp or rsi.
283583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label skip;
283604e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  testq(rsi, rsi);
283704e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  j(zero, &skip, Label::kNear);
28384acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org  movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi);
283949edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  bind(&skip);
28404acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org
284104e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  JumpToHandlerEntry();
284249edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org}
284349edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
284449edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
284565a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.orgvoid MacroAssembler::ThrowUncatchable(Register value) {
28464acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org  // Adjust this code if not the case.
2847d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize +
2848d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org                                                kFPOnStackSize);
284904e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
285004e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
285104e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
285204e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
285304e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
285449edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
2855c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  // The exception is expected in rax.
285665a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  if (!value.is(rax)) {
2857c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org    movq(rax, value);
285849edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  }
2859c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  // Drop the stack pointer to the top of the top stack handler.
2860c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
2861c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  Load(rsp, handler_address);
286249edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
2863c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  // Unwind the handlers until the top ENTRY handler is found.
2864c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  Label fetch_next, check_kind;
2865c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  jmp(&check_kind, Label::kNear);
2866c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  bind(&fetch_next);
2867c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  movq(rsp, Operand(rsp, StackHandlerConstants::kNextOffset));
2868c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org
2869c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  bind(&check_kind);
287078d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org  STATIC_ASSERT(StackHandler::JS_ENTRY == 0);
287104e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  testl(Operand(rsp, StackHandlerConstants::kStateOffset),
287204e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org        Immediate(StackHandler::KindField::kMask));
287304e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  j(not_zero, &fetch_next);
2874c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org
2875c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  // Set the top handler address to next handler past the top ENTRY handler.
2876c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  pop(ExternalOperand(handler_address));
2877c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org
287804e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // Remove the code object and state, compute the handler address in rdi.
287904e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  pop(rdi);  // Code object.
288004e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  pop(rdx);  // Offset and state.
288104e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org
288204e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // Clear the context pointer and frame pointer (0 was saved in the handler).
2883c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  pop(rsi);
2884c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  pop(rbp);
288549edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
288604e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  JumpToHandlerEntry();
288749edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org}
288849edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
288949edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
2890eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.orgvoid MacroAssembler::Ret() {
2891eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  ret(0);
2892eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org}
2893eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
2894eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
2895d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.comvoid MacroAssembler::Ret(int bytes_dropped, Register scratch) {
2896d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  if (is_uint16(bytes_dropped)) {
2897d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com    ret(bytes_dropped);
2898d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  } else {
2899594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    PopReturnAddressTo(scratch);
2900d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com    addq(rsp, Immediate(bytes_dropped));
2901594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    PushReturnAddressFrom(scratch);
2902d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com    ret(0);
2903d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  }
2904d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com}
2905d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com
2906d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com
29073e87580939cb78c5802369f723680d4a16cc2902ager@chromium.orgvoid MacroAssembler::FCmp() {
29083811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  fucomip();
290940b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  fstp(0);
29103e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org}
29113e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org
29123e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org
2913eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.orgvoid MacroAssembler::CmpObjectType(Register heap_object,
2914eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org                                   InstanceType type,
2915eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org                                   Register map) {
2916eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  movq(map, FieldOperand(heap_object, HeapObject::kMapOffset));
2917eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  CmpInstanceType(map, type);
2918eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org}
2919eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
2920eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
2921eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.orgvoid MacroAssembler::CmpInstanceType(Register map, InstanceType type) {
2922eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  cmpb(FieldOperand(map, Map::kInstanceTypeOffset),
2923eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org       Immediate(static_cast<int8_t>(type)));
2924eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org}
2925eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
2926eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
2927d6076d96a1411932548838e5960b594564264010erik.corry@gmail.comvoid MacroAssembler::CheckFastElements(Register map,
2928d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com                                       Label* fail,
2929d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com                                       Label::Distance distance) {
2930830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org  STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
2931830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org  STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
2932830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org  STATIC_ASSERT(FAST_ELEMENTS == 2);
2933830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org  STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
2934c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  cmpb(FieldOperand(map, Map::kBitField2Offset),
2935830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org       Immediate(Map::kMaximumBitField2FastHoleyElementValue));
2936c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  j(above, fail, distance);
2937c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
2938c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
2939c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
2940c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid MacroAssembler::CheckFastObjectElements(Register map,
2941c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                             Label* fail,
2942c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                             Label::Distance distance) {
2943830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org  STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
2944830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org  STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
2945830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org  STATIC_ASSERT(FAST_ELEMENTS == 2);
2946830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org  STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
2947c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  cmpb(FieldOperand(map, Map::kBitField2Offset),
2948830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org       Immediate(Map::kMaximumBitField2FastHoleySmiElementValue));
2949c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  j(below_equal, fail, distance);
2950d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com  cmpb(FieldOperand(map, Map::kBitField2Offset),
2951830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org       Immediate(Map::kMaximumBitField2FastHoleyElementValue));
2952d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com  j(above, fail, distance);
2953d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com}
2954d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com
2955d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com
2956830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.orgvoid MacroAssembler::CheckFastSmiElements(Register map,
2957830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org                                          Label* fail,
2958830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org                                          Label::Distance distance) {
2959830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org  STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
2960830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org  STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
2961c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  cmpb(FieldOperand(map, Map::kBitField2Offset),
2962830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org       Immediate(Map::kMaximumBitField2FastHoleySmiElementValue));
2963c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  j(above, fail, distance);
2964c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
2965c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
2966c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
2967c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid MacroAssembler::StoreNumberToDoubleElements(
2968c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Register maybe_number,
2969c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Register elements,
2970394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    Register index,
2971c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    XMMRegister xmm_scratch,
2972fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    Label* fail,
2973fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    int elements_offset) {
2974c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Label smi_value, is_nan, maybe_nan, not_nan, have_double_value, done;
2975c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
2976c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  JumpIfSmi(maybe_number, &smi_value, Label::kNear);
2977c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
2978c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  CheckMap(maybe_number,
2979c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com           isolate()->factory()->heap_number_map(),
2980c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com           fail,
2981c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com           DONT_DO_SMI_CHECK);
2982c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
2983c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Double value, canonicalize NaN.
2984c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  uint32_t offset = HeapNumber::kValueOffset + sizeof(kHoleNanLower32);
2985c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  cmpl(FieldOperand(maybe_number, offset),
2986c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com       Immediate(kNaNOrInfinityLowerBoundUpper32));
2987c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  j(greater_equal, &maybe_nan, Label::kNear);
2988c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
2989c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  bind(&not_nan);
2990c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  movsd(xmm_scratch, FieldOperand(maybe_number, HeapNumber::kValueOffset));
2991c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  bind(&have_double_value);
2992fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  movsd(FieldOperand(elements, index, times_8,
2993fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                     FixedDoubleArray::kHeaderSize - elements_offset),
2994c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        xmm_scratch);
2995c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  jmp(&done);
2996c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
2997c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  bind(&maybe_nan);
2998c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise
2999c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // it's an Infinity, and the non-NaN code path applies.
3000c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  j(greater, &is_nan, Label::kNear);
3001c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  cmpl(FieldOperand(maybe_number, HeapNumber::kValueOffset), Immediate(0));
3002c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  j(zero, &not_nan);
3003c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  bind(&is_nan);
3004c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Convert all NaNs to the same canonical NaN value when they are stored in
3005c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // the double array.
3006c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Set(kScratchRegister, BitCast<uint64_t>(
3007c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      FixedDoubleArray::canonical_not_the_hole_nan_as_double()));
3008c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  movq(xmm_scratch, kScratchRegister);
3009c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  jmp(&have_double_value, Label::kNear);
3010c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
3011c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  bind(&smi_value);
3012c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Value is a smi. convert to a double and store.
3013c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Preserve original value.
3014c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  SmiToInteger32(kScratchRegister, maybe_number);
3015528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Cvtlsi2sd(xmm_scratch, kScratchRegister);
3016fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  movsd(FieldOperand(elements, index, times_8,
3017fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                     FixedDoubleArray::kHeaderSize - elements_offset),
3018c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        xmm_scratch);
3019c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  bind(&done);
3020c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
3021c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
3022c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
3023935a7790c70d49e252069bc2d34eaa72f8c6677fmachenbach@chromium.orgvoid MacroAssembler::CompareMap(Register obj, Handle<Map> map) {
3024f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  Cmp(FieldOperand(obj, HeapObject::kMapOffset), map);
3025f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com}
3026f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com
3027f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com
30285c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid MacroAssembler::CheckMap(Register obj,
30295c838251403b0be9a882540f1922577abba4c872ager@chromium.org                              Handle<Map> map,
30305c838251403b0be9a882540f1922577abba4c872ager@chromium.org                              Label* fail,
3031a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org                              SmiCheckType smi_check_type) {
3032c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  if (smi_check_type == DO_SMI_CHECK) {
30335c838251403b0be9a882540f1922577abba4c872ager@chromium.org    JumpIfSmi(obj, fail);
30345c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
3035f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com
3036935a7790c70d49e252069bc2d34eaa72f8c6677fmachenbach@chromium.org  CompareMap(obj, map);
30375c838251403b0be9a882540f1922577abba4c872ager@chromium.org  j(not_equal, fail);
30385c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
30395c838251403b0be9a882540f1922577abba4c872ager@chromium.org
30405c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3041c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.orgvoid MacroAssembler::ClampUint8(Register reg) {
3042c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label done;
3043c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  testl(reg, Immediate(0xFFFFFF00));
3044c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  j(zero, &done, Label::kNear);
3045c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  setcc(negative, reg);  // 1 if negative, 0 if positive.
3046c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  decb(reg);  // 0 if negative, 255 if positive.
3047c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  bind(&done);
3048c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org}
3049c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
3050c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
3051c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.orgvoid MacroAssembler::ClampDoubleToUint8(XMMRegister input_reg,
3052c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                                        XMMRegister temp_xmm_reg,
305389e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org                                        Register result_reg) {
3054c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label done;
305589e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org  Label conv_failure;
3056c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  xorps(temp_xmm_reg, temp_xmm_reg);
305746839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  cvtsd2si(result_reg, input_reg);
3058c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  testl(result_reg, Immediate(0xFFFFFF00));
3059c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  j(zero, &done, Label::kNear);
306089e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org  cmpl(result_reg, Immediate(0x80000000));
306189e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org  j(equal, &conv_failure, Label::kNear);
306289e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org  movl(result_reg, Immediate(0));
306389e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org  setcc(above, result_reg);
306489e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org  subl(result_reg, Immediate(1));
306589e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org  andl(result_reg, Immediate(255));
306689e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org  jmp(&done, Label::kNear);
306789e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org  bind(&conv_failure);
306889e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org  Set(result_reg, 0);
306989e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org  ucomisd(input_reg, temp_xmm_reg);
307089e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org  j(below, &done, Label::kNear);
3071c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Set(result_reg, 255);
3072c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  bind(&done);
3073c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org}
3074c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
3075c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
307646839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.orgvoid MacroAssembler::LoadUint32(XMMRegister dst,
307746839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org                                Register src,
307846839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org                                XMMRegister scratch) {
30792f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org  if (FLAG_debug_code) {
30802f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org    cmpq(src, Immediate(0xffffffff));
3081594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    Assert(below_equal, kInputGPRIsExpectedToHaveUpper32Cleared);
30822f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org  }
30832f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org  cvtqsi2sd(dst, src);
308446839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org}
308546839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org
308646839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org
3087c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.orgvoid MacroAssembler::SlowTruncateToI(Register result_reg,
3088c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org                                     Register input_reg,
3089c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org                                     int offset) {
3090c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  DoubleToIStub stub(input_reg, result_reg, offset, true);
3091c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  call(stub.GetCode(isolate()), RelocInfo::CODE_TARGET);
3092c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org}
3093c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
3094c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
3095c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.orgvoid MacroAssembler::TruncateHeapNumberToI(Register result_reg,
3096c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org                                           Register input_reg) {
3097c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  Label done;
3098c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
3099c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  cvttsd2siq(result_reg, xmm0);
3100c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  Set(kScratchRegister, V8_UINT64_C(0x8000000000000000));
3101c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  cmpq(result_reg, kScratchRegister);
3102c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  j(not_equal, &done, Label::kNear);
3103c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
3104c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  // Slow case.
3105c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  if (input_reg.is(result_reg)) {
3106c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org    subq(rsp, Immediate(kDoubleSize));
3107c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org    movsd(MemOperand(rsp, 0), xmm0);
3108c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org    SlowTruncateToI(result_reg, rsp, 0);
3109c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org    addq(rsp, Immediate(kDoubleSize));
3110c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  } else {
3111c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org    SlowTruncateToI(result_reg, input_reg);
3112c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  }
3113c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
3114c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  bind(&done);
3115c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org}
3116c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
3117c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
3118c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.orgvoid MacroAssembler::TruncateDoubleToI(Register result_reg,
3119c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org                                       XMMRegister input_reg) {
3120c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  Label done;
3121c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  cvttsd2siq(result_reg, input_reg);
3122e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  movq(kScratchRegister, V8_INT64_C(0x8000000000000000));
3123c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  cmpq(result_reg, kScratchRegister);
3124c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  j(not_equal, &done, Label::kNear);
3125c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
3126c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  subq(rsp, Immediate(kDoubleSize));
3127c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  movsd(MemOperand(rsp, 0), input_reg);
3128c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  SlowTruncateToI(result_reg, rsp, 0);
3129c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  addq(rsp, Immediate(kDoubleSize));
3130c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
3131c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  bind(&done);
3132c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org}
3133c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
3134c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
3135c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.orgvoid MacroAssembler::DoubleToI(Register result_reg,
3136c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org                               XMMRegister input_reg,
3137c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org                               XMMRegister scratch,
3138c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org                               MinusZeroMode minus_zero_mode,
3139c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org                               Label* conversion_failed,
3140c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org                               Label::Distance dst) {
3141c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  cvttsd2si(result_reg, input_reg);
3142528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Cvtlsi2sd(xmm0, result_reg);
3143c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  ucomisd(xmm0, input_reg);
3144c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  j(not_equal, conversion_failed, dst);
3145c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  j(parity_even, conversion_failed, dst);  // NaN.
3146c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  if (minus_zero_mode == FAIL_ON_MINUS_ZERO) {
3147c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org    Label done;
3148c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org    // The integer converted back is equal to the original. We
3149c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org    // only have to test if we got -0 as an input.
3150c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org    testl(result_reg, result_reg);
3151c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org    j(not_zero, &done, Label::kNear);
3152c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org    movmskpd(result_reg, input_reg);
3153c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org    // Bit 0 contains the sign of the double in input_reg.
3154c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org    // If input was positive, we are ok and return 0, otherwise
3155c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org    // jump to conversion_failed.
3156c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org    andl(result_reg, Immediate(1));
3157c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org    j(not_zero, conversion_failed, dst);
3158c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org    bind(&done);
3159c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  }
3160c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org}
3161c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
3162c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
3163c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.orgvoid MacroAssembler::TaggedToI(Register result_reg,
3164c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org                               Register input_reg,
3165c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org                               XMMRegister temp,
3166c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org                               MinusZeroMode minus_zero_mode,
3167c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org                               Label* lost_precision,
3168c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org                               Label::Distance dst) {
3169c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  Label done;
3170c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  ASSERT(!temp.is(xmm0));
3171c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
3172c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  // Heap number map check.
3173c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset),
3174c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org              Heap::kHeapNumberMapRootIndex);
3175c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  j(not_equal, lost_precision, dst);
3176c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
3177c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
3178c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  cvttsd2si(result_reg, xmm0);
3179528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Cvtlsi2sd(temp, result_reg);
3180c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  ucomisd(xmm0, temp);
3181c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  RecordComment("Deferred TaggedToI: lost precision");
3182c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  j(not_equal, lost_precision, dst);
3183c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  RecordComment("Deferred TaggedToI: NaN");
3184c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  j(parity_even, lost_precision, dst);  // NaN.
3185c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  if (minus_zero_mode == FAIL_ON_MINUS_ZERO) {
3186c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org    testl(result_reg, result_reg);
3187c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org    j(not_zero, &done, Label::kNear);
3188c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org    movmskpd(result_reg, xmm0);
3189c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org    andl(result_reg, Immediate(1));
3190c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org    j(not_zero, lost_precision, dst);
3191c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  }
3192c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  bind(&done);
3193c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org}
3194c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
3195c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
31969af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.orgvoid MacroAssembler::Throw(BailoutReason reason) {
31979af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org#ifdef DEBUG
31989af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  const char* msg = GetBailoutReason(reason);
31999af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  if (msg != NULL) {
32009af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org    RecordComment("Throw message: ");
32019af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org    RecordComment(msg);
32029af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  }
32039af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org#endif
32049af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org
32059af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  push(rax);
32069af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  Push(Smi::FromInt(reason));
32079af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  if (!has_frame_) {
32089af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org    // We don't actually want to generate a pile of code for this, so just
32099af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org    // claim there is a stack frame, without generating one.
32109af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org    FrameScope scope(this, StackFrame::NONE);
32119af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org    CallRuntime(Runtime::kThrowMessage, 1);
32129af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  } else {
32139af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org    CallRuntime(Runtime::kThrowMessage, 1);
32149af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  }
32159af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  // Control will not return here.
32169af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  int3();
32179af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org}
32189af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org
32199af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org
32209af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.orgvoid MacroAssembler::ThrowIf(Condition cc, BailoutReason reason) {
32219af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  Label L;
32229af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  j(NegateCondition(cc), &L);
32239af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  Throw(reason);
32249af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  // will not return here
32259af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  bind(&L);
32269af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org}
32279af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org
32289af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org
322940cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.orgvoid MacroAssembler::LoadInstanceDescriptors(Register map,
323040cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org                                             Register descriptors) {
323189e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org  movq(descriptors, FieldOperand(map, Map::kDescriptorsOffset));
323240cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org}
323340cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org
323440cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org
323506ab2ec756e44eeaf7500b9794f9d2abc79dc8cfverwaest@chromium.orgvoid MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) {
323606ab2ec756e44eeaf7500b9794f9d2abc79dc8cfverwaest@chromium.org  movq(dst, FieldOperand(map, Map::kBitField3Offset));
323706ab2ec756e44eeaf7500b9794f9d2abc79dc8cfverwaest@chromium.org  DecodeField<Map::NumberOfOwnDescriptorsBits>(dst);
323806ab2ec756e44eeaf7500b9794f9d2abc79dc8cfverwaest@chromium.org}
323906ab2ec756e44eeaf7500b9794f9d2abc79dc8cfverwaest@chromium.org
324006ab2ec756e44eeaf7500b9794f9d2abc79dc8cfverwaest@chromium.org
3241355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.orgvoid MacroAssembler::EnumLength(Register dst, Register map) {
3242355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  STATIC_ASSERT(Map::EnumLengthBits::kShift == 0);
3243355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  movq(dst, FieldOperand(map, Map::kBitField3Offset));
3244355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  Move(kScratchRegister, Smi::FromInt(Map::EnumLengthBits::kMask));
3245355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  and_(dst, kScratchRegister);
3246355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org}
3247355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org
3248355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org
3249ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.orgvoid MacroAssembler::DispatchMap(Register obj,
32502bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org                                 Register unused,
3251ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org                                 Handle<Map> map,
3252ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org                                 Handle<Code> success,
3253ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org                                 SmiCheckType smi_check_type) {
3254ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org  Label fail;
3255ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org  if (smi_check_type == DO_SMI_CHECK) {
3256ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org    JumpIfSmi(obj, &fail);
3257ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org  }
3258ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org  Cmp(FieldOperand(obj, HeapObject::kMapOffset), map);
3259ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org  j(equal, success, RelocInfo::CODE_TARGET);
3260ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org
3261ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org  bind(&fail);
3262ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org}
3263ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org
3264ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org
3265c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.orgvoid MacroAssembler::AssertNumber(Register object) {
3266c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  if (emit_debug_code()) {
3267c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org    Label ok;
3268c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org    Condition is_smi = CheckSmi(object);
3269c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org    j(is_smi, &ok, Label::kNear);
3270c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org    Cmp(FieldOperand(object, HeapObject::kMapOffset),
3271c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org        isolate()->factory()->heap_number_map());
3272594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    Check(equal, kOperandIsNotANumber);
3273c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org    bind(&ok);
3274c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  }
32755c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
32765c838251403b0be9a882540f1922577abba4c872ager@chromium.org
32775c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3278c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.orgvoid MacroAssembler::AssertNotSmi(Register object) {
3279c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  if (emit_debug_code()) {
3280c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org    Condition is_smi = CheckSmi(object);
3281594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    Check(NegateCondition(is_smi), kOperandIsASmi);
3282c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  }
3283ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org}
3284ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org
3285ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org
3286c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.orgvoid MacroAssembler::AssertSmi(Register object) {
3287c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  if (emit_debug_code()) {
3288c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org    Condition is_smi = CheckSmi(object);
3289594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    Check(is_smi, kOperandIsNotASmi);
3290c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  }
3291badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org}
3292badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org
3293badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org
3294c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.orgvoid MacroAssembler::AssertSmi(const Operand& object) {
3295c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  if (emit_debug_code()) {
3296c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org    Condition is_smi = CheckSmi(object);
3297594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    Check(is_smi, kOperandIsNotASmi);
3298c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  }
329925156ded31ef771a2d799ed902483d83b3ebcbdclrn@chromium.org}
330025156ded31ef771a2d799ed902483d83b3ebcbdclrn@chromium.org
330125156ded31ef771a2d799ed902483d83b3ebcbdclrn@chromium.org
3302c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.orgvoid MacroAssembler::AssertZeroExtended(Register int32_register) {
3303c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  if (emit_debug_code()) {
3304c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org    ASSERT(!int32_register.is(kScratchRegister));
3305e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    movq(kScratchRegister, V8_INT64_C(0x0000000100000000));
3306c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org    cmpq(kScratchRegister, int32_register);
3307594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    Check(above_equal, k32BitValueInRegisterIsNotZeroExtended);
3308c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  }
3309f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org}
3310f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
3311f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
3312c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.orgvoid MacroAssembler::AssertString(Register object) {
3313c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  if (emit_debug_code()) {
3314c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org    testb(object, Immediate(kSmiTagMask));
3315594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    Check(not_equal, kOperandIsASmiAndNotAString);
3316c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org    push(object);
3317c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org    movq(object, FieldOperand(object, HeapObject::kMapOffset));
3318c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org    CmpInstanceType(object, FIRST_NONSTRING_TYPE);
3319c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org    pop(object);
3320594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    Check(below, kOperandIsNotAString);
3321c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  }
332249edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org}
332349edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
332449edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
3325750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.orgvoid MacroAssembler::AssertName(Register object) {
3326750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  if (emit_debug_code()) {
3327750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    testb(object, Immediate(kSmiTagMask));
3328594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    Check(not_equal, kOperandIsASmiAndNotAName);
3329750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    push(object);
3330750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    movq(object, FieldOperand(object, HeapObject::kMapOffset));
3331750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    CmpInstanceType(object, LAST_NAME_TYPE);
3332750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    pop(object);
3333594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    Check(below_equal, kOperandIsNotAName);
3334750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  }
3335750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org}
3336750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org
3337750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org
3338c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.orgvoid MacroAssembler::AssertRootValue(Register src,
3339c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org                                     Heap::RootListIndex root_value_index,
3340594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org                                     BailoutReason reason) {
3341c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  if (emit_debug_code()) {
3342c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org    ASSERT(!src.is(kScratchRegister));
3343c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org    LoadRoot(kScratchRegister, root_value_index);
3344c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org    cmpq(src, kScratchRegister);
3345594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    Check(equal, reason);
3346c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  }
33475ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org}
33485ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org
33495ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org
33505ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org
3351b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgCondition MacroAssembler::IsObjectStringType(Register heap_object,
3352b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org                                             Register map,
3353b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org                                             Register instance_type) {
3354b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  movq(map, FieldOperand(heap_object, HeapObject::kMapOffset));
3355b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  movzxbl(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
335680c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  STATIC_ASSERT(kNotStringTag != 0);
3357b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  testb(instance_type, Immediate(kIsNotStringMask));
3358b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  return zero;
3359b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
3360b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
3361b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
3362750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.orgCondition MacroAssembler::IsObjectNameType(Register heap_object,
3363750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                           Register map,
3364750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                           Register instance_type) {
3365750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  movq(map, FieldOperand(heap_object, HeapObject::kMapOffset));
3366750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  movzxbl(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
3367750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  cmpb(instance_type, Immediate(static_cast<uint8_t>(LAST_NAME_TYPE)));
3368750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  return below_equal;
3369750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org}
3370750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org
3371750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org
337286f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.orgvoid MacroAssembler::TryGetFunctionPrototype(Register function,
337386f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org                                             Register result,
3374394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                             Label* miss,
3375394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                             bool miss_on_bound_function) {
337686f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  // Check that the receiver isn't a smi.
337786f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  testl(function, Immediate(kSmiTagMask));
337886f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  j(zero, miss);
337986f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org
338086f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  // Check that the function really is a function.
338186f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  CmpObjectType(function, JS_FUNCTION_TYPE, result);
338286f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  j(not_equal, miss);
338386f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org
3384394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  if (miss_on_bound_function) {
3385394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    movq(kScratchRegister,
3386394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com         FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
3387394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // It's not smi-tagged (stored in the top half of a smi-tagged 8-byte
3388394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // field).
3389394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    TestBit(FieldOperand(kScratchRegister,
3390394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                         SharedFunctionInfo::kCompilerHintsOffset),
3391394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com            SharedFunctionInfo::kBoundFunction);
3392394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    j(not_zero, miss);
3393394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  }
3394394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
339586f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  // Make sure that the function has an instance prototype.
339683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label non_instance;
339786f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  testb(FieldOperand(result, Map::kBitFieldOffset),
339886f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        Immediate(1 << Map::kHasNonInstancePrototype));
339983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  j(not_zero, &non_instance, Label::kNear);
340086f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org
340186f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  // Get the prototype or initial map from the function.
340286f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  movq(result,
340386f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org       FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
340486f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org
340586f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  // If the prototype or initial map is the hole, don't return it and
340686f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  // simply miss the cache instead. This will allow us to allocate a
340786f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  // prototype object on-demand in the runtime system.
340818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  CompareRoot(result, Heap::kTheHoleValueRootIndex);
340986f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  j(equal, miss);
341086f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org
341186f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  // If the function does not have an initial map, we're done.
341283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label done;
341386f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  CmpObjectType(result, MAP_TYPE, kScratchRegister);
341483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  j(not_equal, &done, Label::kNear);
341586f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org
341686f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  // Get the prototype from the initial map.
341786f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  movq(result, FieldOperand(result, Map::kPrototypeOffset));
341883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  jmp(&done, Label::kNear);
341986f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org
342086f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  // Non-instance prototype: Fetch prototype from constructor field
342186f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  // in initial map.
342286f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  bind(&non_instance);
342386f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  movq(result, FieldOperand(result, Map::kConstructorOffset));
342486f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org
342586f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  // All done.
342686f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  bind(&done);
342786f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org}
342886f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org
3429eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
3430eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.orgvoid MacroAssembler::SetCounter(StatsCounter* counter, int value) {
3431eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  if (FLAG_native_code_counters && counter->Enabled()) {
3432ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    Operand counter_operand = ExternalOperand(ExternalReference(counter));
3433a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org    movl(counter_operand, Immediate(value));
3434eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  }
3435eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org}
3436eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
3437eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
3438eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.orgvoid MacroAssembler::IncrementCounter(StatsCounter* counter, int value) {
3439eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  ASSERT(value > 0);
3440eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  if (FLAG_native_code_counters && counter->Enabled()) {
3441ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    Operand counter_operand = ExternalOperand(ExternalReference(counter));
3442eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    if (value == 1) {
3443ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      incl(counter_operand);
3444eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    } else {
3445ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      addl(counter_operand, Immediate(value));
3446eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    }
3447eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  }
3448eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org}
3449eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
3450eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
3451eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.orgvoid MacroAssembler::DecrementCounter(StatsCounter* counter, int value) {
3452eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  ASSERT(value > 0);
3453eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  if (FLAG_native_code_counters && counter->Enabled()) {
3454ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    Operand counter_operand = ExternalOperand(ExternalReference(counter));
3455eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    if (value == 1) {
3456ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      decl(counter_operand);
3457eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    } else {
3458ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      subl(counter_operand, Immediate(value));
3459eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    }
3460eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  }
3461eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org}
3462eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
3463eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
3464d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org#ifdef ENABLE_DEBUGGER_SUPPORT
34655c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid MacroAssembler::DebugBreak() {
34665d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  Set(rax, 0);  // No arguments.
3467ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  LoadAddress(rbx, ExternalReference(Runtime::kDebugBreak, isolate()));
34685c838251403b0be9a882540f1922577abba4c872ager@chromium.org  CEntryStub ces(1);
3469c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(AllowThisStubCall(&ces));
34708432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  Call(ces.GetCode(isolate()), RelocInfo::DEBUG_BREAK);
34713e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org}
34725c838251403b0be9a882540f1922577abba4c872ager@chromium.org#endif  // ENABLE_DEBUGGER_SUPPORT
34733e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org
34743e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org
347540cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.orgvoid MacroAssembler::SetCallKind(Register dst, CallKind call_kind) {
347640cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  // This macro takes the dst register to make the code more readable
347740cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  // at the call sites. However, the dst register has to be rcx to
347840cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  // follow the calling convention which requires the call type to be
347940cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  // in rcx.
348040cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  ASSERT(dst.is(rcx));
348140cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  if (call_kind == CALL_AS_FUNCTION) {
348240cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org    LoadSmiConstant(dst, Smi::FromInt(1));
348340cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  } else {
348440cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org    LoadSmiConstant(dst, Smi::FromInt(0));
348540cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  }
348640cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org}
348740cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org
348840cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org
3489eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.orgvoid MacroAssembler::InvokeCode(Register code,
3490eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org                                const ParameterCount& expected,
3491eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org                                const ParameterCount& actual,
34923a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                                InvokeFlag flag,
349340cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org                                const CallWrapper& call_wrapper,
349440cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org                                CallKind call_kind) {
3495c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // You can't call a function without a valid frame.
3496c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(flag == JUMP_FUNCTION || has_frame());
3497c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
349883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label done;
34992efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  bool definitely_mismatches = false;
35003a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  InvokePrologue(expected,
35013a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                 actual,
35023a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                 Handle<Code>::null(),
35033a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                 code,
35043a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                 &done,
35052efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org                 &definitely_mismatches,
35063a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                 flag,
350740cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org                 Label::kNear,
350883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                 call_wrapper,
350940cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org                 call_kind);
35102efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  if (!definitely_mismatches) {
35112efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org    if (flag == CALL_FUNCTION) {
35122efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org      call_wrapper.BeforeCall(CallSize(code));
35132efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org      SetCallKind(rcx, call_kind);
35142efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org      call(code);
35152efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org      call_wrapper.AfterCall();
35162efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org    } else {
35172efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org      ASSERT(flag == JUMP_FUNCTION);
35182efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org      SetCallKind(rcx, call_kind);
35192efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org      jmp(code);
35202efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org    }
35212efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org    bind(&done);
3522eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  }
3523eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org}
3524eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
3525eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
3526eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.orgvoid MacroAssembler::InvokeCode(Handle<Code> code,
3527eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org                                const ParameterCount& expected,
3528eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org                                const ParameterCount& actual,
3529eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org                                RelocInfo::Mode rmode,
35303a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                                InvokeFlag flag,
353140cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org                                const CallWrapper& call_wrapper,
353240cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org                                CallKind call_kind) {
3533c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // You can't call a function without a valid frame.
3534c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(flag == JUMP_FUNCTION || has_frame());
3535c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
353683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label done;
35372efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  bool definitely_mismatches = false;
3538eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  Register dummy = rax;
35393a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  InvokePrologue(expected,
35403a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                 actual,
35413a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                 code,
35423a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                 dummy,
35433a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                 &done,
35442efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org                 &definitely_mismatches,
35453a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                 flag,
354640cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org                 Label::kNear,
354783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                 call_wrapper,
354840cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org                 call_kind);
35492efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  if (!definitely_mismatches) {
35502efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org    if (flag == CALL_FUNCTION) {
35512efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org      call_wrapper.BeforeCall(CallSize(code));
35522efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org      SetCallKind(rcx, call_kind);
35532efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org      Call(code, rmode);
35542efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org      call_wrapper.AfterCall();
35552efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org    } else {
35562efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org      ASSERT(flag == JUMP_FUNCTION);
35572efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org      SetCallKind(rcx, call_kind);
35582efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org      Jump(code, rmode);
35592efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org    }
35602efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org    bind(&done);
3561eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  }
3562eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org}
3563eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
3564eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
3565eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.orgvoid MacroAssembler::InvokeFunction(Register function,
3566eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org                                    const ParameterCount& actual,
35673a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                                    InvokeFlag flag,
356840cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org                                    const CallWrapper& call_wrapper,
356940cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org                                    CallKind call_kind) {
3570c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // You can't call a function without a valid frame.
3571c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(flag == JUMP_FUNCTION || has_frame());
3572c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
3573eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  ASSERT(function.is(rdi));
3574eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  movq(rdx, FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
3575eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  movq(rsi, FieldOperand(function, JSFunction::kContextOffset));
35763e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  movsxlq(rbx,
35773e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org          FieldOperand(rdx, SharedFunctionInfo::kFormalParameterCountOffset));
35785aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  // Advances rdx to the end of the Code object header, to the start of
3579eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // the executable code.
3580145eff58d4f6ac0dcc53abb556dbf3cac6c3280aerik.corry@gmail.com  movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
3581eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
3582eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  ParameterCount expected(rbx);
358340cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  InvokeCode(rdx, expected, actual, flag, call_wrapper, call_kind);
3584eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org}
3585eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
3586eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
35878a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.orgvoid MacroAssembler::InvokeFunction(Register function,
358832d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org                                    const ParameterCount& expected,
35895c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                    const ParameterCount& actual,
35903a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                                    InvokeFlag flag,
3591d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org                                    const CallWrapper& call_wrapper,
3592d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org                                    CallKind call_kind) {
3593c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // You can't call a function without a valid frame.
3594c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(flag == JUMP_FUNCTION || has_frame());
3595c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
35968a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  ASSERT(function.is(rdi));
35978a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  movq(rsi, FieldOperand(function, JSFunction::kContextOffset));
35988a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  // Advances rdx to the end of the Code object header, to the start of
35998a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  // the executable code.
3600394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
36018a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org
3602394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  InvokeCode(rdx, expected, actual, flag, call_wrapper, call_kind);
36035c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
36045c838251403b0be9a882540f1922577abba4c872ager@chromium.org
36055c838251403b0be9a882540f1922577abba4c872ager@chromium.org
36068a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.orgvoid MacroAssembler::InvokeFunction(Handle<JSFunction> function,
36078a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org                                    const ParameterCount& expected,
36088a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org                                    const ParameterCount& actual,
36098a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org                                    InvokeFlag flag,
36108a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org                                    const CallWrapper& call_wrapper,
36118a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org                                    CallKind call_kind) {
36128a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  Move(rdi, function);
36138a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  InvokeFunction(rdi, expected, actual, flag, call_wrapper, call_kind);
36148a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org}
36158a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org
36168a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org
361783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgvoid MacroAssembler::InvokePrologue(const ParameterCount& expected,
361883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                    const ParameterCount& actual,
361983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                    Handle<Code> code_constant,
362083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                    Register code_register,
362183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                    Label* done,
36222efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org                                    bool* definitely_mismatches,
362383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                    InvokeFlag flag,
362440cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org                                    Label::Distance near_jump,
362583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                    const CallWrapper& call_wrapper,
362640cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org                                    CallKind call_kind) {
362783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  bool definitely_matches = false;
36282efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  *definitely_mismatches = false;
362983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label invoke;
363083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  if (expected.is_immediate()) {
363183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    ASSERT(actual.is_immediate());
363283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    if (expected.immediate() == actual.immediate()) {
363383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      definitely_matches = true;
363483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    } else {
363583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      Set(rax, actual.immediate());
363683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      if (expected.immediate() ==
363783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org              SharedFunctionInfo::kDontAdaptArgumentsSentinel) {
363883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org        // Don't worry about adapting arguments for built-ins that
363983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org        // don't want that done. Skip adaption code by making it look
364083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org        // like we have a match between expected and actual number of
364183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org        // arguments.
364283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org        definitely_matches = true;
364383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      } else {
36442efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org        *definitely_mismatches = true;
364583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org        Set(rbx, expected.immediate());
364683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      }
364783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    }
364883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  } else {
364983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    if (actual.is_immediate()) {
365083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      // Expected is in register, actual is immediate. This is the
365183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      // case when we invoke function values without going through the
365283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      // IC mechanism.
365383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      cmpq(expected.reg(), Immediate(actual.immediate()));
365483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      j(equal, &invoke, Label::kNear);
365583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      ASSERT(expected.reg().is(rbx));
365683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      Set(rax, actual.immediate());
365783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    } else if (!expected.reg().is(actual.reg())) {
365883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      // Both expected and actual are in (different) registers. This
365983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      // is the case when we invoke functions using call and apply.
366083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      cmpq(expected.reg(), actual.reg());
366183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      j(equal, &invoke, Label::kNear);
366283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      ASSERT(actual.reg().is(rax));
366383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      ASSERT(expected.reg().is(rbx));
366483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    }
366583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  }
366683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
366783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  if (!definitely_matches) {
366883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Handle<Code> adaptor = isolate()->builtins()->ArgumentsAdaptorTrampoline();
366983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    if (!code_constant.is_null()) {
367083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      movq(rdx, code_constant, RelocInfo::EMBEDDED_OBJECT);
367183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      addq(rdx, Immediate(Code::kHeaderSize - kHeapObjectTag));
367283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    } else if (!code_register.is(rdx)) {
367383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      movq(rdx, code_register);
367483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    }
367583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
367683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    if (flag == CALL_FUNCTION) {
367783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      call_wrapper.BeforeCall(CallSize(adaptor));
367840cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org      SetCallKind(rcx, call_kind);
367983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      Call(adaptor, RelocInfo::CODE_TARGET);
368083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      call_wrapper.AfterCall();
36812efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org      if (!*definitely_mismatches) {
36822efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org        jmp(done, near_jump);
36832efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org      }
368483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    } else {
368540cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org      SetCallKind(rcx, call_kind);
368683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      Jump(adaptor, RelocInfo::CODE_TARGET);
368783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    }
368883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    bind(&invoke);
368983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  }
369083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
369183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
369283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
3693c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.orgvoid MacroAssembler::Prologue(PrologueFrameMode frame_mode) {
3694c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  if (frame_mode == BUILD_STUB_FRAME) {
3695c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org    push(rbp);  // Caller's frame pointer.
3696c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org    movq(rbp, rsp);
3697c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org    push(rsi);  // Callee's context.
3698c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org    Push(Smi::FromInt(StackFrame::STUB));
3699c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  } else {
3700c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org    PredictableCodeSizeScope predictible_code_size_scope(this,
3701c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org        kNoCodeAgeSequenceLength);
3702ed29eb2bdad388c1ce751d68bd4fe6f4f5a7cbc8machenbach@chromium.org    if (isolate()->IsCodePreAgingActive()) {
3703c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org        // Pre-age the code.
3704c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org      Call(isolate()->builtins()->MarkCodeAsExecutedOnce(),
3705c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org           RelocInfo::CODE_AGE_SEQUENCE);
3706c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org      Nop(kNoCodeAgeSequenceLength - Assembler::kShortCallInstructionLength);
3707c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org    } else {
3708c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org      push(rbp);  // Caller's frame pointer.
3709c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org      movq(rbp, rsp);
3710c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org      push(rsi);  // Callee's context.
3711c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org      push(rdi);  // Callee's JS function.
3712c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org    }
3713c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  }
3714c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org}
3715c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
3716c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
3717eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.orgvoid MacroAssembler::EnterFrame(StackFrame::Type type) {
3718eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  push(rbp);
3719eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  movq(rbp, rsp);
3720eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  push(rsi);  // Context.
37219d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  Push(Smi::FromInt(type));
3722eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT);
3723eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  push(kScratchRegister);
3724badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  if (emit_debug_code()) {
3725eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    movq(kScratchRegister,
3726160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org         isolate()->factory()->undefined_value(),
3727eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org         RelocInfo::EMBEDDED_OBJECT);
3728eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    cmpq(Operand(rsp, 0), kScratchRegister);
3729594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    Check(not_equal, kCodeObjectNotProperlyPatched);
3730eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  }
3731eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org}
3732eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
3733eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
3734eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.orgvoid MacroAssembler::LeaveFrame(StackFrame::Type type) {
3735badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  if (emit_debug_code()) {
37369d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    Move(kScratchRegister, Smi::FromInt(type));
3737eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    cmpq(Operand(rbp, StandardFrameConstants::kMarkerOffset), kScratchRegister);
3738594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    Check(equal, kStackFrameTypesMustMatch);
3739eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  }
3740eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  movq(rsp, rbp);
3741eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  pop(rbp);
3742eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org}
3743eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
3744eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
3745d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.orgvoid MacroAssembler::EnterExitFramePrologue(bool save_rax) {
3746f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // Set up the frame structure on the stack.
374786f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  // All constants are relative to the frame pointer of the exit frame.
3748d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  ASSERT(ExitFrameConstants::kCallerSPDisplacement ==
3749d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org         kFPOnStackSize + kPCOnStackSize);
3750d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  ASSERT(ExitFrameConstants::kCallerPCOffset == kFPOnStackSize);
3751d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize);
3752eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  push(rbp);
3753eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  movq(rbp, rsp);
3754eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
3755d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  // Reserve room for entry stack pointer and push the code object.
37569d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize);
37575c838251403b0be9a882540f1922577abba4c872ager@chromium.org  push(Immediate(0));  // Saved entry sp, patched before call.
37585c838251403b0be9a882540f1922577abba4c872ager@chromium.org  movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT);
37595c838251403b0be9a882540f1922577abba4c872ager@chromium.org  push(kScratchRegister);  // Accessed from EditFrame::code_slot.
3760eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
3761eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // Save the frame pointer and the context in top.
3762e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org  if (save_rax) {
37634d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org    movq(r14, rax);  // Backup rax in callee-save register.
3764e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org  }
3765eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
376683e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org  Store(ExternalReference(Isolate::kCEntryFPAddress, isolate()), rbp);
376783e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org  Store(ExternalReference(Isolate::kContextAddress, isolate()), rsi);
3768e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org}
3769eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
37704a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com
37710ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.orgvoid MacroAssembler::EnterExitFrameEpilogue(int arg_stack_space,
37720ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org                                            bool save_doubles) {
3773a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org#ifdef _WIN64
37740ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  const int kShadowSpace = 4;
37750ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  arg_stack_space += kShadowSpace;
3776a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org#endif
37770ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  // Optionally save all XMM registers.
37780ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  if (save_doubles) {
3779c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org    int space = XMMRegister::kMaxNumAllocatableRegisters * kDoubleSize +
37800ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org        arg_stack_space * kPointerSize;
37810ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    subq(rsp, Immediate(space));
37820ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    int offset = -2 * kPointerSize;
3783a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    for (int i = 0; i < XMMRegister::NumAllocatableRegisters(); i++) {
37840ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org      XMMRegister reg = XMMRegister::FromAllocationIndex(i);
37850ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org      movsd(Operand(rbp, offset - ((i + 1) * kDoubleSize)), reg);
37860ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    }
37870ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  } else if (arg_stack_space > 0) {
37884a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com    subq(rsp, Immediate(arg_stack_space * kPointerSize));
37894a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  }
3790a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org
3791eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // Get the required frame alignment for the OS.
3792ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  const int kFrameAlignment = OS::ActivationFrameAlignment();
3793eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  if (kFrameAlignment > 0) {
3794eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    ASSERT(IsPowerOf2(kFrameAlignment));
3795a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org    ASSERT(is_int8(kFrameAlignment));
3796a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org    and_(rsp, Immediate(-kFrameAlignment));
3797eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  }
3798eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
3799eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // Patch the saved entry sp.
3800eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  movq(Operand(rbp, ExitFrameConstants::kSPOffset), rsp);
3801eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org}
3802eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
3803eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
38040ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.orgvoid MacroAssembler::EnterExitFrame(int arg_stack_space, bool save_doubles) {
3805d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  EnterExitFramePrologue(true);
3806e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org
3807f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // Set up argv in callee-saved register r15. It is reused in LeaveExitFrame,
3808e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org  // so it must be retained across the C-call.
3809e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org  int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
3810b08986cb66c3f6687247cb6da186c1e73057e399whesse@chromium.org  lea(r15, Operand(rbp, r14, times_pointer_size, offset));
3811e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org
38120ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  EnterExitFrameEpilogue(arg_stack_space, save_doubles);
3813e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org}
3814e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org
3815e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org
38164a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.comvoid MacroAssembler::EnterApiExitFrame(int arg_stack_space) {
3817d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  EnterExitFramePrologue(false);
38180ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  EnterExitFrameEpilogue(arg_stack_space, false);
3819e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org}
3820e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org
3821e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org
38220ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.orgvoid MacroAssembler::LeaveExitFrame(bool save_doubles) {
3823eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // Registers:
3824b08986cb66c3f6687247cb6da186c1e73057e399whesse@chromium.org  // r15 : argv
38250ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  if (save_doubles) {
38260ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    int offset = -2 * kPointerSize;
3827a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    for (int i = 0; i < XMMRegister::NumAllocatableRegisters(); i++) {
38280ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org      XMMRegister reg = XMMRegister::FromAllocationIndex(i);
38290ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org      movsd(reg, Operand(rbp, offset - ((i + 1) * kDoubleSize)));
38300ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    }
38310ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  }
3832eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // Get the return address from the stack and restore the frame pointer.
3833eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  movq(rcx, Operand(rbp, 1 * kPointerSize));
3834eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  movq(rbp, Operand(rbp, 0 * kPointerSize));
3835eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
38360ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  // Drop everything up to and including the arguments and the receiver
3837a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org  // from the caller stack.
3838b08986cb66c3f6687247cb6da186c1e73057e399whesse@chromium.org  lea(rsp, Operand(r15, 1 * kPointerSize));
3839eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
3840594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  PushReturnAddressFrom(rcx);
38414a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com
3842528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  LeaveExitFrameEpilogue(true);
38434a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com}
38444a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com
38454a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com
3846528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.orgvoid MacroAssembler::LeaveApiExitFrame(bool restore_context) {
38474a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  movq(rsp, rbp);
38484a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  pop(rbp);
38494a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com
3850528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  LeaveExitFrameEpilogue(restore_context);
38514a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com}
38524a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com
38534a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com
3854528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.orgvoid MacroAssembler::LeaveExitFrameEpilogue(bool restore_context) {
3855eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // Restore current context from top and clear it in debug mode.
385683e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org  ExternalReference context_address(Isolate::kContextAddress, isolate());
3857ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  Operand context_operand = ExternalOperand(context_address);
3858528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  if (restore_context) {
3859528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    movq(rsi, context_operand);
3860528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  }
3861eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org#ifdef DEBUG
3862ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  movq(context_operand, Immediate(0));
3863eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org#endif
3864eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
3865eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // Clear the top frame.
386683e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org  ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress,
3867ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org                                       isolate());
3868ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  Operand c_entry_fp_operand = ExternalOperand(c_entry_fp_address);
3869ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  movq(c_entry_fp_operand, Immediate(0));
3870eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org}
3871eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
3872eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
3873e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.orgvoid MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
3874e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org                                            Register scratch,
3875e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org                                            Label* miss) {
3876e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  Label same_contexts;
3877e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
3878e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  ASSERT(!holder_reg.is(scratch));
3879e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  ASSERT(!scratch.is(kScratchRegister));
3880e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  // Load current lexical context from the stack frame.
3881e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  movq(scratch, Operand(rbp, StandardFrameConstants::kContextOffset));
3882e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
3883e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  // When generating debug code, make sure the lexical context is set.
3884badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  if (emit_debug_code()) {
3885e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    cmpq(scratch, Immediate(0));
3886594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    Check(not_equal, kWeShouldNotHaveAnEmptyLexicalContext);
3887e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  }
388846839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  // Load the native context of the current context.
388946839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  int offset =
389046839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org      Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize;
3891e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  movq(scratch, FieldOperand(scratch, offset));
389246839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  movq(scratch, FieldOperand(scratch, GlobalObject::kNativeContextOffset));
3893e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
389446839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  // Check the context is a native context.
3895badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  if (emit_debug_code()) {
3896e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    Cmp(FieldOperand(scratch, HeapObject::kMapOffset),
389746839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org        isolate()->factory()->native_context_map());
3898594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext);
3899e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  }
3900e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
3901e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  // Check if both contexts are the same.
390246839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  cmpq(scratch, FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
3903e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  j(equal, &same_contexts);
3904e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
3905e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  // Compare security tokens.
3906e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  // Check that the security token in the calling global object is
3907e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  // compatible with the security token in the receiving global
3908e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  // object.
3909e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
391046839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  // Check the context is a native context.
3911badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  if (emit_debug_code()) {
3912e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    // Preserve original value of holder_reg.
3913e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    push(holder_reg);
391446839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org    movq(holder_reg,
391546839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org         FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
391618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    CompareRoot(holder_reg, Heap::kNullValueRootIndex);
3917594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    Check(not_equal, kJSGlobalProxyContextShouldNotBeNull);
3918e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
391946839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org    // Read the first word and compare to native_context_map(),
3920e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    movq(holder_reg, FieldOperand(holder_reg, HeapObject::kMapOffset));
392146839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org    CompareRoot(holder_reg, Heap::kNativeContextMapRootIndex);
3922594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext);
3923e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    pop(holder_reg);
3924e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  }
3925e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
3926e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  movq(kScratchRegister,
392746839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org       FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
39289d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  int token_offset =
39299d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com      Context::kHeaderSize + Context::SECURITY_TOKEN_INDEX * kPointerSize;
3930e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  movq(scratch, FieldOperand(scratch, token_offset));
3931e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  cmpq(scratch, FieldOperand(kScratchRegister, token_offset));
3932e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  j(not_equal, miss);
3933e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
3934e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  bind(&same_contexts);
3935e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org}
3936e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
3937e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
3938ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org// Compute the hash code from the untagged key.  This must be kept in sync with
3939ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org// ComputeIntegerHash in utils.h and KeyedLoadGenericElementStub in
3940ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org// code-stub-hydrogen.cc
3941f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.comvoid MacroAssembler::GetNumberHash(Register r0, Register scratch) {
3942f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // First of all we assign the hash seed to scratch.
3943f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  LoadRoot(scratch, Heap::kHashSeedRootIndex);
3944f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  SmiToInteger32(scratch, scratch);
3945f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com
3946f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // Xor original key with a seed.
3947f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  xorl(r0, scratch);
3948f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com
3949f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // Compute the hash code from the untagged key.  This must be kept in sync
3950f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // with ComputeIntegerHash in utils.h.
3951f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  //
3952f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // hash = ~hash + (hash << 15);
3953f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  movl(scratch, r0);
3954f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  notl(r0);
3955f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  shll(scratch, Immediate(15));
3956f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  addl(r0, scratch);
3957f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // hash = hash ^ (hash >> 12);
3958f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  movl(scratch, r0);
3959f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  shrl(scratch, Immediate(12));
3960f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  xorl(r0, scratch);
3961f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // hash = hash + (hash << 2);
3962f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  leal(r0, Operand(r0, r0, times_4, 0));
3963f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // hash = hash ^ (hash >> 4);
3964f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  movl(scratch, r0);
3965f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  shrl(scratch, Immediate(4));
3966f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  xorl(r0, scratch);
3967f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // hash = hash * 2057;
3968f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  imull(r0, r0, Immediate(2057));
3969f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // hash = hash ^ (hash >> 16);
3970f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  movl(scratch, r0);
3971f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  shrl(scratch, Immediate(16));
3972f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  xorl(r0, scratch);
3973f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com}
3974f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com
3975f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com
3976f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com
39776db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.orgvoid MacroAssembler::LoadFromNumberDictionary(Label* miss,
39786db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org                                              Register elements,
39796db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org                                              Register key,
39806db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org                                              Register r0,
39816db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org                                              Register r1,
39826db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org                                              Register r2,
39836db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org                                              Register result) {
39846db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // Register use:
39856db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //
39866db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // elements - holds the slow-case elements of the receiver on entry.
39876db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //            Unchanged unless 'result' is the same register.
39886db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //
39896db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // key      - holds the smi key on entry.
39906db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //            Unchanged unless 'result' is the same register.
39916db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //
39926db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // Scratch registers:
39936db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //
39946db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // r0 - holds the untagged key on entry and holds the hash once computed.
39956db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //
39966db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // r1 - used to hold the capacity mask of the dictionary
39976db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //
39986db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // r2 - used for the index into the dictionary.
39996db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //
40006db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // result - holds the result on exit if the load succeeded.
40016db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //          Allowed to be the same as 'key' or 'result'.
40026db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //          Unchanged on bailout so 'key' or 'result' can be used
40036db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //          in further computation.
40046db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
40056db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  Label done;
40066db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
4007f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  GetNumberHash(r0, r1);
40086db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
40096db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // Compute capacity mask.
4010f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  SmiToInteger32(r1, FieldOperand(elements,
4011f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com                                  SeededNumberDictionary::kCapacityOffset));
40126db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  decl(r1);
40136db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
40146db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // Generate an unrolled loop that performs a few probes before giving up.
4015ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org  for (int i = 0; i < kNumberDictionaryProbes; i++) {
40166db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org    // Use r2 for index calculations and keep the hash intact in r0.
40176db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org    movq(r2, r0);
40186db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org    // Compute the masked index: (hash + i + i * i) & mask.
40196db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org    if (i > 0) {
4020f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com      addl(r2, Immediate(SeededNumberDictionary::GetProbeOffset(i)));
40216db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org    }
40226db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org    and_(r2, r1);
40236db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
40246db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org    // Scale the index by multiplying by the entry size.
4025f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com    ASSERT(SeededNumberDictionary::kEntrySize == 3);
40266db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org    lea(r2, Operand(r2, r2, times_2, 0));  // r2 = r2 * 3
40276db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
40286db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org    // Check if the key matches.
40296db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org    cmpq(key, FieldOperand(elements,
40306db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org                           r2,
40316db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org                           times_pointer_size,
4032f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com                           SeededNumberDictionary::kElementsStartOffset));
4033ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org    if (i != (kNumberDictionaryProbes - 1)) {
40346db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org      j(equal, &done);
40356db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org    } else {
40366db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org      j(not_equal, miss);
40376db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org    }
40386db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  }
40396db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
40406db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  bind(&done);
40416db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // Check that the value is a normal propety.
40426db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  const int kDetailsOffset =
4043f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com      SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize;
40446db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  ASSERT_EQ(NORMAL, 0);
40456db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  Test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset),
404683e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org       Smi::FromInt(PropertyDetails::TypeField::kMask));
40476db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  j(not_zero, miss);
40486db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
40496db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // Get the value at the masked, scaled index.
40506db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  const int kValueOffset =
4051f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com      SeededNumberDictionary::kElementsStartOffset + kPointerSize;
40526db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  movq(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset));
40536db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org}
40546db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
40556db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
4056a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.orgvoid MacroAssembler::LoadAllocationTopHelper(Register result,
4057a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org                                             Register scratch,
4058a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org                                             AllocationFlags flags) {
40592bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  ExternalReference allocation_top =
40602bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org      AllocationUtils::GetAllocationTopReference(isolate(), flags);
406118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
406218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Just return if allocation top is already known.
4063a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org  if ((flags & RESULT_CONTAINS_TOP) != 0) {
406418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // No use of scratch if allocation top is provided.
4065ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org    ASSERT(!scratch.is_valid());
4066a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org#ifdef DEBUG
4067a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org    // Assert that result actually contains top on entry.
40682bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org    Operand top_operand = ExternalOperand(allocation_top);
4069ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    cmpq(result, top_operand);
4070594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    Check(equal, kUnexpectedAllocationTop);
4071a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org#endif
407218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    return;
407318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  }
407418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
4075ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  // Move address of new object to result. Use scratch register if available,
4076ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  // and keep address in scratch until call to UpdateAllocationTopHelper.
4077ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  if (scratch.is_valid()) {
40782bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org    LoadAddress(scratch, allocation_top);
407918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    movq(result, Operand(scratch, 0));
4080ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  } else {
40812bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org    Load(result, allocation_top);
408218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  }
408318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
408418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
408518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
408618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid MacroAssembler::UpdateAllocationTopHelper(Register result_end,
40872bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org                                               Register scratch,
40882bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org                                               AllocationFlags flags) {
4089badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  if (emit_debug_code()) {
4090ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org    testq(result_end, Immediate(kObjectAlignmentMask));
4091594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    Check(zero, kUnalignedAllocationInNewSpace);
4092ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org  }
4093ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org
40942bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  ExternalReference allocation_top =
40952bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org      AllocationUtils::GetAllocationTopReference(isolate(), flags);
409618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
409718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Update new top.
4098ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  if (scratch.is_valid()) {
4099ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    // Scratch already contains address of allocation top.
4100ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    movq(Operand(scratch, 0), result_end);
410118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  } else {
41022bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org    Store(allocation_top, result_end);
410318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  }
410418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
410518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
410618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
41072bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.orgvoid MacroAssembler::Allocate(int object_size,
41082bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org                              Register result,
41092bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org                              Register result_end,
41102bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org                              Register scratch,
41112bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org                              Label* gc_required,
41122bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org                              AllocationFlags flags) {
41134cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org  ASSERT((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0);
4114c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org  ASSERT(object_size <= Page::kMaxNonCodeHeapObjectSize);
4115b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  if (!FLAG_inline_new) {
4116badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org    if (emit_debug_code()) {
4117303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org      // Trash the registers to simulate an allocation failure.
4118303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org      movl(result, Immediate(0x7091));
4119303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org      if (result_end.is_valid()) {
4120303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org        movl(result_end, Immediate(0x7191));
4121303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org      }
4122303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org      if (scratch.is_valid()) {
4123303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org        movl(scratch, Immediate(0x7291));
4124303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org      }
4125303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org    }
4126303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org    jmp(gc_required);
4127303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org    return;
4128303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  }
412918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  ASSERT(!result.is(result_end));
413018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
413118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Load address of new object into result.
4132beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  LoadAllocationTopHelper(result, scratch, flags);
413318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
41344cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org  // Align the next allocation. Storing the filler map without checking top is
4135f6fe1183c2663bdae2b8e265d4ec3d9e925568e7mstarzinger@chromium.org  // safe in new-space because the limit of the heap is aligned there.
41364cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org  if (((flags & DOUBLE_ALIGNMENT) != 0) && FLAG_debug_code) {
41374cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org    testq(result, Immediate(kDoubleAlignmentMask));
4138594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    Check(zero, kAllocationIsNotDoubleAligned);
41394cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org  }
41404cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org
414118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Calculate new top and bail out if new space is exhausted.
41422bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  ExternalReference allocation_limit =
41432bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org      AllocationUtils::GetAllocationLimitReference(isolate(), flags);
4144ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org
4145ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  Register top_reg = result_end.is_valid() ? result_end : result;
4146ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org
4147d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  if (!top_reg.is(result)) {
4148d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com    movq(top_reg, result);
4149ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  }
4150d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  addq(top_reg, Immediate(object_size));
4151d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  j(carry, gc_required);
41522bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  Operand limit_operand = ExternalOperand(allocation_limit);
4153ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  cmpq(top_reg, limit_operand);
415418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  j(above, gc_required);
415518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
415618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Update allocation top.
41572bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  UpdateAllocationTopHelper(top_reg, scratch, flags);
4158a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org
41594cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org  bool tag_result = (flags & TAG_OBJECT) != 0;
4160ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  if (top_reg.is(result)) {
41614cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org    if (tag_result) {
4162ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org      subq(result, Immediate(object_size - kHeapObjectTag));
4163ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org    } else {
4164ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org      subq(result, Immediate(object_size));
4165ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org    }
41664cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org  } else if (tag_result) {
4167ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org    // Tag the result if requested.
41684cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org    ASSERT(kHeapObjectTag == 1);
41694cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org    incq(result);
4170a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org  }
417118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
417218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
417318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
4174f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.orgvoid MacroAssembler::Allocate(int header_size,
4175f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                              ScaleFactor element_size,
4176f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                              Register element_count,
4177f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                              Register result,
4178f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                              Register result_end,
4179f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                              Register scratch,
4180f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                              Label* gc_required,
4181f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                              AllocationFlags flags) {
41824cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org  ASSERT((flags & SIZE_IN_WORDS) == 0);
4183d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  lea(result_end, Operand(element_count, element_size, header_size));
4184e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  Allocate(result_end, result, result_end, scratch, gc_required, flags);
4185a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org}
418618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
418718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
4188f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.orgvoid MacroAssembler::Allocate(Register object_size,
4189f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                              Register result,
4190f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                              Register result_end,
4191f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                              Register scratch,
4192f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                              Label* gc_required,
4193f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                              AllocationFlags flags) {
4194e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  ASSERT((flags & SIZE_IN_WORDS) == 0);
4195b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  if (!FLAG_inline_new) {
4196badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org    if (emit_debug_code()) {
4197303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org      // Trash the registers to simulate an allocation failure.
4198303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org      movl(result, Immediate(0x7091));
4199303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org      movl(result_end, Immediate(0x7191));
4200303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org      if (scratch.is_valid()) {
4201303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org        movl(scratch, Immediate(0x7291));
4202303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org      }
4203303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org      // object_size is left unchanged by this function.
4204303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org    }
4205303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org    jmp(gc_required);
4206303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org    return;
4207303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  }
4208303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  ASSERT(!result.is(result_end));
4209303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org
421018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Load address of new object into result.
4211beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  LoadAllocationTopHelper(result, scratch, flags);
421218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
4213e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  // Align the next allocation. Storing the filler map without checking top is
4214f6fe1183c2663bdae2b8e265d4ec3d9e925568e7mstarzinger@chromium.org  // safe in new-space because the limit of the heap is aligned there.
4215e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  if (((flags & DOUBLE_ALIGNMENT) != 0) && FLAG_debug_code) {
4216e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org    testq(result, Immediate(kDoubleAlignmentMask));
4217594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    Check(zero, kAllocationIsNotDoubleAligned);
4218e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  }
4219e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
422018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Calculate new top and bail out if new space is exhausted.
4221f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  ExternalReference allocation_limit =
4222f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      AllocationUtils::GetAllocationLimitReference(isolate(), flags);
422318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  if (!object_size.is(result_end)) {
422418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    movq(result_end, object_size);
422518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  }
422618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  addq(result_end, result);
4227d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  j(carry, gc_required);
4228f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  Operand limit_operand = ExternalOperand(allocation_limit);
4229ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  cmpq(result_end, limit_operand);
423018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  j(above, gc_required);
423118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
423218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Update allocation top.
42332bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  UpdateAllocationTopHelper(result_end, scratch, flags);
4234a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org
4235a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org  // Tag the result if requested.
4236a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org  if ((flags & TAG_OBJECT) != 0) {
4237a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org    addq(result, Immediate(kHeapObjectTag));
4238a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org  }
423918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
424018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
424118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
424218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid MacroAssembler::UndoAllocationInNewSpace(Register object) {
424318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  ExternalReference new_space_allocation_top =
4244ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      ExternalReference::new_space_allocation_top_address(isolate());
424518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
424618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Make sure the object has no tag before resetting top.
424718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  and_(object, Immediate(~kHeapObjectTagMask));
4248ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  Operand top_operand = ExternalOperand(new_space_allocation_top);
424918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org#ifdef DEBUG
4250ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  cmpq(object, top_operand);
4251594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  Check(below, kUndoAllocationOfNonAllocatedMemory);
425218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org#endif
4253ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  movq(top_operand, object);
425418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
425518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
425618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
42573811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.orgvoid MacroAssembler::AllocateHeapNumber(Register result,
42583811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org                                        Register scratch,
42593811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org                                        Label* gc_required) {
42603811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  // Allocate heap number in new space.
42612bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  Allocate(HeapNumber::kSize, result, scratch, no_reg, gc_required, TAG_OBJECT);
42623811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
42633811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  // Set the map.
42643811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  LoadRoot(kScratchRegister, Heap::kHeapNumberMapRootIndex);
42653811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
42663811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org}
42673811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
42683811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
426913bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.orgvoid MacroAssembler::AllocateTwoByteString(Register result,
427013bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                                           Register length,
427113bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                                           Register scratch1,
427213bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                                           Register scratch2,
427313bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                                           Register scratch3,
427413bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                                           Label* gc_required) {
427513bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  // Calculate the number of bytes needed for the characters in the string while
427613bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  // observing object alignment.
4277ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  const int kHeaderAlignment = SeqTwoByteString::kHeaderSize &
4278ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org                               kObjectAlignmentMask;
427913bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  ASSERT(kShortSize == 2);
428013bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  // scratch1 = length * 2 + kObjectAlignmentMask.
4281ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  lea(scratch1, Operand(length, length, times_1, kObjectAlignmentMask +
4282ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org                kHeaderAlignment));
428313bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  and_(scratch1, Immediate(~kObjectAlignmentMask));
4284ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  if (kHeaderAlignment > 0) {
4285ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org    subq(scratch1, Immediate(kHeaderAlignment));
4286ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  }
428713bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org
428813bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  // Allocate two byte string in new space.
4289f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  Allocate(SeqTwoByteString::kHeaderSize,
4290f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org           times_1,
4291f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org           scratch1,
4292f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org           result,
4293f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org           scratch2,
4294f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org           scratch3,
4295f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org           gc_required,
4296f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org           TAG_OBJECT);
429713bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org
429813bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  // Set the map, length and hash field.
429913bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  LoadRoot(kScratchRegister, Heap::kStringMapRootIndex);
430013bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
4301ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  Integer32ToSmi(scratch1, length);
4302ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  movq(FieldOperand(result, String::kLengthOffset), scratch1);
430330ce411529579186181838984710b0b0980857aaricow@chromium.org  movq(FieldOperand(result, String::kHashFieldOffset),
430413bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org       Immediate(String::kEmptyHashField));
430513bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org}
430613bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org
430713bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org
430813bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.orgvoid MacroAssembler::AllocateAsciiString(Register result,
430913bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                                         Register length,
431013bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                                         Register scratch1,
431113bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                                         Register scratch2,
431213bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                                         Register scratch3,
431313bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                                         Label* gc_required) {
431413bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  // Calculate the number of bytes needed for the characters in the string while
431513bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  // observing object alignment.
4316fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  const int kHeaderAlignment = SeqOneByteString::kHeaderSize &
4317ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org                               kObjectAlignmentMask;
431813bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  movl(scratch1, length);
431913bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  ASSERT(kCharSize == 1);
4320ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  addq(scratch1, Immediate(kObjectAlignmentMask + kHeaderAlignment));
432113bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  and_(scratch1, Immediate(~kObjectAlignmentMask));
4322ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  if (kHeaderAlignment > 0) {
4323ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org    subq(scratch1, Immediate(kHeaderAlignment));
4324ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  }
432513bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org
43262efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  // Allocate ASCII string in new space.
4327f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  Allocate(SeqOneByteString::kHeaderSize,
4328f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org           times_1,
4329f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org           scratch1,
4330f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org           result,
4331f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org           scratch2,
4332f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org           scratch3,
4333f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org           gc_required,
4334f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org           TAG_OBJECT);
433513bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org
433613bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  // Set the map, length and hash field.
433713bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  LoadRoot(kScratchRegister, Heap::kAsciiStringMapRootIndex);
433813bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
4339ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  Integer32ToSmi(scratch1, length);
4340ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  movq(FieldOperand(result, String::kLengthOffset), scratch1);
434130ce411529579186181838984710b0b0980857aaricow@chromium.org  movq(FieldOperand(result, String::kHashFieldOffset),
434213bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org       Immediate(String::kEmptyHashField));
434313bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org}
434413bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org
434513bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org
43461805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.orgvoid MacroAssembler::AllocateTwoByteConsString(Register result,
434713bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                                        Register scratch1,
434813bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                                        Register scratch2,
434913bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                                        Label* gc_required) {
435013bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  // Allocate heap number in new space.
43512bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
43522bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org           TAG_OBJECT);
435313bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org
435413bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  // Set the map. The other fields are left uninitialized.
435513bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  LoadRoot(kScratchRegister, Heap::kConsStringMapRootIndex);
435613bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
435713bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org}
435813bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org
435913bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org
436013bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.orgvoid MacroAssembler::AllocateAsciiConsString(Register result,
436113bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                                             Register scratch1,
436213bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                                             Register scratch2,
436313bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                                             Label* gc_required) {
436457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  Label allocate_new_space, install_map;
436557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  AllocationFlags flags = TAG_OBJECT;
436657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
436757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  ExternalReference high_promotion_mode = ExternalReference::
436857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      new_space_high_promotion_mode_active_address(isolate());
436957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
437057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  Load(scratch1, high_promotion_mode);
437157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  testb(scratch1, Immediate(1));
437257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  j(zero, &allocate_new_space);
437357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  Allocate(ConsString::kSize,
437457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org           result,
437557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org           scratch1,
437657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org           scratch2,
437757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org           gc_required,
437857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org           static_cast<AllocationFlags>(flags | PRETENURE_OLD_POINTER_SPACE));
437957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
438057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  jmp(&install_map);
438157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
438257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  bind(&allocate_new_space);
438357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  Allocate(ConsString::kSize,
438457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org           result,
438557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org           scratch1,
438657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org           scratch2,
438757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org           gc_required,
438857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org           flags);
438957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
439057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  bind(&install_map);
439113bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org
439213bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  // Set the map. The other fields are left uninitialized.
439313bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  LoadRoot(kScratchRegister, Heap::kConsAsciiStringMapRootIndex);
439413bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
439513bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org}
439613bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org
439713bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org
43981805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.orgvoid MacroAssembler::AllocateTwoByteSlicedString(Register result,
43991805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org                                          Register scratch1,
44001805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org                                          Register scratch2,
44011805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org                                          Label* gc_required) {
44021805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  // Allocate heap number in new space.
44032bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
44042bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org           TAG_OBJECT);
44051805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
44061805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  // Set the map. The other fields are left uninitialized.
44071805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  LoadRoot(kScratchRegister, Heap::kSlicedStringMapRootIndex);
44081805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
44091805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org}
44101805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
44111805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
44121805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.orgvoid MacroAssembler::AllocateAsciiSlicedString(Register result,
44131805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org                                               Register scratch1,
44141805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org                                               Register scratch2,
44151805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org                                               Label* gc_required) {
44161805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  // Allocate heap number in new space.
44172bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
44182bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org           TAG_OBJECT);
44191805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
44201805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  // Set the map. The other fields are left uninitialized.
44211805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  LoadRoot(kScratchRegister, Heap::kSlicedAsciiStringMapRootIndex);
44221805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
44231805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org}
44241805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
44251805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
44267979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org// Copy memory, byte-by-byte, from source to destination.  Not optimized for
44277979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org// long or aligned copies.  The contents of scratch and length are destroyed.
44287979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org// Destination is incremented by length, source, length and scratch are
44297979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org// clobbered.
44307979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org// A simpler loop is faster on small copies, but slower on large ones.
44317979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org// The cld() instruction must have been emitted, to set the direction flag(),
44327979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org// before calling this function.
44337979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.orgvoid MacroAssembler::CopyBytes(Register destination,
44347979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org                               Register source,
44357979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org                               Register length,
44367979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org                               int min_length,
44377979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org                               Register scratch) {
44387979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  ASSERT(min_length >= 0);
4439000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.org  if (emit_debug_code()) {
44407979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    cmpl(length, Immediate(min_length));
4441594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    Assert(greater_equal, kInvalidMinLength);
44427979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  }
44430cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org  Label short_loop, len8, len16, len24, done, short_string;
44447979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
44450cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org  const int kLongStringLimit = 4 * kPointerSize;
44467979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  if (min_length <= kLongStringLimit) {
44470cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    cmpl(length, Immediate(kPointerSize));
44480cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    j(below, &short_string, Label::kNear);
44497979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  }
44507979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
44517979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  ASSERT(source.is(rsi));
44527979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  ASSERT(destination.is(rdi));
44537979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  ASSERT(length.is(rcx));
44547979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
44550cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org  if (min_length <= kLongStringLimit) {
44560cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    cmpl(length, Immediate(2 * kPointerSize));
44570cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    j(below_equal, &len8, Label::kNear);
44580cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    cmpl(length, Immediate(3 * kPointerSize));
44590cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    j(below_equal, &len16, Label::kNear);
44600cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    cmpl(length, Immediate(4 * kPointerSize));
44610cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    j(below_equal, &len24, Label::kNear);
44620cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org  }
44630cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org
44647979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Because source is 8-byte aligned in our uses of this function,
44657979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // we keep source aligned for the rep movs operation by copying the odd bytes
44667979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // at the end of the ranges.
44677979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  movq(scratch, length);
446893a47f4837f2137c8d8349250fd8e91da3108126jkummerow@chromium.org  shrl(length, Immediate(kPointerSizeLog2));
44697979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  repmovsq();
44707979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Move remaining bytes of length.
447193a47f4837f2137c8d8349250fd8e91da3108126jkummerow@chromium.org  andl(scratch, Immediate(kPointerSize - 1));
447293a47f4837f2137c8d8349250fd8e91da3108126jkummerow@chromium.org  movq(length, Operand(source, scratch, times_1, -kPointerSize));
447393a47f4837f2137c8d8349250fd8e91da3108126jkummerow@chromium.org  movq(Operand(destination, scratch, times_1, -kPointerSize), length);
44747979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  addq(destination, scratch);
44757979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
44767979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  if (min_length <= kLongStringLimit) {
44770cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    jmp(&done, Label::kNear);
44780cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    bind(&len24);
44790cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    movq(scratch, Operand(source, 2 * kPointerSize));
44800cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    movq(Operand(destination, 2 * kPointerSize), scratch);
44810cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    bind(&len16);
44820cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    movq(scratch, Operand(source, kPointerSize));
44830cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    movq(Operand(destination, kPointerSize), scratch);
44840cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    bind(&len8);
44850cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    movq(scratch, Operand(source, 0));
44860cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    movq(Operand(destination, 0), scratch);
44870cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    // Move remaining bytes of length.
44880cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    movq(scratch, Operand(source, length, times_1, -kPointerSize));
44890cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    movq(Operand(destination, length, times_1, -kPointerSize), scratch);
44900cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    addq(destination, length);
44910cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    jmp(&done, Label::kNear);
44927979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
44937979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    bind(&short_string);
44947979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    if (min_length == 0) {
44957979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org      testl(length, length);
44960cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org      j(zero, &done, Label::kNear);
44977979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    }
44987979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
44997979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    bind(&short_loop);
45000cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    movb(scratch, Operand(source, 0));
45010cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    movb(Operand(destination, 0), scratch);
45027979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    incq(source);
45037979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    incq(destination);
45040cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    decl(length);
45050cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    j(not_zero, &short_loop);
45067979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  }
45070cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org
45080cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org  bind(&done);
45097979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org}
45107979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
45117979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
4512c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid MacroAssembler::InitializeFieldsWithFiller(Register start_offset,
4513c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                                Register end_offset,
4514c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                                Register filler) {
4515c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Label loop, entry;
4516c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  jmp(&entry);
4517c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  bind(&loop);
4518c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  movq(Operand(start_offset, 0), filler);
4519c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  addq(start_offset, Immediate(kPointerSize));
4520c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  bind(&entry);
4521c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  cmpq(start_offset, end_offset);
4522c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  j(less, &loop);
4523c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
4524c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
4525c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
4526ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.orgvoid MacroAssembler::LoadContext(Register dst, int context_chain_length) {
4527ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org  if (context_chain_length > 0) {
4528ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org    // Move up the chain of contexts to the context containing the slot.
45296d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org    movq(dst, Operand(rsi, Context::SlotOffset(Context::PREVIOUS_INDEX)));
4530ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org    for (int i = 1; i < context_chain_length; i++) {
45316d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org      movq(dst, Operand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX)));
4532ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org    }
45335d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  } else {
45345d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org    // Slot is in the current function context.  Move it into the
45355d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org    // destination register in case we store into it (the write barrier
45365d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org    // cannot be allowed to destroy the context in rsi).
45375d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org    movq(dst, rsi);
45385d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  }
45395d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org
45404f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  // We should not have found a with context by walking the context
45414f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  // chain (i.e., the static scope chain and runtime context chain do
45424f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  // not agree).  A variable occurring in such a scope should have
45434f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  // slot type LOOKUP and not CONTEXT.
4544badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  if (emit_debug_code()) {
45453cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    CompareRoot(FieldOperand(dst, HeapObject::kMapOffset),
45463cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org                Heap::kWithContextMapRootIndex);
4547594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    Check(not_equal, kVariableResolvedToWithContext);
4548ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org  }
4549ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org}
4550ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org
4551fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org
45521145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.orgvoid MacroAssembler::LoadTransitionedArrayMapConditional(
45531145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org    ElementsKind expected_kind,
45541145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org    ElementsKind transitioned_kind,
45551145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org    Register map_in_out,
45561145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org    Register scratch,
45571145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org    Label* no_map_match) {
45581145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org  // Load the global or builtins object from the current context.
455946839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  movq(scratch,
456046839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org       Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
456146839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  movq(scratch, FieldOperand(scratch, GlobalObject::kNativeContextOffset));
45621145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org
45631145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org  // Check that the function's map is the same as the expected cached map.
4564830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org  movq(scratch, Operand(scratch,
4565830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org                        Context::SlotOffset(Context::JS_ARRAY_MAPS_INDEX)));
4566830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org
4567830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org  int offset = expected_kind * kPointerSize +
4568830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org      FixedArrayBase::kHeaderSize;
4569830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org  cmpq(map_in_out, FieldOperand(scratch, offset));
45701145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org  j(not_equal, no_map_match);
45711145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org
45721145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org  // Use the transitioned cached map.
4573830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org  offset = transitioned_kind * kPointerSize +
4574830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org      FixedArrayBase::kHeaderSize;
4575830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org  movq(map_in_out, FieldOperand(scratch, offset));
45761145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org}
45771145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org
45781145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org
45791145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.orgvoid MacroAssembler::LoadInitialArrayMap(
4580830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org    Register function_in, Register scratch,
4581830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org    Register map_out, bool can_have_holes) {
4582fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  ASSERT(!function_in.is(map_out));
4583fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  Label done;
4584fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  movq(map_out, FieldOperand(function_in,
4585fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org                             JSFunction::kPrototypeOrInitialMapOffset));
4586fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  if (!FLAG_smi_only_arrays) {
4587830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org    ElementsKind kind = can_have_holes ? FAST_HOLEY_ELEMENTS : FAST_ELEMENTS;
4588830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org    LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
4589830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org                                        kind,
4590830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org                                        map_out,
4591830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org                                        scratch,
4592830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org                                        &done);
4593830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org  } else if (can_have_holes) {
4594830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org    LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
4595830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org                                        FAST_HOLEY_SMI_ELEMENTS,
45961145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org                                        map_out,
45971145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org                                        scratch,
45981145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org                                        &done);
4599fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  }
4600fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  bind(&done);
4601fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org}
4602fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org
4603ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#ifdef _WIN64
4604ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgstatic const int kRegisterPassedArguments = 4;
4605ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#else
4606ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgstatic const int kRegisterPassedArguments = 6;
4607ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#endif
460830ce411529579186181838984710b0b0980857aaricow@chromium.org
46095f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.orgvoid MacroAssembler::LoadGlobalFunction(int index, Register function) {
46105f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  // Load the global or builtins object from the current context.
461146839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  movq(function,
461246839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org       Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
461346839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  // Load the native context from the global or builtins object.
461446839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  movq(function, FieldOperand(function, GlobalObject::kNativeContextOffset));
461546839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  // Load the function from the native context.
46165f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  movq(function, Operand(function, Context::SlotOffset(index)));
46175f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org}
46185f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org
46195f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org
46204a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.orgvoid MacroAssembler::LoadArrayFunction(Register function) {
46214a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  movq(function,
46224a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org       Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
46234a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  movq(function, FieldOperand(function, GlobalObject::kGlobalContextOffset));
46244a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  movq(function,
46254a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org       Operand(function, Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX)));
46264a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org}
46274a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
46284a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
46295f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.orgvoid MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
46305f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org                                                  Register map) {
46315f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  // Load the initial map.  The global functions all have initial maps.
46325f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  movq(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
4633badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  if (emit_debug_code()) {
46345f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org    Label ok, fail;
4635c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    CheckMap(map, isolate()->factory()->meta_map(), &fail, DO_SMI_CHECK);
46365f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org    jmp(&ok);
46375f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org    bind(&fail);
4638594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    Abort(kGlobalFunctionsMustHaveInitialMap);
46395f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org    bind(&ok);
46405f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  }
46415f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org}
46425f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org
46435f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org
4644b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgint MacroAssembler::ArgumentStackSlotsForCFunctionCall(int num_arguments) {
464530ce411529579186181838984710b0b0980857aaricow@chromium.org  // On Windows 64 stack slots are reserved by the caller for all arguments
464630ce411529579186181838984710b0b0980857aaricow@chromium.org  // including the ones passed in registers, and space is always allocated for
464730ce411529579186181838984710b0b0980857aaricow@chromium.org  // the four register arguments even if the function takes fewer than four
464830ce411529579186181838984710b0b0980857aaricow@chromium.org  // arguments.
464930ce411529579186181838984710b0b0980857aaricow@chromium.org  // On AMD64 ABI (Linux/Mac) the first six arguments are passed in registers
465030ce411529579186181838984710b0b0980857aaricow@chromium.org  // and the caller does not reserve stack slots for them.
4651b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  ASSERT(num_arguments >= 0);
4652b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org#ifdef _WIN64
4653ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  const int kMinimumStackSlots = kRegisterPassedArguments;
465430ce411529579186181838984710b0b0980857aaricow@chromium.org  if (num_arguments < kMinimumStackSlots) return kMinimumStackSlots;
465530ce411529579186181838984710b0b0980857aaricow@chromium.org  return num_arguments;
4656b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org#else
465730ce411529579186181838984710b0b0980857aaricow@chromium.org  if (num_arguments < kRegisterPassedArguments) return 0;
465830ce411529579186181838984710b0b0980857aaricow@chromium.org  return num_arguments - kRegisterPassedArguments;
4659b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org#endif
4660b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
4661b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
466230ce411529579186181838984710b0b0980857aaricow@chromium.org
46639af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.orgvoid MacroAssembler::EmitSeqStringSetCharCheck(Register string,
46649af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org                                               Register index,
46659af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org                                               Register value,
46669af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org                                               uint32_t encoding_mask) {
46679af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  Label is_object;
46689af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  JumpIfNotSmi(string, &is_object);
46699af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  Throw(kNonObject);
46709af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  bind(&is_object);
46719af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org
46729af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  push(value);
46739af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  movq(value, FieldOperand(string, HeapObject::kMapOffset));
46749af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  movzxbq(value, FieldOperand(value, Map::kInstanceTypeOffset));
46759af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org
46769af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  andb(value, Immediate(kStringRepresentationMask | kStringEncodingMask));
46779af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  cmpq(value, Immediate(encoding_mask));
46789af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  pop(value);
46799af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  ThrowIf(not_equal, kUnexpectedStringType);
46809af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org
46819af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  // The index is assumed to be untagged coming in, tag it to compare with the
46829af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  // string length without using a temp register, it is restored at the end of
46839af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  // this function.
46849af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  Integer32ToSmi(index, index);
46859af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  SmiCompare(index, FieldOperand(string, String::kLengthOffset));
46869af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  ThrowIf(greater_equal, kIndexIsTooLarge);
46879af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org
46889af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  SmiCompare(index, Smi::FromInt(0));
46899af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  ThrowIf(less, kIndexIsNegative);
46909af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org
46919af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  // Restore the index
46929af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  SmiToInteger32(index, index);
46939af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org}
46949af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org
46959af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org
4696b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid MacroAssembler::PrepareCallCFunction(int num_arguments) {
4697b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  int frame_alignment = OS::ActivationFrameAlignment();
4698b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  ASSERT(frame_alignment != 0);
4699b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  ASSERT(num_arguments >= 0);
4700ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
4701b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Make stack end at alignment and allocate space for arguments and old rsp.
4702b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  movq(kScratchRegister, rsp);
4703b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  ASSERT(IsPowerOf2(frame_alignment));
4704b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  int argument_slots_on_stack =
4705b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      ArgumentStackSlotsForCFunctionCall(num_arguments);
4706b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  subq(rsp, Immediate((argument_slots_on_stack + 1) * kPointerSize));
4707b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  and_(rsp, Immediate(-frame_alignment));
4708b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  movq(Operand(rsp, argument_slots_on_stack * kPointerSize), kScratchRegister);
4709b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
4710b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4711b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4712b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid MacroAssembler::CallCFunction(ExternalReference function,
4713b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org                                   int num_arguments) {
4714ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  LoadAddress(rax, function);
4715b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  CallCFunction(rax, num_arguments);
4716b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
4717b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4718b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4719b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid MacroAssembler::CallCFunction(Register function, int num_arguments) {
4720c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(has_frame());
4721c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org  // Check stack alignment.
4722badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  if (emit_debug_code()) {
4723c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org    CheckStackAlignment();
4724c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org  }
4725c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org
4726b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  call(function);
4727b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  ASSERT(OS::ActivationFrameAlignment() != 0);
4728b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  ASSERT(num_arguments >= 0);
4729b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  int argument_slots_on_stack =
4730b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      ArgumentStackSlotsForCFunctionCall(num_arguments);
4731b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  movq(rsp, Operand(rsp, argument_slots_on_stack * kPointerSize));
4732b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
4733b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4734ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org
4735c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.combool AreAliased(Register r1, Register r2, Register r3, Register r4) {
4736c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (r1.is(r2)) return true;
4737c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (r1.is(r3)) return true;
4738c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (r1.is(r4)) return true;
4739c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (r2.is(r3)) return true;
4740c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (r2.is(r4)) return true;
4741c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (r3.is(r4)) return true;
4742c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  return false;
4743c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
4744c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
4745c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
47464af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.orgCodePatcher::CodePatcher(byte* address, int size)
4747c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org    : address_(address),
4748c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org      size_(size),
4749212d964d8f853ddb1fdf3a64037f3af294d55cf3jkummerow@chromium.org      masm_(NULL, address, size + Assembler::kGap) {
47504af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Create a new macro assembler pointing to the address of the code to patch.
47514af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // The size is adjusted with kGap on order for the assembler to generate size
47524af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // bytes of instructions without failing with buffer size constraints.
47534af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
47544af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org}
47554af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
47564af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
47574af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.orgCodePatcher::~CodePatcher() {
47584af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Indicate that code has changed.
47594af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  CPU::FlushICache(address_, size_);
47604af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
47614af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Check that the code was patched as expected.
47624af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  ASSERT(masm_.pc_ == address_ + size_);
47634af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
47644af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org}
47654af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
4766c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
4767c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid MacroAssembler::CheckPageFlag(
4768c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Register object,
4769c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Register scratch,
4770c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    int mask,
4771c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Condition cc,
4772c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Label* condition_met,
4773c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Label::Distance condition_met_distance) {
4774c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(cc == zero || cc == not_zero);
4775c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (scratch.is(object)) {
4776c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    and_(scratch, Immediate(~Page::kPageAlignmentMask));
4777c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  } else {
4778c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    movq(scratch, Immediate(~Page::kPageAlignmentMask));
4779c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    and_(scratch, object);
4780c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
4781c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (mask < (1 << kBitsPerByte)) {
4782c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    testb(Operand(scratch, MemoryChunk::kFlagsOffset),
4783c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          Immediate(static_cast<uint8_t>(mask)));
4784c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  } else {
4785c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    testl(Operand(scratch, MemoryChunk::kFlagsOffset), Immediate(mask));
4786c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
4787c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  j(cc, condition_met, condition_met_distance);
4788c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
4789c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
4790c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
4791f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.orgvoid MacroAssembler::CheckMapDeprecated(Handle<Map> map,
4792f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org                                        Register scratch,
4793f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org                                        Label* if_deprecated) {
4794f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  if (map->CanBeDeprecated()) {
4795f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    Move(scratch, map);
4796f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    movq(scratch, FieldOperand(scratch, Map::kBitField3Offset));
4797f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    SmiToInteger32(scratch, scratch);
4798f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    and_(scratch, Immediate(Map::Deprecated::kMask));
4799f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    j(not_zero, if_deprecated);
4800f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  }
4801f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org}
4802f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org
4803f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org
4804c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid MacroAssembler::JumpIfBlack(Register object,
4805c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                 Register bitmap_scratch,
4806c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                 Register mask_scratch,
4807c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                 Label* on_black,
4808c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                 Label::Distance on_black_distance) {
4809c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(!AreAliased(object, bitmap_scratch, mask_scratch, rcx));
4810c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  GetMarkBits(object, bitmap_scratch, mask_scratch);
4811c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
4812c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0);
4813c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // The mask_scratch register contains a 1 at the position of the first bit
4814c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // and a 0 at all other positions, including the position of the second bit.
4815c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  movq(rcx, mask_scratch);
4816c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Make rcx into a mask that covers both marking bits using the operation
4817c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // rcx = mask | (mask << 1).
4818c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  lea(rcx, Operand(mask_scratch, mask_scratch, times_2, 0));
4819c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Note that we are using a 4-byte aligned 8-byte load.
4820c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  and_(rcx, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
4821c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  cmpq(mask_scratch, rcx);
4822c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  j(equal, on_black, on_black_distance);
4823c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
4824c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
4825c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
4826c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// Detect some, but not all, common pointer-free objects.  This is used by the
4827c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// incremental write barrier which doesn't care about oddballs (they are always
4828c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// marked black immediately so this code is not hit).
4829c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid MacroAssembler::JumpIfDataObject(
4830c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Register value,
4831c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Register scratch,
4832c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Label* not_data_object,
4833c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Label::Distance not_data_object_distance) {
4834c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Label is_data_object;
4835c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  movq(scratch, FieldOperand(value, HeapObject::kMapOffset));
4836c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  CompareRoot(scratch, Heap::kHeapNumberMapRootIndex);
4837c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  j(equal, &is_data_object, Label::kNear);
4838c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1);
4839c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(kNotStringTag == 0x80 && kIsNotStringMask == 0x80);
4840c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // If it's a string and it's not a cons string then it's an object containing
4841c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // no GC pointers.
4842c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  testb(FieldOperand(scratch, Map::kInstanceTypeOffset),
4843c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        Immediate(kIsIndirectStringMask | kIsNotStringMask));
4844c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  j(not_zero, not_data_object, not_data_object_distance);
4845c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  bind(&is_data_object);
4846c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
4847c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
4848c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
4849c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid MacroAssembler::GetMarkBits(Register addr_reg,
4850c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                 Register bitmap_reg,
4851c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                 Register mask_reg) {
4852c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(!AreAliased(addr_reg, bitmap_reg, mask_reg, rcx));
4853c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  movq(bitmap_reg, addr_reg);
4854c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Sign extended 32 bit immediate.
4855c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  and_(bitmap_reg, Immediate(~Page::kPageAlignmentMask));
4856c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  movq(rcx, addr_reg);
4857c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  int shift =
4858c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Bitmap::kBitsPerCellLog2 + kPointerSizeLog2 - Bitmap::kBytesPerCellLog2;
4859c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  shrl(rcx, Immediate(shift));
4860c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  and_(rcx,
4861c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com       Immediate((Page::kPageAlignmentMask >> shift) &
4862c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                 ~(Bitmap::kBytesPerCell - 1)));
4863c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
4864c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  addq(bitmap_reg, rcx);
4865c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  movq(rcx, addr_reg);
4866c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  shrl(rcx, Immediate(kPointerSizeLog2));
4867c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  and_(rcx, Immediate((1 << Bitmap::kBitsPerCellLog2) - 1));
4868c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  movl(mask_reg, Immediate(1));
4869c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  shl_cl(mask_reg);
4870c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
4871c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
4872c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
4873c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid MacroAssembler::EnsureNotWhite(
4874c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Register value,
4875c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Register bitmap_scratch,
4876c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Register mask_scratch,
4877c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Label* value_is_white_and_not_data,
4878c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Label::Distance distance) {
4879c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(!AreAliased(value, bitmap_scratch, mask_scratch, rcx));
4880c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  GetMarkBits(value, bitmap_scratch, mask_scratch);
4881c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
4882c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // If the value is black or grey we don't need to do anything.
4883c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(strcmp(Marking::kWhiteBitPattern, "00") == 0);
4884c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0);
4885c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(strcmp(Marking::kGreyBitPattern, "11") == 0);
4886c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(strcmp(Marking::kImpossibleBitPattern, "01") == 0);
4887c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
4888c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Label done;
4889c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
4890c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Since both black and grey have a 1 in the first position and white does
4891c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // not have a 1 there we only need to check one bit.
4892c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  testq(Operand(bitmap_scratch, MemoryChunk::kHeaderSize), mask_scratch);
4893c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  j(not_zero, &done, Label::kNear);
4894c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
4895000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.org  if (emit_debug_code()) {
4896c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Check for impossible bit pattern.
4897c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Label ok;
4898c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    push(mask_scratch);
4899c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // shl.  May overflow making the check conservative.
4900c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    addq(mask_scratch, mask_scratch);
4901c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    testq(Operand(bitmap_scratch, MemoryChunk::kHeaderSize), mask_scratch);
4902c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    j(zero, &ok, Label::kNear);
4903c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    int3();
4904c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    bind(&ok);
4905c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    pop(mask_scratch);
4906c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
4907c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
4908c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Value is white.  We check whether it is data that doesn't need scanning.
4909c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Currently only checks for HeapNumber and non-cons strings.
4910c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Register map = rcx;  // Holds map while checking type.
4911c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Register length = rcx;  // Holds length of object after checking type.
4912c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Label not_heap_number;
4913c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Label is_data_object;
4914c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
4915c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Check for heap-number
4916c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  movq(map, FieldOperand(value, HeapObject::kMapOffset));
4917c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  CompareRoot(map, Heap::kHeapNumberMapRootIndex);
4918c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  j(not_equal, &not_heap_number, Label::kNear);
4919c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  movq(length, Immediate(HeapNumber::kSize));
4920c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  jmp(&is_data_object, Label::kNear);
4921c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
4922c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  bind(&not_heap_number);
4923c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Check for strings.
4924c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1);
4925c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(kNotStringTag == 0x80 && kIsNotStringMask == 0x80);
4926c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // If it's a string and it's not a cons string then it's an object containing
4927c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // no GC pointers.
4928c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Register instance_type = rcx;
4929c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  movzxbl(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
4930c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  testb(instance_type, Immediate(kIsIndirectStringMask | kIsNotStringMask));
4931c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  j(not_zero, value_is_white_and_not_data);
4932c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // It's a non-indirect (non-cons and non-slice) string.
4933c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // If it's external, the length is just ExternalString::kSize.
4934c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Otherwise it's String::kHeaderSize + string->length() * (1 or 2).
4935c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Label not_external;
4936c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // External strings are the only ones with the kExternalStringTag bit
4937c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // set.
4938c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT_EQ(0, kSeqStringTag & kExternalStringTag);
4939c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT_EQ(0, kConsStringTag & kExternalStringTag);
4940c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  testb(instance_type, Immediate(kExternalStringTag));
4941c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  j(zero, &not_external, Label::kNear);
4942c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  movq(length, Immediate(ExternalString::kSize));
4943c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  jmp(&is_data_object, Label::kNear);
4944c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
4945c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  bind(&not_external);
4946c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Sequential string, either ASCII or UC16.
4947e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  ASSERT(kOneByteStringTag == 0x04);
4948c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  and_(length, Immediate(kStringEncodingMask));
4949c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  xor_(length, Immediate(kStringEncodingMask));
4950c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  addq(length, Immediate(0x04));
4951c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Value now either 4 (if ASCII) or 8 (if UC16), i.e. char-size shifted by 2.
4952c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  imul(length, FieldOperand(value, String::kLengthOffset));
4953c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  shr(length, Immediate(2 + kSmiTagSize + kSmiShiftSize));
4954c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  addq(length, Immediate(SeqString::kHeaderSize + kObjectAlignmentMask));
4955c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  and_(length, Immediate(~kObjectAlignmentMask));
4956c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
4957c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  bind(&is_data_object);
4958c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Value is a data object, and it is white.  Mark it black.  Since we know
4959c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // that the object is white we can make it black by flipping one bit.
4960c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  or_(Operand(bitmap_scratch, MemoryChunk::kHeaderSize), mask_scratch);
4961c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
4962c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  and_(bitmap_scratch, Immediate(~Page::kPageAlignmentMask));
4963c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  addl(Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset), length);
4964c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
4965c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  bind(&done);
4966c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
4967c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
4968be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.org
4969be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.orgvoid MacroAssembler::CheckEnumCache(Register null_value, Label* call_runtime) {
4970355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  Label next, start;
4971be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.org  Register empty_fixed_array_value = r8;
4972be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.org  LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex);
4973be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.org  movq(rcx, rax);
4974be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.org
4975355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  // Check if the enum length field is properly initialized, indicating that
4976355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  // there is an enum cache.
4977be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.org  movq(rbx, FieldOperand(rcx, HeapObject::kMapOffset));
4978657d53b99cb4d261f8245bcb4248c39eb0a2b10frossberg@chromium.org
4979355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  EnumLength(rdx, rbx);
4980af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  Cmp(rdx, Smi::FromInt(kInvalidEnumCacheSentinel));
4981de64f721c489207a7b9018406d39c7fb04bb9424verwaest@chromium.org  j(equal, call_runtime);
4982de64f721c489207a7b9018406d39c7fb04bb9424verwaest@chromium.org
4983355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  jmp(&start);
4984355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org
4985355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  bind(&next);
4986355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org
4987355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  movq(rbx, FieldOperand(rcx, HeapObject::kMapOffset));
4988be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.org
4989be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.org  // For all objects but the receiver, check that the cache is empty.
4990355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  EnumLength(rdx, rbx);
4991355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  Cmp(rdx, Smi::FromInt(0));
4992355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  j(not_equal, call_runtime);
4993355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org
4994355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  bind(&start);
4995355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org
4996355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  // Check that there are no elements. Register rcx contains the current JS
4997355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  // object we've reached through the prototype chain.
4998355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  cmpq(empty_fixed_array_value,
4999355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org       FieldOperand(rcx, JSObject::kElementsOffset));
5000be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.org  j(not_equal, call_runtime);
5001be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.org
5002be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.org  movq(rcx, FieldOperand(rbx, Map::kPrototypeOffset));
5003be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.org  cmpq(rcx, null_value);
5004be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.org  j(not_equal, &next);
5005be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.org}
5006be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.org
5007ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.orgvoid MacroAssembler::TestJSArrayForAllocationMemento(
500859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    Register receiver_reg,
5009b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org    Register scratch_reg,
5010b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org    Label* no_memento_found) {
501159297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  ExternalReference new_space_start =
501259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org      ExternalReference::new_space_start(isolate());
501359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  ExternalReference new_space_allocation_top =
501459297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org      ExternalReference::new_space_allocation_top_address(isolate());
501559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org
501659297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  lea(scratch_reg, Operand(receiver_reg,
5017ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org      JSArray::kSize + AllocationMemento::kSize - kHeapObjectTag));
5018e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  Move(kScratchRegister, new_space_start);
501959297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  cmpq(scratch_reg, kScratchRegister);
5020b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org  j(less, no_memento_found);
502159297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  cmpq(scratch_reg, ExternalOperand(new_space_allocation_top));
5022b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org  j(greater, no_memento_found);
5023ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  CompareRoot(MemOperand(scratch_reg, -AllocationMemento::kSize),
5024ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org              Heap::kAllocationMementoMapRootIndex);
502559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org}
502659297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org
5027be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.org
5028e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.orgvoid MacroAssembler::JumpIfDictionaryInPrototypeChain(
5029e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    Register object,
5030e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    Register scratch0,
5031e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    Register scratch1,
5032e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    Label* found) {
5033e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  ASSERT(!(scratch0.is(kScratchRegister) && scratch1.is(kScratchRegister)));
5034e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  ASSERT(!scratch1.is(scratch0));
5035e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  Register current = scratch0;
5036e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  Label loop_again;
5037e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org
5038e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  movq(current, object);
5039e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org
5040e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  // Loop based on the map going up the prototype chain.
5041e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  bind(&loop_again);
5042e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  movq(current, FieldOperand(current, HeapObject::kMapOffset));
5043e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  movq(scratch1, FieldOperand(current, Map::kBitField2Offset));
5044e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  and_(scratch1, Immediate(Map::kElementsKindMask));
5045e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  shr(scratch1, Immediate(Map::kElementsKindShift));
5046e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  cmpq(scratch1, Immediate(DICTIONARY_ELEMENTS));
5047e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  j(equal, found);
5048e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  movq(current, FieldOperand(current, Map::kPrototypeOffset));
5049e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  CompareRoot(current, Heap::kNullValueRootIndex);
5050e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  j(not_equal, &loop_again);
5051e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org}
5052e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org
5053e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org
505471affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org} }  // namespace v8::internal
50559dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
50569dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com#endif  // V8_TARGET_ARCH_X64
5057