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
289085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#ifndef V8_X64_MACRO_ASSEMBLER_X64_H_
299085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#define V8_X64_MACRO_ASSEMBLER_X64_H_
309085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
319085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#include "assembler.h"
32c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com#include "frames.h"
33c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org#include "v8globals.h"
349085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3571affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgnamespace v8 {
3671affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgnamespace internal {
379085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
38e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org// Default scratch register used by MacroAssembler (and other code that needs
39e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org// a spare register). The register isn't callee save, and not used by the
40e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org// function calling convention.
411b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.orgconst Register kScratchRegister = { 10 };      // r10.
421b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.orgconst Register kSmiConstantRegister = { 12 };  // r12 (callee save).
431b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.orgconst Register kRootRegister = { 13 };         // r13 (callee save).
4469ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org// Value of smi in kSmiConstantRegister.
451b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.orgconst int kSmiConstantRegisterValue = 1;
468f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org// Actual value of root register is offset from the root array's start
478f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org// to take advantage of negitive 8-bit displacement values.
481b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.orgconst int kRootRegisterBias = 128;
49e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
500c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org// Convenience for platform-independent signatures.
510c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.orgtypedef Operand MemOperand;
520c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org
53c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comenum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET };
54c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comenum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK };
55c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
56c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.combool AreAliased(Register r1, Register r2, Register r3, Register r4);
57c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
589085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// Forward declaration.
599085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgclass JumpTarget;
609085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
614af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.orgstruct SmiIndex {
624af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  SmiIndex(Register index_register, ScaleFactor scale)
634af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org      : reg(index_register),
644af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org        scale(scale) {}
654af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  Register reg;
664af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  ScaleFactor scale;
674af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org};
689085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
69c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
709085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// MacroAssembler implements a collection of frequently used macros.
719085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgclass MacroAssembler: public Assembler {
729085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org public:
73c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  // The isolate parameter can be NULL if the macro assembler should
74c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  // not use isolate-dependent functionality. In this case, it's the
75c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  // responsibility of the caller to never invoke such function on the
76c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  // macro assembler.
77c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  MacroAssembler(Isolate* isolate, void* buffer, int size);
789085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
79ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // Prevent the use of the RootArray during the lifetime of this
80ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // scope object.
81ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  class NoRootArrayScope BASE_EMBEDDED {
82ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org   public:
83ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    explicit NoRootArrayScope(MacroAssembler* assembler)
84ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org        : variable_(&assembler->root_array_available_),
85ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org          old_value_(assembler->root_array_available_) {
86ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      assembler->root_array_available_ = false;
87ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    }
88ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    ~NoRootArrayScope() {
89ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      *variable_ = old_value_;
90ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    }
91ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org   private:
92ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    bool* variable_;
93ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    bool old_value_;
94ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  };
95ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
96ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // Operand pointing to an external reference.
97ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // May emit code to set up the scratch register. The operand is
98ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // only guaranteed to be correct as long as the scratch register
99ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // isn't changed.
100ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // If the operand is used more than once, use a scratch register
101ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // that is guaranteed not to be clobbered.
102ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  Operand ExternalOperand(ExternalReference reference,
103ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org                          Register scratch = kScratchRegister);
104ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // Loads and stores the value of an external reference.
105ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // Special case code for load and store to take advantage of
106ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // load_rax/store_rax if possible/necessary.
107ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // For other operations, just use:
108ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  //   Operand operand = ExternalOperand(extref);
109ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  //   operation(operand, ..);
110ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  void Load(Register destination, ExternalReference source);
111ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  void Store(ExternalReference destination, Register source);
112ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // Loads the address of the external reference into the destination
113ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // register.
114ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  void LoadAddress(Register destination, ExternalReference source);
115ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // Returns the size of the code generated by LoadAddress.
116ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // Used by CallSize(ExternalReference) to find the size of a call.
117ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  int LoadAddressSize(ExternalReference source);
118ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  // Pushes the address of the external reference onto the stack.
119ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  void PushAddress(ExternalReference source);
120ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
121ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // Operations on roots in the root-array.
12218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  void LoadRoot(Register destination, Heap::RootListIndex index);
123ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  void StoreRoot(Register source, Heap::RootListIndex index);
1248f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  // Load a root value where the index (or part of it) is variable.
1258f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  // The variable_offset register is added to the fixed_offset value
1268f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  // to get the index into the root-array.
1278f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  void LoadRootIndexed(Register destination,
1288f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org                       Register variable_offset,
1298f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org                       int fixed_offset);
13018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  void CompareRoot(Register with, Heap::RootListIndex index);
13183aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  void CompareRoot(const Operand& with, Heap::RootListIndex index);
13218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  void PushRoot(Heap::RootListIndex index);
13318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
134c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // These functions do not arrange the registers in any particular order so
135c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // they are not useful for calls that can cause a GC.  The caller can
136c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // exclude up to 3 registers that do not need to be saved and restored.
137c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void PushCallerSaved(SaveFPRegsMode fp_mode,
138c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                       Register exclusion1 = no_reg,
139c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                       Register exclusion2 = no_reg,
140c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                       Register exclusion3 = no_reg);
141c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void PopCallerSaved(SaveFPRegsMode fp_mode,
142c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                      Register exclusion1 = no_reg,
143c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                      Register exclusion2 = no_reg,
144c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                      Register exclusion3 = no_reg);
145c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
146c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// ---------------------------------------------------------------------------
147c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// GC Support
148c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
149c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
150c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  enum RememberedSetFinalAction {
151c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    kReturnAtEnd,
152c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    kFallThroughAtEnd
153c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  };
1544111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org
155c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Record in the remembered set the fact that we have a pointer to new space
156c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // at the address pointed to by the addr register.  Only works if addr is not
157c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // in new space.
158c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void RememberedSetHelper(Register object,  // Used for debug code.
159c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           Register addr,
160c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           Register scratch,
161c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           SaveFPRegsMode save_fp,
162c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           RememberedSetFinalAction and_then);
163c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
164c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void CheckPageFlag(Register object,
165c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     Register scratch,
166c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     int mask,
167c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     Condition cc,
168c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     Label* condition_met,
169c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     Label::Distance condition_met_distance = Label::kFar);
170c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
171f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  void CheckMapDeprecated(Handle<Map> map,
172f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org                          Register scratch,
173f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org                          Label* if_deprecated);
174f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org
175c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Check if object is in new space.  Jumps if the object is not in new space.
176c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // The register scratch can be object itself, but scratch will be clobbered.
177c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void JumpIfNotInNewSpace(Register object,
178c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           Register scratch,
179c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           Label* branch,
180c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           Label::Distance distance = Label::kFar) {
181c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    InNewSpace(object, scratch, not_equal, branch, distance);
182c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
183c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
184c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Check if object is in new space.  Jumps if the object is in new space.
185c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // The register scratch can be object itself, but it will be clobbered.
186c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void JumpIfInNewSpace(Register object,
187c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                        Register scratch,
188c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                        Label* branch,
189c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                        Label::Distance distance = Label::kFar) {
190c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    InNewSpace(object, scratch, equal, branch, distance);
191c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
192c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
193c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Check if an object has the black incremental marking color.  Also uses rcx!
194c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void JumpIfBlack(Register object,
195c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                   Register scratch0,
196c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                   Register scratch1,
197c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                   Label* on_black,
198c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                   Label::Distance on_black_distance = Label::kFar);
199c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
2002efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  // Detects conservatively whether an object is data-only, i.e. it does need to
201c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // be scanned by the garbage collector.
202c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void JumpIfDataObject(Register value,
203c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                        Register scratch,
204c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                        Label* not_data_object,
205c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                        Label::Distance not_data_object_distance);
206c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
207c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Checks the color of an object.  If the object is already grey or black
208c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // then we just fall through, since it is already live.  If it is white and
209c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // we can determine that it doesn't need to be scanned, then we just mark it
210c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // black and fall through.  For the rest we jump to the label so the
211c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // incremental marker can fix its assumptions.
212c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void EnsureNotWhite(Register object,
213c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                      Register scratch1,
214c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                      Register scratch2,
215c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                      Label* object_is_white_and_not_data,
216c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                      Label::Distance distance);
217c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
218c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Notify the garbage collector that we wrote a pointer into an object.
219c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // |object| is the object being stored into, |value| is the object being
220c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // stored.  value and scratch registers are clobbered by the operation.
221c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // The offset is the offset from the start of the object, not the offset from
222c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // the tagged HeapObject pointer.  For use with FieldOperand(reg, off).
223c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void RecordWriteField(
224c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Register object,
225c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      int offset,
226c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Register value,
227c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Register scratch,
228c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      SaveFPRegsMode save_fp,
229c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
230c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      SmiCheck smi_check = INLINE_SMI_CHECK);
231c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
232c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // As above, but the offset has the tag presubtracted.  For use with
233c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Operand(reg, off).
234c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void RecordWriteContextSlot(
235c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Register context,
236c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      int offset,
237c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Register value,
238c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Register scratch,
239c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      SaveFPRegsMode save_fp,
240c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
241c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      SmiCheck smi_check = INLINE_SMI_CHECK) {
242c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    RecordWriteField(context,
243c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     offset + kHeapObjectTag,
244c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     value,
245c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     scratch,
246c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     save_fp,
247c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     remembered_set_action,
248c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     smi_check);
249c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
250c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
251c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Notify the garbage collector that we wrote a pointer into a fixed array.
252c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // |array| is the array being stored into, |value| is the
253394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // object being stored.  |index| is the array index represented as a non-smi.
254394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // All registers are clobbered by the operation RecordWriteArray
255c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // filters out smis so it does not update the write barrier if the
256c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // value is a smi.
257c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void RecordWriteArray(
258c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Register array,
259c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Register value,
260c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Register index,
261c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      SaveFPRegsMode save_fp,
262c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
263c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      SmiCheck smi_check = INLINE_SMI_CHECK);
264c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
265c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // For page containing |object| mark region covering |address|
26669ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  // dirty. |object| is the object being stored into, |value| is the
267c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // object being stored. The address and value registers are clobbered by the
26869ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  // operation.  RecordWrite filters out smis so it does not update
26969ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  // the write barrier if the value is a smi.
270c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void RecordWrite(
271c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Register object,
272c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Register address,
273c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Register value,
274c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      SaveFPRegsMode save_fp,
275c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
276c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      SmiCheck smi_check = INLINE_SMI_CHECK);
2779d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
2789085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#ifdef ENABLE_DEBUGGER_SUPPORT
2799085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // ---------------------------------------------------------------------------
2809085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Debugger Support
2819085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
2825c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void DebugBreak();
2839085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#endif
2849085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
285c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  // Enter specific kind of exit frame; either in normal or
286c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  // debug mode. Expects the number of arguments in register rax and
287a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org  // sets up the number of arguments in register rdi and the pointer
288a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org  // to the first argument in register rsi.
2894a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  //
2904a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  // Allocates arg_stack_space * kPointerSize memory (not GCed) on the stack
2914a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  // accessible via StackSpaceOperand.
2920ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  void EnterExitFrame(int arg_stack_space = 0, bool save_doubles = false);
2939085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
2944a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  // Enter specific kind of exit frame. Allocates arg_stack_space * kPointerSize
2954a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  // memory (not GCed) on the stack accessible via StackSpaceOperand.
2964a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  void EnterApiExitFrame(int arg_stack_space);
297e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org
298a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org  // Leave the current exit frame. Expects/provides the return value in
299a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org  // register rax:rdx (untouched) and the pointer to the first
300a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org  // argument in register rsi.
3010ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  void LeaveExitFrame(bool save_doubles = false);
3029085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3034a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  // Leave the current exit frame. Expects/provides the return value in
3044a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  // register rax (untouched).
3054a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  void LeaveApiExitFrame();
3069085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
307a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Push and pop the registers that can hold pointers.
3080ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  void PushSafepointRegisters() { Pushad(); }
3090ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  void PopSafepointRegisters() { Popad(); }
3103a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // Store the value in register src in the safepoint register stack
3113a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // slot for register dst.
31246839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  void StoreToSafepointRegisterSlot(Register dst, const Immediate& imm);
3133a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  void StoreToSafepointRegisterSlot(Register dst, Register src);
3145d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  void LoadFromSafepointRegisterSlot(Register dst, Register src);
3150ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org
3168f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  void InitializeRootRegister() {
317394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    ExternalReference roots_array_start =
318394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        ExternalReference::roots_array_start(isolate());
319394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    movq(kRootRegister, roots_array_start);
3208f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    addq(kRootRegister, Immediate(kRootRegisterBias));
3218f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  }
3228f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org
3239085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // ---------------------------------------------------------------------------
3249085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // JavaScript invokes
3259085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
326f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // Set up call kind marking in rcx. The method takes rcx as an
32740cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  // explicit first parameter to make the code more readable at the
32840cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  // call sites.
32940cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  void SetCallKind(Register dst, CallKind kind);
33040cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org
3319085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Invoke the JavaScript function code by either calling or jumping.
332eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void InvokeCode(Register code,
3339085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org                  const ParameterCount& expected,
3349085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org                  const ParameterCount& actual,
3353a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                  InvokeFlag flag,
336d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org                  const CallWrapper& call_wrapper,
337d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org                  CallKind call_kind);
3389085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3399085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void InvokeCode(Handle<Code> code,
3409085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org                  const ParameterCount& expected,
3419085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org                  const ParameterCount& actual,
3429085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org                  RelocInfo::Mode rmode,
3433a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                  InvokeFlag flag,
344d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org                  const CallWrapper& call_wrapper,
345d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org                  CallKind call_kind);
3469085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3479085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Invoke the JavaScript function in the given register. Changes the
3489085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // current context to the context in the function before invoking.
3499085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void InvokeFunction(Register function,
3509085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org                      const ParameterCount& actual,
3513a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                      InvokeFlag flag,
352d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org                      const CallWrapper& call_wrapper,
353d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org                      CallKind call_kind);
3549085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
355c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  void InvokeFunction(Handle<JSFunction> function,
35632d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org                      const ParameterCount& expected,
3575c838251403b0be9a882540f1922577abba4c872ager@chromium.org                      const ParameterCount& actual,
3583a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                      InvokeFlag flag,
359d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org                      const CallWrapper& call_wrapper,
360d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org                      CallKind call_kind);
3615c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3629085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Invoke specified builtin JavaScript function. Adds an entry to
3639085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // the unresolved list if the name does not resolve.
3643a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  void InvokeBuiltin(Builtins::JavaScript id,
3653a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                     InvokeFlag flag,
366fb144a0716afe7ab8bf245f2391a9e53b3db3c89fschneider@chromium.org                     const CallWrapper& call_wrapper = NullCallWrapper());
3679085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
368145eff58d4f6ac0dcc53abb556dbf3cac6c3280aerik.corry@gmail.com  // Store the function for the given builtin in the target register.
369145eff58d4f6ac0dcc53abb556dbf3cac6c3280aerik.corry@gmail.com  void GetBuiltinFunction(Register target, Builtins::JavaScript id);
370145eff58d4f6ac0dcc53abb556dbf3cac6c3280aerik.corry@gmail.com
3719085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Store the code object for the given builtin in the target register.
3729085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void GetBuiltinEntry(Register target, Builtins::JavaScript id);
3739085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3744af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
3754af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // ---------------------------------------------------------------------------
3764af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Smi tagging, untagging and operations on tagged smis.
3774af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
37869ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  void InitializeSmiConstantRegister() {
37969ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    movq(kSmiConstantRegister,
38069ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org         reinterpret_cast<uint64_t>(Smi::FromInt(kSmiConstantRegisterValue)),
3814cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org         RelocInfo::NONE64);
38269ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  }
38369ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org
3844af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Conversions between tagged smi values and non-tagged integer values.
3854af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
3864af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Tag an integer value. The result must be known to be a valid smi value.
387b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Only uses the low 32 bits of the src register. Sets the N and Z flags
388c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org  // based on the value of the resulting smi.
3894af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void Integer32ToSmi(Register dst, Register src);
3904af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
3915ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org  // Stores an integer32 value into a memory field that already holds a smi.
3925ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org  void Integer32ToSmiField(const Operand& dst, Register src);
3935ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org
3944af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Adds constant to src and tags the result as a smi.
3954af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Result must be a valid smi.
3969d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void Integer64PlusConstantToSmi(Register dst, Register src, int constant);
3974af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
3984af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Convert smi to 32-bit integer. I.e., not sign extended into
3994af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // high 32 bits of destination.
4004af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiToInteger32(Register dst, Register src);
40130ce411529579186181838984710b0b0980857aaricow@chromium.org  void SmiToInteger32(Register dst, const Operand& src);
4024af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
4034af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Convert smi to 64-bit integer (sign extended if necessary).
4044af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiToInteger64(Register dst, Register src);
4055ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org  void SmiToInteger64(Register dst, const Operand& src);
4064af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
4074af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Multiply a positive smi's integer value by a power of two.
4084af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Provides result as 64-bit integer value.
4094af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void PositiveSmiTimesPowerOfTwoToInteger64(Register dst,
4104af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                                             Register src,
4114af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                                             int power);
4124af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
41330ce411529579186181838984710b0b0980857aaricow@chromium.org  // Divide a positive smi's integer value by a power of two.
41430ce411529579186181838984710b0b0980857aaricow@chromium.org  // Provides result as 32-bit integer value.
41530ce411529579186181838984710b0b0980857aaricow@chromium.org  void PositiveSmiDivPowerOfTwoToInteger32(Register dst,
41630ce411529579186181838984710b0b0980857aaricow@chromium.org                                           Register src,
41730ce411529579186181838984710b0b0980857aaricow@chromium.org                                           int power);
41830ce411529579186181838984710b0b0980857aaricow@chromium.org
41944bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  // Perform the logical or of two smi values and return a smi value.
42044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  // If either argument is not a smi, jump to on_not_smis and retain
42144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  // the original values of source registers. The destination register
42244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  // may be changed if it's not one of the source registers.
42344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  void SmiOrIfSmis(Register dst,
42444bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org                   Register src1,
42544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org                   Register src2,
42683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                   Label* on_not_smis,
42783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                   Label::Distance near_jump = Label::kFar);
42844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
42930ce411529579186181838984710b0b0980857aaricow@chromium.org
430badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  // Simple comparison of smis.  Both sides must be known smis to use these,
431badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  // otherwise use Cmp.
432badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  void SmiCompare(Register smi1, Register smi2);
4339d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void SmiCompare(Register dst, Smi* src);
434ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  void SmiCompare(Register dst, const Operand& src);
4359d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void SmiCompare(const Operand& dst, Register src);
4369d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void SmiCompare(const Operand& dst, Smi* src);
4375ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org  // Compare the int32 in src register to the value of the smi stored at dst.
4385ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org  void SmiCompareInteger32(const Operand& dst, Register src);
4399d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  // Sets sign and zero flags depending on value of smi in register.
4409d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void SmiTest(Register src);
4419d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
4424af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Functions performing a check on a known or potential smi. Returns
4434af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // a condition that is satisfied if the check is successful.
4444af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
4454af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Is the value a tagged smi.
4464af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  Condition CheckSmi(Register src);
4470a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  Condition CheckSmi(const Operand& src);
4484af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
449eb7c144137bd7d461d4996f752f1353a0856fac1ricow@chromium.org  // Is the value a non-negative tagged smi.
450eb7c144137bd7d461d4996f752f1353a0856fac1ricow@chromium.org  Condition CheckNonNegativeSmi(Register src);
4514af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
452b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Are both values tagged smis.
4534af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  Condition CheckBothSmi(Register first, Register second);
4544af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
455eb7c144137bd7d461d4996f752f1353a0856fac1ricow@chromium.org  // Are both values non-negative tagged smis.
456eb7c144137bd7d461d4996f752f1353a0856fac1ricow@chromium.org  Condition CheckBothNonNegativeSmi(Register first, Register second);
457b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
458b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Are either value a tagged smi.
459c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org  Condition CheckEitherSmi(Register first,
460c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org                           Register second,
461c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org                           Register scratch = kScratchRegister);
462b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4634af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Is the value the minimum smi value (since we are using
4644af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // two's complement numbers, negating the value is known to yield
4654af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // a non-smi value).
4664af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  Condition CheckIsMinSmi(Register src);
4674af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
4684af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Checks whether an 32-bit integer value is a valid for conversion
4694af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // to a smi.
4704af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  Condition CheckInteger32ValidSmiValue(Register src);
4714af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
4723811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  // Checks whether an 32-bit unsigned integer value is a valid for
4733811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  // conversion to a smi.
4743811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  Condition CheckUInteger32ValidSmiValue(Register src);
4753811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
4760ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  // Check whether src is a Smi, and set dst to zero if it is a smi,
4770ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  // and to one if it isn't.
4780ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  void CheckSmiToIndicator(Register dst, Register src);
4790ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  void CheckSmiToIndicator(Register dst, const Operand& src);
4800ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org
4814af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Test-and-jump functions. Typically combines a check function
4824af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // above with a conditional jump.
4834af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
4844af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Jump if the value cannot be represented by a smi.
48583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  void JumpIfNotValidSmiValue(Register src, Label* on_invalid,
48683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                              Label::Distance near_jump = Label::kFar);
4874af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
4883811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  // Jump if the unsigned integer value cannot be represented by a smi.
48983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  void JumpIfUIntNotValidSmiValue(Register src, Label* on_invalid,
49083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                  Label::Distance near_jump = Label::kFar);
4913811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
4924af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Jump to label if the value is a tagged smi.
49383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  void JumpIfSmi(Register src,
49483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                 Label* on_smi,
49583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                 Label::Distance near_jump = Label::kFar);
4964af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
4974af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Jump to label if the value is not a tagged smi.
49883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  void JumpIfNotSmi(Register src,
49983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                    Label* on_not_smi,
50083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                    Label::Distance near_jump = Label::kFar);
5014af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
502eb7c144137bd7d461d4996f752f1353a0856fac1ricow@chromium.org  // Jump to label if the value is not a non-negative tagged smi.
50383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  void JumpUnlessNonNegativeSmi(Register src,
50483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                Label* on_not_smi,
50583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                Label::Distance near_jump = Label::kFar);
5064af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
5079d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  // Jump to label if the value, which must be a tagged smi, has value equal
5084af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // to the constant.
509c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org  void JumpIfSmiEqualsConstant(Register src,
510c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org                               Smi* constant,
51183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                               Label* on_equals,
51283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                               Label::Distance near_jump = Label::kFar);
513c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org
5144af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Jump if either or both register are not smi values.
515c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org  void JumpIfNotBothSmi(Register src1,
516c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org                        Register src2,
51783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                        Label* on_not_both_smi,
51883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                        Label::Distance near_jump = Label::kFar);
5194af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
520eb7c144137bd7d461d4996f752f1353a0856fac1ricow@chromium.org  // Jump if either or both register are not non-negative smi values.
521eb7c144137bd7d461d4996f752f1353a0856fac1ricow@chromium.org  void JumpUnlessBothNonNegativeSmi(Register src1, Register src2,
52283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                    Label* on_not_both_smi,
52383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                    Label::Distance near_jump = Label::kFar);
524b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
5254af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Operations on tagged smi values.
5264af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
5274af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Smis represent a subset of integers. The subset is always equivalent to
5284af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // a two's complement interpretation of a fixed number of bits.
5294af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
5304af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Optimistically adds an integer constant to a supposed smi.
5314af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // If the src is not a smi, or the result is not a smi, jump to
5324af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // the label.
5334af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiTryAddConstant(Register dst,
5344af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                         Register src,
5359d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com                         Smi* constant,
53683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                         Label* on_not_smi_result,
53783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                         Label::Distance near_jump = Label::kFar);
5384af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
5399d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  // Add an integer constant to a tagged smi, giving a tagged smi as result.
5409d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  // No overflow testing on the result is done.
5419d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void SmiAddConstant(Register dst, Register src, Smi* constant);
5429d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
5439dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Add an integer constant to a tagged smi, giving a tagged smi as result.
5449dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // No overflow testing on the result is done.
5459dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  void SmiAddConstant(const Operand& dst, Smi* constant);
5469dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
5474af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Add an integer constant to a tagged smi, giving a tagged smi as result,
5484af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // or jumping to a label if the result cannot be represented by a smi.
5494af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiAddConstant(Register dst,
5504af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                      Register src,
5519d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com                      Smi* constant,
55283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                      Label* on_not_smi_result,
55383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                      Label::Distance near_jump = Label::kFar);
5544af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
5554af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Subtract an integer constant from a tagged smi, giving a tagged smi as
556ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  // result. No testing on the result is done. Sets the N and Z flags
557ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  // based on the value of the resulting integer.
5589d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void SmiSubConstant(Register dst, Register src, Smi* constant);
5599d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
5609d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  // Subtract an integer constant from a tagged smi, giving a tagged smi as
5614af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // result, or jumping to a label if the result cannot be represented by a smi.
5624af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiSubConstant(Register dst,
5634af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                      Register src,
5649d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com                      Smi* constant,
56583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                      Label* on_not_smi_result,
56683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                      Label::Distance near_jump = Label::kFar);
5674af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
5684af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Negating a smi can give a negative zero or too large positive value.
5699d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  // NOTICE: This operation jumps on success, not failure!
5704af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiNeg(Register dst,
5714af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org              Register src,
57283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org              Label* on_smi_result,
57383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org              Label::Distance near_jump = Label::kFar);
5744af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
5754af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Adds smi values and return the result as a smi.
5764af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // If dst is src1, then src1 will be destroyed, even if
5774af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // the operation is unsuccessful.
5784af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiAdd(Register dst,
5794af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org              Register src1,
5804af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org              Register src2,
58183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org              Label* on_not_smi_result,
58283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org              Label::Distance near_jump = Label::kFar);
5837979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  void SmiAdd(Register dst,
5847979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org              Register src1,
5857979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org              const Operand& src2,
58683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org              Label* on_not_smi_result,
58783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org              Label::Distance near_jump = Label::kFar);
588c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org
589c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org  void SmiAdd(Register dst,
590c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org              Register src1,
591c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org              Register src2);
5924af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
5934af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Subtracts smi values and return the result as a smi.
5944af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // If dst is src1, then src1 will be destroyed, even if
5954af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // the operation is unsuccessful.
5964af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiSub(Register dst,
5974af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org              Register src1,
5984af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org              Register src2,
59983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org              Label* on_not_smi_result,
60083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org              Label::Distance near_jump = Label::kFar);
601c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org
602c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org  void SmiSub(Register dst,
603c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org              Register src1,
604c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org              Register src2);
6054af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
606ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  void SmiSub(Register dst,
607ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org              Register src1,
6089dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com              const Operand& src2,
60983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org              Label* on_not_smi_result,
61083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org              Label::Distance near_jump = Label::kFar);
611c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org
612c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org  void SmiSub(Register dst,
613c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org              Register src1,
614c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org              const Operand& src2);
615ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org
6164af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Multiplies smi values and return the result as a smi,
6174af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // if possible.
6184af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // If dst is src1, then src1 will be destroyed, even if
6194af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // the operation is unsuccessful.
6204af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiMul(Register dst,
6214af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org              Register src1,
6224af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org              Register src2,
62383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org              Label* on_not_smi_result,
62483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org              Label::Distance near_jump = Label::kFar);
6254af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
6264af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Divides one smi by another and returns the quotient.
6274af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Clobbers rax and rdx registers.
6284af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiDiv(Register dst,
6294af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org              Register src1,
6304af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org              Register src2,
63183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org              Label* on_not_smi_result,
63283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org              Label::Distance near_jump = Label::kFar);
6334af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
6344af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Divides one smi by another and returns the remainder.
6354af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Clobbers rax and rdx registers.
6364af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiMod(Register dst,
6374af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org              Register src1,
6384af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org              Register src2,
63983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org              Label* on_not_smi_result,
64083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org              Label::Distance near_jump = Label::kFar);
6414af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
6424af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Bitwise operations.
6434af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiNot(Register dst, Register src);
6444af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiAnd(Register dst, Register src1, Register src2);
6454af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiOr(Register dst, Register src1, Register src2);
6464af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiXor(Register dst, Register src1, Register src2);
6479d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void SmiAndConstant(Register dst, Register src1, Smi* constant);
6489d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void SmiOrConstant(Register dst, Register src1, Smi* constant);
6499d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void SmiXorConstant(Register dst, Register src1, Smi* constant);
6504af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
6514af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiShiftLeftConstant(Register dst,
6524af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                            Register src,
653720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org                            int shift_value);
6544af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiShiftLogicalRightConstant(Register dst,
6554af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                                  Register src,
6564af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                                  int shift_value,
65783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                  Label* on_not_smi_result,
65883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                  Label::Distance near_jump = Label::kFar);
6594af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiShiftArithmeticRightConstant(Register dst,
6604af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                                       Register src,
6614af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                                       int shift_value);
6624af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
6634af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Shifts a smi value to the left, and returns the result if that is a smi.
6644af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Uses and clobbers rcx, so dst may not be rcx.
6654af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiShiftLeft(Register dst,
6664af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                    Register src1,
667720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org                    Register src2);
6684af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Shifts a smi value to the right, shifting in zero bits at the top, and
6694af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // returns the unsigned intepretation of the result if that is a smi.
6704af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Uses and clobbers rcx, so dst may not be rcx.
6714af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiShiftLogicalRight(Register dst,
672c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org                            Register src1,
673c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org                            Register src2,
67483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                            Label* on_not_smi_result,
67583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                            Label::Distance near_jump = Label::kFar);
6764af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Shifts a smi value to the right, sign extending the top, and
6774af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // returns the signed intepretation of the result. That will always
6784af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // be a valid smi value, since it's numerically smaller than the
6794af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // original.
6804af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Uses and clobbers rcx, so dst may not be rcx.
6814af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiShiftArithmeticRight(Register dst,
6824af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                               Register src1,
6834af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                               Register src2);
6844af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
6854af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Specialized operations
6864af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
6874af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Select the non-smi register of two registers where exactly one is a
6884af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // smi. If neither are smis, jump to the failure label.
6894af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SelectNonSmi(Register dst,
6904af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                    Register src1,
6914af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                    Register src2,
69283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                    Label* on_not_smis,
69383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                    Label::Distance near_jump = Label::kFar);
6944af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
6954af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Converts, if necessary, a smi to a combination of number and
6964af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // multiplier to be used as a scaled index.
6974af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // The src register contains a *positive* smi value. The shift is the
6984af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // power of two to multiply the index value by (e.g.
6994af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // to index by smi-value * kPointerSize, pass the smi and kPointerSizeLog2).
7004af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // The returned index register may be either src or dst, depending
7014af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // on what is most efficient. If src and dst are different registers,
7024af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // src is always unchanged.
7034af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  SmiIndex SmiToIndex(Register dst, Register src, int shift);
7044af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
7054af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Converts a positive smi to a negative index.
7064af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  SmiIndex SmiToNegativeIndex(Register dst, Register src, int shift);
7074af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
7087979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Add the value of a smi in memory to an int32 register.
7097979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Sets flags as a normal add.
7107979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  void AddSmiField(Register dst, const Operand& src);
7117979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
7129d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  // Basic Smi operations.
7133811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  void Move(Register dst, Smi* source) {
71469ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    LoadSmiConstant(dst, source);
7153811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  }
7163811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
7173811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  void Move(const Operand& dst, Smi* source) {
71869ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    Register constant = GetSmiConstant(source);
71969ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    movq(dst, constant);
7203811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  }
7213811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
7229d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void Push(Smi* smi);
7239d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void Test(const Operand& dst, Smi* source);
7249d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
725394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
726eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // ---------------------------------------------------------------------------
727b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // String macros.
72883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org
72983aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  // If object is a string, its map is loaded into object_map.
73083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  void JumpIfNotString(Register object,
73183aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org                       Register object_map,
73283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                       Label* not_string,
73383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                       Label::Distance near_jump = Label::kFar);
73483aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org
73583aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org
73683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  void JumpIfNotBothSequentialAsciiStrings(
73783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      Register first_object,
73883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      Register second_object,
73983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      Register scratch1,
74083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      Register scratch2,
74183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      Label* on_not_both_flat_ascii,
74283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      Label::Distance near_jump = Label::kFar);
743b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
7442efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  // Check whether the instance type represents a flat ASCII string. Jump to the
745ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org  // label if not. If the instance type can be scratched specify same register
746ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org  // for both instance type and scratch.
747c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org  void JumpIfInstanceTypeIsNotSequentialAscii(
748c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org      Register instance_type,
749c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org      Register scratch,
75083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      Label*on_not_flat_ascii_string,
75183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      Label::Distance near_jump = Label::kFar);
752ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org
753ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org  void JumpIfBothInstanceTypesAreNotSequentialAscii(
754ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org      Register first_object_instance_type,
755ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org      Register second_object_instance_type,
756ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org      Register scratch1,
757ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org      Register scratch2,
75883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      Label* on_fail,
75983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      Label::Distance near_jump = Label::kFar);
760ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org
7611510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  // Checks if the given register or operand is a unique name
7621510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  void JumpIfNotUniqueName(Register reg, Label* not_unique_name,
7631510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org                           Label::Distance distance = Label::kFar);
7641510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  void JumpIfNotUniqueName(Operand operand, Label* not_unique_name,
7651510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org                           Label::Distance distance = Label::kFar);
7661510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
767b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // ---------------------------------------------------------------------------
76813bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  // Macro instructions.
769eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
7709d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  // Load a register with a long value as efficiently as possible.
771e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void Set(Register dst, int64_t x);
772e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void Set(const Operand& dst, int64_t x);
7739085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
7744a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  // Move if the registers are not identical.
7754a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  void Move(Register target, Register source);
7764a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
7777a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org  // Support for constant splitting.
7787a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org  bool IsUnsafeInt(const int x);
7797a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org  void SafeMove(Register dst, Smi* src);
7807a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org  void SafePush(Smi* src);
7817a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org
782394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Bit-field support.
783394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  void TestBit(const Operand& dst, int bit_index);
784394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
7855aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  // Handle support
7865aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  void Move(Register dst, Handle<Object> source);
7875aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  void Move(const Operand& dst, Handle<Object> source);
7885aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  void Cmp(Register dst, Handle<Object> source);
7893e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void Cmp(const Operand& dst, Handle<Object> source);
790badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  void Cmp(Register dst, Smi* src);
791badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  void Cmp(const Operand& dst, Smi* src);
7925aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  void Push(Handle<Object> source);
7930c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org
79464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // Load a heap object and handle the case of new-space objects by
79564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // indirecting via a global cell.
79664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  void LoadHeapObject(Register result, Handle<HeapObject> object);
797a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org  void CmpHeapObject(Register reg, Handle<HeapObject> object);
79864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  void PushHeapObject(Handle<HeapObject> object);
79964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
800bf0c820d028452571c8c744ddd212c32c6d6a996danno@chromium.org  void LoadObject(Register result, Handle<Object> object) {
80179e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org    AllowDeferredHandleDereference heap_object_check;
802bf0c820d028452571c8c744ddd212c32c6d6a996danno@chromium.org    if (object->IsHeapObject()) {
803bf0c820d028452571c8c744ddd212c32c6d6a996danno@chromium.org      LoadHeapObject(result, Handle<HeapObject>::cast(object));
804bf0c820d028452571c8c744ddd212c32c6d6a996danno@chromium.org    } else {
805bf0c820d028452571c8c744ddd212c32c6d6a996danno@chromium.org      Move(result, object);
806bf0c820d028452571c8c744ddd212c32c6d6a996danno@chromium.org    }
807bf0c820d028452571c8c744ddd212c32c6d6a996danno@chromium.org  }
808bf0c820d028452571c8c744ddd212c32c6d6a996danno@chromium.org
809a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org  void CmpObject(Register reg, Handle<Object> object) {
81079e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org    AllowDeferredHandleDereference heap_object_check;
811a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org    if (object->IsHeapObject()) {
812a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org      CmpHeapObject(reg, Handle<HeapObject>::cast(object));
813a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org    } else {
814a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org      Cmp(reg, object);
815a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org    }
816a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org  }
817a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org
81864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // Load a global cell into a register.
81941728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org  void LoadGlobalCell(Register dst, Handle<Cell> cell);
82064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
8210c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  // Emit code to discard a non-negative number of pointer-sized elements
8220c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  // from the stack, clobbering only the rsp register.
82313bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  void Drop(int stack_elements);
8240c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org
82513bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  void Call(Label* target) { call(target); }
826594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  void Push(Register src) { push(src); }
827594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  void Pop(Register dst) { pop(dst); }
828594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  void PushReturnAddressFrom(Register src) { push(src); }
829594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  void PopReturnAddressTo(Register dst) { pop(dst); }
8305aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
831eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // Control Flow
832eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void Jump(Address destination, RelocInfo::Mode rmode);
833eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void Jump(ExternalReference ext);
8345aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  void Jump(Handle<Code> code_object, RelocInfo::Mode rmode);
8355aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
836eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void Call(Address destination, RelocInfo::Mode rmode);
837eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void Call(ExternalReference ext);
8388e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  void Call(Handle<Code> code_object,
8398e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org            RelocInfo::Mode rmode,
840471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org            TypeFeedbackId ast_id = TypeFeedbackId::None());
841eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
842eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org  // The size of the code generated for different call instructions.
843eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org  int CallSize(Address destination, RelocInfo::Mode rmode) {
844594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    return kCallSequenceLength;
845eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org  }
846ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  int CallSize(ExternalReference ext);
847eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org  int CallSize(Handle<Code> code_object) {
848eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org    // Code calls use 32-bit relative addressing.
849eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org    return kShortCallInstructionLength;
850eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org  }
851eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org  int CallSize(Register target) {
852eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org    // Opcode: REX_opt FF /2 m64
853eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org    return (target.high_bit() != 0) ? 3 : 2;
854eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org  }
855eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org  int CallSize(const Operand& target) {
856eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org    // Opcode: REX_opt FF /2 m64
857eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org    return (target.requires_rex() ? 2 : 1) + target.operand_size();
858eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org  }
859eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org
86083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  // Emit call to the code we are currently generating.
86183aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  void CallSelf() {
86283aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org    Handle<Code> self(reinterpret_cast<Code**>(CodeObject().location()));
86383aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org    Call(self, RelocInfo::CODE_TARGET);
86483aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  }
86583aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org
8660a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  // Non-x64 instructions.
8670a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  // Push/pop all general purpose registers.
8680a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  // Does not push rsp/rbp nor any of the assembler's special purpose registers
8690a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  // (kScratchRegister, kSmiConstantRegister, kRootRegister).
8700a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  void Pushad();
8710a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  void Popad();
8720ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  // Sets the stack as after performing Popad, without actually loading the
8730ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  // registers.
8740ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  void Dropad();
8750a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
8769085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Compare object type for heap object.
877e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  // Always use unsigned comparisons: above and below, not less and greater.
8789085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Incoming register is heap_object and outgoing register is map.
87986f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  // They may be the same register, and may be kScratchRegister.
8809085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void CmpObjectType(Register heap_object, InstanceType type, Register map);
8819085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
8829085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Compare instance type for map.
883e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  // Always use unsigned comparisons: above and below, not less and greater.
8849085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void CmpInstanceType(Register map, InstanceType type);
8859085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
886d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com  // Check if a map for a JSObject indicates that the object has fast elements.
887d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com  // Jump to the specified label if it does not.
888d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com  void CheckFastElements(Register map,
889d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com                         Label* fail,
890d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com                         Label::Distance distance = Label::kFar);
891d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com
892c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Check if a map for a JSObject indicates that the object can have both smi
893c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // and HeapObject elements.  Jump to the specified label if it does not.
894c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void CheckFastObjectElements(Register map,
895c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                               Label* fail,
896c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                               Label::Distance distance = Label::kFar);
897c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
898c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Check if a map for a JSObject indicates that the object has fast smi only
899c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // elements.  Jump to the specified label if it does not.
900830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org  void CheckFastSmiElements(Register map,
901830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org                            Label* fail,
902830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org                            Label::Distance distance = Label::kFar);
903c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
904c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Check to see if maybe_number can be stored as a double in
905394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // FastDoubleElements. If it can, store it at the index specified by index in
906394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // the FastDoubleElements array elements, otherwise jump to fail.  Note that
907394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // index must not be smi-tagged.
908c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void StoreNumberToDoubleElements(Register maybe_number,
909c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                   Register elements,
910394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                   Register index,
911c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                   XMMRegister xmm_scratch,
912fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                   Label* fail,
913fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                   int elements_offset = 0);
914c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
915f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // Compare an object's map with the specified map and its transitioned
916f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // elements maps if mode is ALLOW_ELEMENT_TRANSITION_MAPS. FLAGS are set with
917f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // result of map compare. If multiple map compares are required, the compare
918f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // sequences branches to early_success.
919f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  void CompareMap(Register obj,
920f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com                  Handle<Map> map,
921a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org                  Label* early_success);
922f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com
923f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // Check if the map of an object is equal to a specified map and branch to
924f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // label if not. Skip the smi check if not required (object is known to be a
925f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match
9262efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  // against maps that are ElementsKind transition maps of the specified map.
9275c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void CheckMap(Register obj,
9285c838251403b0be9a882540f1922577abba4c872ager@chromium.org                Handle<Map> map,
9295c838251403b0be9a882540f1922577abba4c872ager@chromium.org                Label* fail,
930a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org                SmiCheckType smi_check_type);
9315c838251403b0be9a882540f1922577abba4c872ager@chromium.org
932ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org  // Check if the map of an object is equal to a specified map and branch to a
933ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org  // specified target if equal. Skip the smi check if not required (object is
934ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org  // known to be a heap object)
935ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org  void DispatchMap(Register obj,
9362bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org                   Register unused,
937ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org                   Handle<Map> map,
938ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org                   Handle<Code> success,
939ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org                   SmiCheckType smi_check_type);
940ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org
941b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Check if the object in register heap_object is a string. Afterwards the
942b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // register map contains the object map and the register instance_type
943b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // contains the instance_type. The registers map and instance_type can be the
944b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // same in which case it contains the instance type afterwards. Either of the
945b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // registers map and instance_type can be the same as heap_object.
946b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  Condition IsObjectStringType(Register heap_object,
947b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org                               Register map,
948b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org                               Register instance_type);
949b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
950750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  // Check if the object in register heap_object is a name. Afterwards the
951750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  // register map contains the object map and the register instance_type
952750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  // contains the instance_type. The registers map and instance_type can be the
953750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  // same in which case it contains the instance type afterwards. Either of the
954750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  // registers map and instance_type can be the same as heap_object.
955750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  Condition IsObjectNameType(Register heap_object,
956750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                             Register map,
957750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                             Register instance_type);
958750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org
95940b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  // FCmp compares and pops the two values on top of the FPU stack.
96040b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  // The flag results are similar to integer cmp, but requires unsigned
9619085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // jcc instructions (je, ja, jae, jb, jbe, je, and jz).
9629085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void FCmp();
9639085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
964c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  void ClampUint8(Register reg);
965c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
966c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  void ClampDoubleToUint8(XMMRegister input_reg,
967c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                          XMMRegister temp_xmm_reg,
96889e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org                          Register result_reg);
969c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
97046839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  void LoadUint32(XMMRegister dst, Register src, XMMRegister scratch);
97146839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org
97240cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  void LoadInstanceDescriptors(Register map, Register descriptors);
973355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  void EnumLength(Register dst, Register map);
97406ab2ec756e44eeaf7500b9794f9d2abc79dc8cfverwaest@chromium.org  void NumberOfOwnDescriptors(Register dst, Register map);
975355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org
976355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  template<typename Field>
977355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  void DecodeField(Register reg) {
97806ab2ec756e44eeaf7500b9794f9d2abc79dc8cfverwaest@chromium.org    static const int shift = Field::kShift + kSmiShift;
97906ab2ec756e44eeaf7500b9794f9d2abc79dc8cfverwaest@chromium.org    static const int mask = Field::kMask >> Field::kShift;
98006ab2ec756e44eeaf7500b9794f9d2abc79dc8cfverwaest@chromium.org    shr(reg, Immediate(shift));
98106ab2ec756e44eeaf7500b9794f9d2abc79dc8cfverwaest@chromium.org    and_(reg, Immediate(mask));
98206ab2ec756e44eeaf7500b9794f9d2abc79dc8cfverwaest@chromium.org    shl(reg, Immediate(kSmiShift));
983355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  }
98440cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org
985c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  // Abort execution if argument is not a number, enabled via --debug-code.
986c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  void AssertNumber(Register object);
9875c838251403b0be9a882540f1922577abba4c872ager@chromium.org
988c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  // Abort execution if argument is a smi, enabled via --debug-code.
989c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  void AssertNotSmi(Register object);
990ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org
991c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  // Abort execution if argument is not a smi, enabled via --debug-code.
992c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  void AssertSmi(Register object);
993c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  void AssertSmi(const Operand& object);
99425156ded31ef771a2d799ed902483d83b3ebcbdclrn@chromium.org
995f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  // Abort execution if a 64 bit register containing a 32 bit payload does not
996c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  // have zeros in the top 32 bits, enabled via --debug-code.
997c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  void AssertZeroExtended(Register reg);
998f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
999c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  // Abort execution if argument is not a string, enabled via --debug-code.
1000c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  void AssertString(Register object);
100149edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
1002750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  // Abort execution if argument is not a name, enabled via --debug-code.
1003750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  void AssertName(Register object);
1004750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org
1005c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  // Abort execution if argument is not the root value with the given index,
1006c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  // enabled via --debug-code.
1007c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  void AssertRootValue(Register src,
1008c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org                       Heap::RootListIndex root_value_index,
1009594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org                       BailoutReason reason);
10105ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org
10119085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // ---------------------------------------------------------------------------
10129085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Exception handling
10139085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
101404e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // Push a new try handler and link it into try handler chain.
101578d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org  void PushTryHandler(StackHandler::Kind kind, int handler_index);
10169085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
101713bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  // Unlink the stack handler on top of the stack from the try handler chain.
101813bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  void PopTryHandler();
10199085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
102049edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  // Activate the top handler in the try hander chain and pass the
102149edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  // thrown value.
102249edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  void Throw(Register value);
102349edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
102449edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  // Propagate an uncatchable exception out of the current JS stack.
102565a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  void ThrowUncatchable(Register value);
102649edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
10279085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // ---------------------------------------------------------------------------
10289085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Inline caching support
10299085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
10309085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Generate code for checking access rights - used for security checks
10319085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // on access to global objects across environments. The holder register
1032e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  // is left untouched, but the scratch register and kScratchRegister,
1033e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  // which must be different, are clobbered.
10349085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void CheckAccessGlobalProxy(Register holder_reg,
10359085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org                              Register scratch,
10369085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org                              Label* miss);
10379085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1038f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  void GetNumberHash(Register r0, Register scratch);
10399085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
10406db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  void LoadFromNumberDictionary(Label* miss,
10416db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org                                Register elements,
10426db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org                                Register key,
10436db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org                                Register r0,
10446db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org                                Register r1,
10456db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org                                Register r2,
10466db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org                                Register result);
10476db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
10486db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
10499085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // ---------------------------------------------------------------------------
105018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Allocation support
105118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
10522bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  // Allocate an object in new space or old pointer space. If the given space
10532bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  // is exhausted control continues at the gc_required label. The allocated
10542bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  // object is returned in result and end of the new object is returned in
10552bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  // result_end. The register scratch can be passed as no_reg in which case
10562bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  // an additional object reference will be added to the reloc info. The
10572bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  // returned pointers in result and result_end have not yet been tagged as
10582bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  // heap objects. If result_contains_top_on_entry is true the content of
10592bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  // result is known to be the allocation top on entry (could be result_end
10602bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  // from a previous call). If result_contains_top_on_entry is true scratch
106118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // should be no_reg as it is never used.
10622bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  void Allocate(int object_size,
10632bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org                Register result,
10642bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org                Register result_end,
10652bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org                Register scratch,
10662bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org                Label* gc_required,
10672bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org                AllocationFlags flags);
1068c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org
1069f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  void Allocate(int header_size,
1070f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                ScaleFactor element_size,
1071f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                Register element_count,
1072f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                Register result,
1073f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                Register result_end,
1074f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                Register scratch,
1075f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                Label* gc_required,
1076f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                AllocationFlags flags);
1077f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org
1078f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  void Allocate(Register object_size,
1079f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                Register result,
1080f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                Register result_end,
1081f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                Register scratch,
1082f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                Label* gc_required,
1083f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                AllocationFlags flags);
108418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
108518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Undo allocation in new space. The object passed and objects allocated after
108618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // it will no longer be allocated. Make sure that no pointers are left to the
108718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // object(s) no longer allocated as they would be invalid when allocation is
108818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // un-done.
108918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  void UndoAllocationInNewSpace(Register object);
109018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
10913811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  // Allocate a heap number in new space with undefined value. Returns
10923811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  // tagged pointer in result register, or jumps to gc_required if new
10933811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  // space is full.
10943811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  void AllocateHeapNumber(Register result,
10953811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org                          Register scratch,
10963811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org                          Label* gc_required);
10973811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
109813bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  // Allocate a sequential string. All the header fields of the string object
109913bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  // are initialized.
110013bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  void AllocateTwoByteString(Register result,
110113bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                             Register length,
110213bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                             Register scratch1,
110313bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                             Register scratch2,
110413bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                             Register scratch3,
110513bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                             Label* gc_required);
110613bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  void AllocateAsciiString(Register result,
110713bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                           Register length,
110813bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                           Register scratch1,
110913bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                           Register scratch2,
111013bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                           Register scratch3,
111113bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                           Label* gc_required);
111213bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org
111313bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  // Allocate a raw cons string object. Only the map field of the result is
111413bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  // initialized.
11151805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  void AllocateTwoByteConsString(Register result,
111613bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                          Register scratch1,
111713bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                          Register scratch2,
111813bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                          Label* gc_required);
111913bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  void AllocateAsciiConsString(Register result,
112013bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                               Register scratch1,
112113bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                               Register scratch2,
112213bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                               Label* gc_required);
112313bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org
11241805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  // Allocate a raw sliced string object. Only the map field of the result is
11251805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  // initialized.
11261805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  void AllocateTwoByteSlicedString(Register result,
11271805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org                            Register scratch1,
11281805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org                            Register scratch2,
11291805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org                            Label* gc_required);
11301805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  void AllocateAsciiSlicedString(Register result,
11311805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org                                 Register scratch1,
11321805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org                                 Register scratch2,
11331805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org                                 Label* gc_required);
11341805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
113518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // ---------------------------------------------------------------------------
11369085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Support functions.
11379085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
11389085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Check if result is zero and op is negative.
11399085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void NegativeZeroTest(Register result, Register op, Label* then_label);
11409085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
11419085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Check if result is zero and op is negative in code using jump targets.
11429085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void NegativeZeroTest(CodeGenerator* cgen,
11439085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org                        Register result,
11449085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org                        Register op,
11459085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org                        JumpTarget* then_target);
11469085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
11479085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Check if result is zero and any of op1 and op2 are negative.
11489085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Register scratch is destroyed, and it must be different from op2.
11499085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void NegativeZeroTest(Register result, Register op1, Register op2,
11509085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org                        Register scratch, Label* then_label);
11519085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
11529085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Try to get function prototype of a function and puts the value in
11539085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // the result register. Checks that the function really is a
11549085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // function and jumps to the miss label if the fast checks fail. The
115586f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  // function register will be untouched; the other register may be
11569085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // clobbered.
11579085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void TryGetFunctionPrototype(Register function,
11589085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org                               Register result,
1159394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                               Label* miss,
1160394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                               bool miss_on_bound_function = false);
11619085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
11629085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Generates code for reporting that an illegal operation has
11639085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // occurred.
11649085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void IllegalOperation(int num_arguments);
11659085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1166d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  // Picks out an array index from the hash field.
1167d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  // Register use:
1168d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  //   hash - holds the index's hash. Clobbered.
1169d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  //   index - holds the overwritten index on exit.
1170d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  void IndexFromHash(Register hash, Register index);
1171d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org
1172ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org  // Find the function context up the context chain.
1173ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org  void LoadContext(Register dst, int context_chain_length);
1174ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org
11751145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org  // Conditionally load the cached Array transitioned map of type
117646839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  // transitioned_kind from the native context if the map in register
117746839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  // map_in_out is the cached Array map in the native context of
11781145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org  // expected_kind.
11791145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org  void LoadTransitionedArrayMapConditional(
11801145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org      ElementsKind expected_kind,
11811145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org      ElementsKind transitioned_kind,
11821145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org      Register map_in_out,
11831145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org      Register scratch,
11841145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org      Label* no_map_match);
11851145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org
11861145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org  // Load the initial map for new Arrays from a JSFunction.
11871145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org  void LoadInitialArrayMap(Register function_in,
11881145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org                           Register scratch,
1189830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org                           Register map_out,
1190830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org                           bool can_have_holes);
1191fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org
11925f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  // Load the global function with the given index.
11935f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  void LoadGlobalFunction(int index, Register function);
11944a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  void LoadArrayFunction(Register function);
11955f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org
11965f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  // Load the initial map from the global function. The registers
11975f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  // function and map can be the same.
11985f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  void LoadGlobalFunctionInitialMap(Register function, Register map);
11995f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org
12009085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // ---------------------------------------------------------------------------
12019085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Runtime calls
12029085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
12039085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Call a code stub.
1204471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org  void CallStub(CodeStub* stub, TypeFeedbackId ast_id = TypeFeedbackId::None());
12059085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
120613bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  // Tail call a code stub (jump).
120713bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  void TailCallStub(CodeStub* stub);
120813bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org
12099085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Return from a code stub after popping its arguments.
12109085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void StubReturn(int argc);
12119085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
12129085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Call a runtime routine.
1213ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  void CallRuntime(const Runtime::Function* f, int num_arguments);
12149085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
12150ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  // Call a runtime function and save the value of XMM registers.
12160ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  void CallRuntimeSaveDoubles(Runtime::FunctionId id);
12170ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org
12189085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Convenience function: Same as above, but takes the fid instead.
12199085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void CallRuntime(Runtime::FunctionId id, int num_arguments);
12209085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
12215c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Convenience function: call an external reference.
12225c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void CallExternalReference(const ExternalReference& ext,
12235c838251403b0be9a882540f1922577abba4c872ager@chromium.org                             int num_arguments);
12245c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12259085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Tail call of a runtime routine (jump).
1226ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org  // Like JumpToExternalReference, but also takes care of passing the number
1227ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org  // of parameters.
1228ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org  void TailCallExternalReference(const ExternalReference& ext,
1229ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org                                 int num_arguments,
1230ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org                                 int result_size);
1231ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org
1232ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org  // Convenience function: tail call a runtime routine (jump).
1233ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org  void TailCallRuntime(Runtime::FunctionId fid,
1234a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org                       int num_arguments,
1235a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org                       int result_size);
12369085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1237c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // Jump to a runtime routine.
1238ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org  void JumpToExternalReference(const ExternalReference& ext, int result_size);
12399085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1240c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // Prepares stack to put arguments (aligns and so on).  WIN64 calling
1241c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // convention requires to put the pointer to the return value slot into
1242c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // rcx (rcx must be preserverd until CallApiFunctionAndReturn).  Saves
1243c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // context (rsi).  Clobbers rax.  Allocates arg_stack_space * kPointerSize
12444a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  // inside the exit frame (not GCed) accessible via StackSpaceOperand.
1245bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  void PrepareCallApiFunction(int arg_stack_space, bool returns_handle);
12464a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com
1247c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // Calls an API function.  Allocates HandleScope, extracts returned value
1248c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // from handle and propagates exceptions.  Clobbers r14, r15, rbx and
1249c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // caller-save registers.  Restores context.  On return removes
1250c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // stack_space * kPointerSize (GCed).
1251bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  void CallApiFunctionAndReturn(Address function_address,
1252b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org                                Address thunk_address,
1253b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org                                Register thunk_last_arg,
1254bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org                                int stack_space,
1255bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org                                bool returns_handle,
1256bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org                                int return_value_offset_from_rbp);
1257303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org
1258b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Before calling a C-function from generated code, align arguments on stack.
1259c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org  // After aligning the frame, arguments must be stored in rsp[0], rsp[8],
1260b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // etc., not pushed. The argument count assumes all arguments are word sized.
1261b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // The number of slots reserved for arguments depends on platform. On Windows
1262b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // stack slots are reserved for the arguments passed in registers. On other
1263b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // platforms stack slots are only reserved for the arguments actually passed
1264b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // on the stack.
1265b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void PrepareCallCFunction(int num_arguments);
1266b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
1267b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Calls a C function and cleans up the space for arguments allocated
1268b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // by PrepareCallCFunction. The called function is not allowed to trigger a
1269b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // garbage collection, since that might move the code and invalidate the
1270b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // return address (unless this is somehow accounted for by the called
1271b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // function).
1272b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void CallCFunction(ExternalReference function, int num_arguments);
1273b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void CallCFunction(Register function, int num_arguments);
1274b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
1275b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Calculate the number of stack slots to reserve for arguments when calling a
1276b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // C function.
1277b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  int ArgumentStackSlotsForCFunctionCall(int num_arguments);
12789085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
12799085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // ---------------------------------------------------------------------------
12809085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Utilities
12819085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
12829085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void Ret();
12839085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1284d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  // Return and drop arguments from stack, where the number of arguments
1285d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  // may be bigger than 2^16 - 1.  Requires a scratch register.
1286d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  void Ret(int bytes_dropped, Register scratch);
1287d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com
1288c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  Handle<Object> CodeObject() {
1289c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org    ASSERT(!code_object_.is_null());
1290c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org    return code_object_;
1291c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  }
12929085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
12937979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Copy length bytes from source to destination.
12947979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Uses scratch register internally (if you have a low-eight register
12957979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // free, do use it, otherwise kScratchRegister will be used).
12967979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // The min_length is a minimum limit on the value that length will have.
12977979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // The algorithm has some special cases that might be omitted if the string
12987979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // is known to always be long.
12997979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  void CopyBytes(Register destination,
13007979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org                 Register source,
13017979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org                 Register length,
13027979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org                 int min_length = 0,
13037979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org                 Register scratch = kScratchRegister);
13047979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
1305c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Initialize fields with filler values.  Fields starting at |start_offset|
1306c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // not including end_offset are overwritten with the value in |filler|.  At
1307c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // the end the loop, |start_offset| takes the value of |end_offset|.
1308c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void InitializeFieldsWithFiller(Register start_offset,
1309c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                  Register end_offset,
1310c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                  Register filler);
1311c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
13129085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
13139085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // ---------------------------------------------------------------------------
13149085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // StatsCounter support
13159085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
13169085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void SetCounter(StatsCounter* counter, int value);
13179085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void IncrementCounter(StatsCounter* counter, int value);
13189085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void DecrementCounter(StatsCounter* counter, int value);
13199085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
13209085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
13219085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // ---------------------------------------------------------------------------
13229085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Debugging
13239085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
13249085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Calls Abort(msg) if the condition cc is not satisfied.
13259085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Use --debug_code to enable.
1326594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  void Assert(Condition cc, BailoutReason reason);
13279085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
13280b9f850f0e9dc624b9e0c5254393112ecc7f8bc9ricow@chromium.org  void AssertFastElements(Register elements);
13290b9f850f0e9dc624b9e0c5254393112ecc7f8bc9ricow@chromium.org
13309085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Like Assert(), but always enabled.
1331594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  void Check(Condition cc, BailoutReason reason);
13329085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
13339085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Print a message to stdout and abort execution.
1334594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  void Abort(BailoutReason msg);
13359085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1336c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org  // Check that the stack is aligned.
1337c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org  void CheckStackAlignment();
1338c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org
13399085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Verify restrictions about code generated in stubs.
13409085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void set_generating_stub(bool value) { generating_stub_ = value; }
13419085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  bool generating_stub() { return generating_stub_; }
13429085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; }
13439085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  bool allow_stub_calls() { return allow_stub_calls_; }
1344c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void set_has_frame(bool value) { has_frame_ = value; }
1345c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  bool has_frame() { return has_frame_; }
1346c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  inline bool AllowThisStubCall(CodeStub* stub);
13479085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
134844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  static int SafepointRegisterStackIndex(Register reg) {
134944bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    return SafepointRegisterStackIndex(reg.code());
135044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  }
135144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
1352c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Activation support.
1353c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void EnterFrame(StackFrame::Type type);
1354c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void LeaveFrame(StackFrame::Type type);
1355c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1356be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.org  // Expects object in rax and returns map with validated enum cache
1357be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.org  // in rax.  Assumes that any other register can be used as a scratch.
1358be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.org  void CheckEnumCache(Register null_value,
1359be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.org                      Label* call_runtime);
1360be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.org
1361ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // AllocationMemento support. Arrays may have an associated
1362ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // AllocationMemento object that can be checked for in order to pretransition
136359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  // to another type.
136459297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  // On entry, receiver_reg should point to the array object.
136559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  // scratch_reg gets clobbered.
136694b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org  // If allocation info is present, condition flags are set to equal
1367ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  void TestJSArrayForAllocationMemento(Register receiver_reg,
1368ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org                                       Register scratch_reg);
136959297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org
13709085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org private:
13710ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  // Order general registers are pushed by Pushad.
1372b08986cb66c3f6687247cb6da186c1e73057e399whesse@chromium.org  // rax, rcx, rdx, rbx, rsi, rdi, r8, r9, r11, r14, r15.
13731456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  static const int kSafepointPushRegisterIndices[Register::kNumRegisters];
137449edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  static const int kNumSafepointSavedRegisters = 11;
137583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static const int kSmiShift = kSmiTagSize + kSmiShiftSize;
137649edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
13779085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  bool generating_stub_;
13789085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  bool allow_stub_calls_;
1379c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  bool has_frame_;
1380ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  bool root_array_available_;
138169ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org
138269ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  // Returns a register holding the smi value. The register MUST NOT be
138369ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  // modified. It may be the "smi 1 constant" register.
138469ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  Register GetSmiConstant(Smi* value);
138569ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org
1386000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.org  intptr_t RootRegisterDelta(ExternalReference other);
1387000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.org
138869ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  // Moves the smi value to the destination register.
138969ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  void LoadSmiConstant(Register dst, Smi* value);
139069ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org
13915c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // This handle will be patched with the code object on installation.
13925c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Handle<Object> code_object_;
13939085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
13949085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Helper functions for generating invokes.
13959085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void InvokePrologue(const ParameterCount& expected,
13969085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org                      const ParameterCount& actual,
13979085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org                      Handle<Code> code_constant,
1398eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org                      Register code_register,
139983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                      Label* done,
14002efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org                      bool* definitely_mismatches,
14013a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                      InvokeFlag flag,
140240cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org                      Label::Distance near_jump = Label::kFar,
140340cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org                      const CallWrapper& call_wrapper = NullCallWrapper(),
140440cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org                      CallKind call_kind = CALL_AS_METHOD);
14059085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1406d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  void EnterExitFramePrologue(bool save_rax);
14074a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com
14084a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  // Allocates arg_stack_space * kPointerSize memory (not GCed) on the stack
14094a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  // accessible via StackSpaceOperand.
14100ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  void EnterExitFrameEpilogue(int arg_stack_space, bool save_doubles);
14114a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com
14124a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  void LeaveExitFrameEpilogue();
1413e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org
141418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Allocation support helpers.
1415ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  // Loads the top of new-space into the result register.
1416ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  // Otherwise the address of the new-space top is loaded into scratch (if
1417ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  // scratch is valid), and the new-space top is loaded into result.
141818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  void LoadAllocationTopHelper(Register result,
141918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org                               Register scratch,
1420a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org                               AllocationFlags flags);
14212bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org
1422ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  // Update allocation top with value in result_end register.
1423ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  // If scratch is valid, it contains the address of the allocation top.
14242bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  void UpdateAllocationTopHelper(Register result_end,
14252bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org                                 Register scratch,
14262bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org                                 AllocationFlags flags);
1427e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org
1428e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org  // Helper for PopHandleScope.  Allowed to perform a GC and returns
1429e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org  // NULL if gc_allowed.  Does not perform a GC if !gc_allowed, and
1430e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org  // possibly returns a failure object indicating an allocation failure.
1431e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org  Object* PopHandleScopeHelper(Register saved,
1432e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org                               Register scratch,
1433e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org                               bool gc_allowed);
14343a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
1435c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Helper for implementing JumpIfNotInNewSpace and JumpIfInNewSpace.
1436c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void InNewSpace(Register object,
1437c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                  Register scratch,
1438c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                  Condition cc,
1439c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                  Label* branch,
1440c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                  Label::Distance distance = Label::kFar);
1441c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1442c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Helper for finding the mark bits for an address.  Afterwards, the
1443c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // bitmap register points at the word with the mark bits and the mask
1444c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // the position of the first bit.  Uses rcx as scratch and leaves addr_reg
1445c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // unchanged.
1446c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  inline void GetMarkBits(Register addr_reg,
1447c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                          Register bitmap_reg,
1448c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                          Register mask_reg);
14493a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
145004e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // Helper for throwing exceptions.  Compute a handler address and jump to
145104e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // it.  See the implementation for register usage.
145204e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  void JumpToHandlerEntry();
145304e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org
14543a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // Compute memory operands for safepoint stack slots.
14553a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  Operand SafepointRegisterSlot(Register reg);
14563a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  static int SafepointRegisterStackIndex(int reg_code) {
14573a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    return kNumSafepointRegisters - kSafepointPushRegisterIndices[reg_code] - 1;
14583a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  }
14593a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
1460a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // Needs access to SafepointRegisterStackIndex for compiled frame
14613a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // traversal.
1462a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  friend class StandardFrame;
14639085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org};
14649085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
14659085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
14664af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org// The code patcher is used to patch (typically) small parts of code e.g. for
14674af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org// debugging and other types of instrumentation. When using the code patcher
14684af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org// the exact number of bytes specified must be emitted. Is not legal to emit
14694af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org// relocation information. If any of these constraints are violated it causes
14704af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org// an assertion.
14714af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.orgclass CodePatcher {
14724af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org public:
14734af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  CodePatcher(byte* address, int size);
14744af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  virtual ~CodePatcher();
14754af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
14764af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Macro assembler to emit code.
14774af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  MacroAssembler* masm() { return &masm_; }
14784af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
14794af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org private:
14804af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  byte* address_;  // The address of the code being patched.
14814af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  int size_;  // Number of bytes of the expected patch size.
14824af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  MacroAssembler masm_;  // Macro assembler used to generate the code.
14834af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org};
14844af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
14854af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
14869085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// -----------------------------------------------------------------------------
14879085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// Static helper functions.
14889085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
14899085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// Generate an Operand for loading a field from an object.
14901b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.orginline Operand FieldOperand(Register object, int offset) {
14919085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  return Operand(object, offset - kHeapObjectTag);
14929085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org}
14939085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
14949085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
14959085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// Generate an Operand for loading an indexed field from an object.
14961b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.orginline Operand FieldOperand(Register object,
14971b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org                            Register index,
14981b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org                            ScaleFactor scale,
14991b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org                            int offset) {
15009085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  return Operand(object, index, scale, offset - kHeapObjectTag);
15019085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org}
15029085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
15039085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
15041b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.orginline Operand ContextOperand(Register context, int index) {
15054a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  return Operand(context, Context::SlotOffset(index));
15064a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com}
15074a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com
15084a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com
15091b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.orginline Operand GlobalObjectOperand() {
151046839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  return ContextOperand(rsi, Context::GLOBAL_OBJECT_INDEX);
15114a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com}
15124a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com
15134a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com
15144a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com// Provides access to exit frame stack space (not GCed).
15151b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.orginline Operand StackSpaceOperand(int index) {
15164a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com#ifdef _WIN64
15174a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  const int kShaddowSpace = 4;
15184a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  return Operand(rsp, (index + kShaddowSpace) * kPointerSize);
15194a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com#else
15204a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  return Operand(rsp, index * kPointerSize);
15214a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com#endif
15224a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com}
15234a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com
15244a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com
1525d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.orginline Operand StackOperandForReturnAddress(int32_t disp) {
1526d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org  return Operand(rsp, disp);
1527d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org}
1528d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org
15294a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com
15309085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#ifdef GENERATED_CODE_COVERAGE
15319085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgextern void LogGeneratedCodeCoverage(const char* file_line);
15329085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#define CODE_COVERAGE_STRINGIFY(x) #x
15339085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x)
15349085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__)
15354cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org#define ACCESS_MASM(masm) {                                                  \
15364cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org    Address x64_coverage_function = FUNCTION_ADDR(LogGeneratedCodeCoverage); \
15374cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org    masm->pushfq();                                                          \
15384cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org    masm->Pushad();                                                          \
15394cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org    masm->push(Immediate(reinterpret_cast<int>(&__FILE_LINE__)));            \
15404cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org    masm->Call(x64_coverage_function, RelocInfo::EXTERNAL_REFERENCE);        \
15414cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org    masm->pop(rax);                                                          \
15424cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org    masm->Popad();                                                           \
15434cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org    masm->popfq();                                                           \
15444cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org  }                                                                          \
15459085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  masm->
15469085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#else
15479085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#define ACCESS_MASM(masm) masm->
15489085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#endif
15499085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
15509085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org} }  // namespace v8::internal
15519085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
15529085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#endif  // V8_X64_MACRO_ASSEMBLER_X64_H_
1553