1f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com// Copyright 2012 the V8 project authors. All rights reserved.
23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be
33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file.
45ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org
59085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#ifndef V8_X64_MACRO_ASSEMBLER_X64_H_
69085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#define V8_X64_MACRO_ASSEMBLER_X64_H_
79085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
8196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/assembler.h"
9b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org#include "src/bailout-reason.h"
10196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/frames.h"
11196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/globals.h"
129085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1371affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgnamespace v8 {
1471affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgnamespace internal {
159085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
16e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org// Default scratch register used by MacroAssembler (and other code that needs
17e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org// a spare register). The register isn't callee save, and not used by the
18e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org// function calling convention.
191b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.orgconst Register kScratchRegister = { 10 };      // r10.
201b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.orgconst Register kSmiConstantRegister = { 12 };  // r12 (callee save).
211b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.orgconst Register kRootRegister = { 13 };         // r13 (callee save).
2269ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org// Value of smi in kSmiConstantRegister.
231b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.orgconst int kSmiConstantRegisterValue = 1;
248f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org// Actual value of root register is offset from the root array's start
258f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org// to take advantage of negitive 8-bit displacement values.
261b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.orgconst int kRootRegisterBias = 128;
27e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
280c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org// Convenience for platform-independent signatures.
290c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.orgtypedef Operand MemOperand;
300c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org
31c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comenum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET };
32c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comenum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK };
33196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.orgenum PointersToHereCheck {
34196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org  kPointersToHereMaybeInteresting,
35196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org  kPointersToHereAreAlwaysInteresting
36196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org};
37c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
38e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.orgenum SmiOperationConstraint {
39e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  PRESERVE_SOURCE_REGISTER,
40e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  BAILOUT_ON_NO_OVERFLOW,
41e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  BAILOUT_ON_OVERFLOW,
42e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  NUMBER_OF_CONSTRAINTS
43e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org};
44e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org
45e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.orgSTATIC_ASSERT(NUMBER_OF_CONSTRAINTS <= 8);
46e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org
47e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.orgclass SmiOperationExecutionMode : public EnumSet<SmiOperationConstraint, byte> {
48e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org public:
49e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  SmiOperationExecutionMode() : EnumSet<SmiOperationConstraint, byte>(0) { }
50e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  explicit SmiOperationExecutionMode(byte bits)
51e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org      : EnumSet<SmiOperationConstraint, byte>(bits) { }
52e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org};
53e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org
549bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org#ifdef DEBUG
559bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.orgbool AreAliased(Register reg1,
569bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org                Register reg2,
579bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org                Register reg3 = no_reg,
589bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org                Register reg4 = no_reg,
599bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org                Register reg5 = no_reg,
609bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org                Register reg6 = no_reg,
619bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org                Register reg7 = no_reg,
629bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org                Register reg8 = no_reg);
639bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org#endif
64c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
659085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// Forward declaration.
669085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgclass JumpTarget;
679085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
684af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.orgstruct SmiIndex {
694af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  SmiIndex(Register index_register, ScaleFactor scale)
704af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org      : reg(index_register),
714af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org        scale(scale) {}
724af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  Register reg;
734af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  ScaleFactor scale;
744af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org};
759085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
76c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
779085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// MacroAssembler implements a collection of frequently used macros.
789085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgclass MacroAssembler: public Assembler {
799085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org public:
80c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  // The isolate parameter can be NULL if the macro assembler should
81c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  // not use isolate-dependent functionality. In this case, it's the
82c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  // responsibility of the caller to never invoke such function on the
83c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  // macro assembler.
84c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  MacroAssembler(Isolate* isolate, void* buffer, int size);
859085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
86ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // Prevent the use of the RootArray during the lifetime of this
87ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // scope object.
88ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  class NoRootArrayScope BASE_EMBEDDED {
89ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org   public:
90ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    explicit NoRootArrayScope(MacroAssembler* assembler)
91ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org        : variable_(&assembler->root_array_available_),
92ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org          old_value_(assembler->root_array_available_) {
93ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      assembler->root_array_available_ = false;
94ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    }
95ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    ~NoRootArrayScope() {
96ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      *variable_ = old_value_;
97ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    }
98ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org   private:
99ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    bool* variable_;
100ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    bool old_value_;
101ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  };
102ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
103ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // Operand pointing to an external reference.
104ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // May emit code to set up the scratch register. The operand is
105ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // only guaranteed to be correct as long as the scratch register
106ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // isn't changed.
107ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // If the operand is used more than once, use a scratch register
108ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // that is guaranteed not to be clobbered.
109ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  Operand ExternalOperand(ExternalReference reference,
110ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org                          Register scratch = kScratchRegister);
111ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // Loads and stores the value of an external reference.
112ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // Special case code for load and store to take advantage of
113ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // load_rax/store_rax if possible/necessary.
114ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // For other operations, just use:
115ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  //   Operand operand = ExternalOperand(extref);
116ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  //   operation(operand, ..);
117ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  void Load(Register destination, ExternalReference source);
118ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  void Store(ExternalReference destination, Register source);
119ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // Loads the address of the external reference into the destination
120ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // register.
121ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  void LoadAddress(Register destination, ExternalReference source);
122ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // Returns the size of the code generated by LoadAddress.
123ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // Used by CallSize(ExternalReference) to find the size of a call.
124ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  int LoadAddressSize(ExternalReference source);
125ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  // Pushes the address of the external reference onto the stack.
126ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  void PushAddress(ExternalReference source);
127ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
128ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // Operations on roots in the root-array.
12918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  void LoadRoot(Register destination, Heap::RootListIndex index);
130ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  void StoreRoot(Register source, Heap::RootListIndex index);
1318f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  // Load a root value where the index (or part of it) is variable.
1328f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  // The variable_offset register is added to the fixed_offset value
1338f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  // to get the index into the root-array.
1348f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  void LoadRootIndexed(Register destination,
1358f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org                       Register variable_offset,
1368f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org                       int fixed_offset);
13718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  void CompareRoot(Register with, Heap::RootListIndex index);
13883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  void CompareRoot(const Operand& with, Heap::RootListIndex index);
13918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  void PushRoot(Heap::RootListIndex index);
14018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
141c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // These functions do not arrange the registers in any particular order so
142c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // they are not useful for calls that can cause a GC.  The caller can
143c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // exclude up to 3 registers that do not need to be saved and restored.
144c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void PushCallerSaved(SaveFPRegsMode fp_mode,
145c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                       Register exclusion1 = no_reg,
146c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                       Register exclusion2 = no_reg,
147c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                       Register exclusion3 = no_reg);
148c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void PopCallerSaved(SaveFPRegsMode fp_mode,
149c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                      Register exclusion1 = no_reg,
150c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                      Register exclusion2 = no_reg,
151c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                      Register exclusion3 = no_reg);
152c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
153c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// ---------------------------------------------------------------------------
154c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// GC Support
155c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
156c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
157c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  enum RememberedSetFinalAction {
158c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    kReturnAtEnd,
159c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    kFallThroughAtEnd
160c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  };
1614111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org
162c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Record in the remembered set the fact that we have a pointer to new space
163c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // at the address pointed to by the addr register.  Only works if addr is not
164c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // in new space.
165c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void RememberedSetHelper(Register object,  // Used for debug code.
166c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           Register addr,
167c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           Register scratch,
168c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           SaveFPRegsMode save_fp,
169c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           RememberedSetFinalAction and_then);
170c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
171c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void CheckPageFlag(Register object,
172c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     Register scratch,
173c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     int mask,
174c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     Condition cc,
175c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     Label* condition_met,
176c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     Label::Distance condition_met_distance = Label::kFar);
177c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
178f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  void CheckMapDeprecated(Handle<Map> map,
179f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org                          Register scratch,
180f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org                          Label* if_deprecated);
181f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org
182c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Check if object is in new space.  Jumps if the object is not in new space.
183c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // The register scratch can be object itself, but scratch will be clobbered.
184c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void JumpIfNotInNewSpace(Register object,
185c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           Register scratch,
186c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           Label* branch,
187c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           Label::Distance distance = Label::kFar) {
188c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    InNewSpace(object, scratch, not_equal, branch, distance);
189c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
190c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
191c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Check if object is in new space.  Jumps if the object is in new space.
192c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // The register scratch can be object itself, but it will be clobbered.
193c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void JumpIfInNewSpace(Register object,
194c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                        Register scratch,
195c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                        Label* branch,
196c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                        Label::Distance distance = Label::kFar) {
197c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    InNewSpace(object, scratch, equal, branch, distance);
198c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
199c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
200c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Check if an object has the black incremental marking color.  Also uses rcx!
201c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void JumpIfBlack(Register object,
202c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                   Register scratch0,
203c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                   Register scratch1,
204c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                   Label* on_black,
205c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                   Label::Distance on_black_distance = Label::kFar);
206c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
2072efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  // Detects conservatively whether an object is data-only, i.e. it does need to
208c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // be scanned by the garbage collector.
209c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void JumpIfDataObject(Register value,
210c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                        Register scratch,
211c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                        Label* not_data_object,
212c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                        Label::Distance not_data_object_distance);
213c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
214c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Checks the color of an object.  If the object is already grey or black
215c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // then we just fall through, since it is already live.  If it is white and
216c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // we can determine that it doesn't need to be scanned, then we just mark it
217c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // black and fall through.  For the rest we jump to the label so the
218c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // incremental marker can fix its assumptions.
219c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void EnsureNotWhite(Register object,
220c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                      Register scratch1,
221c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                      Register scratch2,
222c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                      Label* object_is_white_and_not_data,
223c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                      Label::Distance distance);
224c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
225c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Notify the garbage collector that we wrote a pointer into an object.
226c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // |object| is the object being stored into, |value| is the object being
227c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // stored.  value and scratch registers are clobbered by the operation.
228c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // The offset is the offset from the start of the object, not the offset from
229c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // the tagged HeapObject pointer.  For use with FieldOperand(reg, off).
230c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void RecordWriteField(
231c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Register object,
232c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      int offset,
233c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Register value,
234c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Register scratch,
235c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      SaveFPRegsMode save_fp,
236c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
237196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org      SmiCheck smi_check = INLINE_SMI_CHECK,
238196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org      PointersToHereCheck pointers_to_here_check_for_value =
239196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org          kPointersToHereMaybeInteresting);
240c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
241c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // As above, but the offset has the tag presubtracted.  For use with
242c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Operand(reg, off).
243c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void RecordWriteContextSlot(
244c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Register context,
245c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      int offset,
246c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Register value,
247c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Register scratch,
248c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      SaveFPRegsMode save_fp,
249c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
250196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org      SmiCheck smi_check = INLINE_SMI_CHECK,
251196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org      PointersToHereCheck pointers_to_here_check_for_value =
252196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org          kPointersToHereMaybeInteresting) {
253c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    RecordWriteField(context,
254c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     offset + kHeapObjectTag,
255c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     value,
256c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     scratch,
257c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     save_fp,
258c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     remembered_set_action,
259196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org                     smi_check,
260196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org                     pointers_to_here_check_for_value);
261c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
262c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
263c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Notify the garbage collector that we wrote a pointer into a fixed array.
264c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // |array| is the array being stored into, |value| is the
265394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // object being stored.  |index| is the array index represented as a non-smi.
266394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // All registers are clobbered by the operation RecordWriteArray
267c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // filters out smis so it does not update the write barrier if the
268c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // value is a smi.
269c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void RecordWriteArray(
270c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Register array,
271c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Register value,
272c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Register index,
273c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      SaveFPRegsMode save_fp,
274c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
275196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org      SmiCheck smi_check = INLINE_SMI_CHECK,
276196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org      PointersToHereCheck pointers_to_here_check_for_value =
277196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org          kPointersToHereMaybeInteresting);
278196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org
279196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org  void RecordWriteForMap(
280196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org      Register object,
281196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org      Register map,
282196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org      Register dst,
283196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org      SaveFPRegsMode save_fp);
284c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
285c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // For page containing |object| mark region covering |address|
28669ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  // dirty. |object| is the object being stored into, |value| is the
287c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // object being stored. The address and value registers are clobbered by the
28869ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  // operation.  RecordWrite filters out smis so it does not update
28969ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  // the write barrier if the value is a smi.
290c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void RecordWrite(
291c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Register object,
292c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Register address,
293c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Register value,
294c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      SaveFPRegsMode save_fp,
295c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
296196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org      SmiCheck smi_check = INLINE_SMI_CHECK,
297196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org      PointersToHereCheck pointers_to_here_check_for_value =
298196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org          kPointersToHereMaybeInteresting);
2999d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
3009085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // ---------------------------------------------------------------------------
3019085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Debugger Support
3029085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3035c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void DebugBreak();
3049085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
305c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  // Generates function and stub prologue code.
306285f85a5a149f36516a20200a76899651dd95fb6machenbach@chromium.org  void StubPrologue();
307285f85a5a149f36516a20200a76899651dd95fb6machenbach@chromium.org  void Prologue(bool code_pre_aging);
308c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
309c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  // Enter specific kind of exit frame; either in normal or
310c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  // debug mode. Expects the number of arguments in register rax and
311a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org  // sets up the number of arguments in register rdi and the pointer
312a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org  // to the first argument in register rsi.
3134a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  //
3144a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  // Allocates arg_stack_space * kPointerSize memory (not GCed) on the stack
3154a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  // accessible via StackSpaceOperand.
3160ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  void EnterExitFrame(int arg_stack_space = 0, bool save_doubles = false);
3179085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3184a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  // Enter specific kind of exit frame. Allocates arg_stack_space * kPointerSize
3194a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  // memory (not GCed) on the stack accessible via StackSpaceOperand.
3204a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  void EnterApiExitFrame(int arg_stack_space);
321e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org
322a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org  // Leave the current exit frame. Expects/provides the return value in
323a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org  // register rax:rdx (untouched) and the pointer to the first
324a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org  // argument in register rsi.
3250ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  void LeaveExitFrame(bool save_doubles = false);
3269085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3274a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  // Leave the current exit frame. Expects/provides the return value in
3284a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  // register rax (untouched).
329528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  void LeaveApiExitFrame(bool restore_context);
3309085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
331a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Push and pop the registers that can hold pointers.
3320ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  void PushSafepointRegisters() { Pushad(); }
3330ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  void PopSafepointRegisters() { Popad(); }
3343a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // Store the value in register src in the safepoint register stack
3353a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // slot for register dst.
33646839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  void StoreToSafepointRegisterSlot(Register dst, const Immediate& imm);
3373a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  void StoreToSafepointRegisterSlot(Register dst, Register src);
3385d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  void LoadFromSafepointRegisterSlot(Register dst, Register src);
3390ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org
3408f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  void InitializeRootRegister() {
341394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    ExternalReference roots_array_start =
342394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        ExternalReference::roots_array_start(isolate());
343e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    Move(kRootRegister, roots_array_start);
344fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org    addp(kRootRegister, Immediate(kRootRegisterBias));
3458f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  }
3468f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org
3479085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // ---------------------------------------------------------------------------
3489085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // JavaScript invokes
3499085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3509085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Invoke the JavaScript function code by either calling or jumping.
351eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void InvokeCode(Register code,
3529085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org                  const ParameterCount& expected,
3539085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org                  const ParameterCount& actual,
3543a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                  InvokeFlag flag,
355e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org                  const CallWrapper& call_wrapper);
3569085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3579085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Invoke the JavaScript function in the given register. Changes the
3589085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // current context to the context in the function before invoking.
3599085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void InvokeFunction(Register function,
3609085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org                      const ParameterCount& actual,
3613a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                      InvokeFlag flag,
362e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org                      const CallWrapper& call_wrapper);
3639085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3648a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  void InvokeFunction(Register function,
3658a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org                      const ParameterCount& expected,
3668a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org                      const ParameterCount& actual,
3678a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org                      InvokeFlag flag,
368e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org                      const CallWrapper& call_wrapper);
3698a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org
370c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  void InvokeFunction(Handle<JSFunction> function,
37132d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org                      const ParameterCount& expected,
3725c838251403b0be9a882540f1922577abba4c872ager@chromium.org                      const ParameterCount& actual,
3733a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                      InvokeFlag flag,
374e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org                      const CallWrapper& call_wrapper);
3755c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3769085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Invoke specified builtin JavaScript function. Adds an entry to
3779085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // the unresolved list if the name does not resolve.
3783a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  void InvokeBuiltin(Builtins::JavaScript id,
3793a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                     InvokeFlag flag,
380fb144a0716afe7ab8bf245f2391a9e53b3db3c89fschneider@chromium.org                     const CallWrapper& call_wrapper = NullCallWrapper());
3819085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
382145eff58d4f6ac0dcc53abb556dbf3cac6c3280aerik.corry@gmail.com  // Store the function for the given builtin in the target register.
383145eff58d4f6ac0dcc53abb556dbf3cac6c3280aerik.corry@gmail.com  void GetBuiltinFunction(Register target, Builtins::JavaScript id);
384145eff58d4f6ac0dcc53abb556dbf3cac6c3280aerik.corry@gmail.com
3859085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Store the code object for the given builtin in the target register.
3869085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void GetBuiltinEntry(Register target, Builtins::JavaScript id);
3879085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3884af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
3894af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // ---------------------------------------------------------------------------
3904af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Smi tagging, untagging and operations on tagged smis.
3914af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
392dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  // Support for constant splitting.
393dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  bool IsUnsafeInt(const int32_t x);
394dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  void SafeMove(Register dst, Smi* src);
395dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  void SafePush(Smi* src);
396dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
39769ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  void InitializeSmiConstantRegister() {
3989cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org    Move(kSmiConstantRegister, Smi::FromInt(kSmiConstantRegisterValue),
399af4fba3c6d2a18866505de3e6798757dd1448c6dmachenbach@chromium.org         Assembler::RelocInfoNone());
40069ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  }
40169ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org
4024af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Conversions between tagged smi values and non-tagged integer values.
4034af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
4044af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Tag an integer value. The result must be known to be a valid smi value.
405b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Only uses the low 32 bits of the src register. Sets the N and Z flags
406c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org  // based on the value of the resulting smi.
4074af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void Integer32ToSmi(Register dst, Register src);
4084af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
4095ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org  // Stores an integer32 value into a memory field that already holds a smi.
4105ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org  void Integer32ToSmiField(const Operand& dst, Register src);
4115ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org
4124af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Adds constant to src and tags the result as a smi.
4134af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Result must be a valid smi.
4149d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void Integer64PlusConstantToSmi(Register dst, Register src, int constant);
4154af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
4164af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Convert smi to 32-bit integer. I.e., not sign extended into
4174af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // high 32 bits of destination.
4184af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiToInteger32(Register dst, Register src);
41930ce411529579186181838984710b0b0980857aaricow@chromium.org  void SmiToInteger32(Register dst, const Operand& src);
4204af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
4214af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Convert smi to 64-bit integer (sign extended if necessary).
4224af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiToInteger64(Register dst, Register src);
4235ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org  void SmiToInteger64(Register dst, const Operand& src);
4244af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
4254af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Multiply a positive smi's integer value by a power of two.
4264af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Provides result as 64-bit integer value.
4274af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void PositiveSmiTimesPowerOfTwoToInteger64(Register dst,
4284af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                                             Register src,
4294af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                                             int power);
4304af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
43130ce411529579186181838984710b0b0980857aaricow@chromium.org  // Divide a positive smi's integer value by a power of two.
43230ce411529579186181838984710b0b0980857aaricow@chromium.org  // Provides result as 32-bit integer value.
43330ce411529579186181838984710b0b0980857aaricow@chromium.org  void PositiveSmiDivPowerOfTwoToInteger32(Register dst,
43430ce411529579186181838984710b0b0980857aaricow@chromium.org                                           Register src,
43530ce411529579186181838984710b0b0980857aaricow@chromium.org                                           int power);
43630ce411529579186181838984710b0b0980857aaricow@chromium.org
43744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  // Perform the logical or of two smi values and return a smi value.
43844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  // If either argument is not a smi, jump to on_not_smis and retain
43944bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  // the original values of source registers. The destination register
44044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  // may be changed if it's not one of the source registers.
44144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  void SmiOrIfSmis(Register dst,
44244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org                   Register src1,
44344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org                   Register src2,
44483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                   Label* on_not_smis,
44583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                   Label::Distance near_jump = Label::kFar);
44644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
44730ce411529579186181838984710b0b0980857aaricow@chromium.org
448badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  // Simple comparison of smis.  Both sides must be known smis to use these,
449badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  // otherwise use Cmp.
450badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  void SmiCompare(Register smi1, Register smi2);
4519d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void SmiCompare(Register dst, Smi* src);
452ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  void SmiCompare(Register dst, const Operand& src);
4539d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void SmiCompare(const Operand& dst, Register src);
4549d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void SmiCompare(const Operand& dst, Smi* src);
4555ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org  // Compare the int32 in src register to the value of the smi stored at dst.
4565ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org  void SmiCompareInteger32(const Operand& dst, Register src);
4579d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  // Sets sign and zero flags depending on value of smi in register.
4589d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void SmiTest(Register src);
4599d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
4604af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Functions performing a check on a known or potential smi. Returns
4614af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // a condition that is satisfied if the check is successful.
4624af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
4634af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Is the value a tagged smi.
4644af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  Condition CheckSmi(Register src);
4650a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  Condition CheckSmi(const Operand& src);
4664af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
467eb7c144137bd7d461d4996f752f1353a0856fac1ricow@chromium.org  // Is the value a non-negative tagged smi.
468eb7c144137bd7d461d4996f752f1353a0856fac1ricow@chromium.org  Condition CheckNonNegativeSmi(Register src);
4694af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
470b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Are both values tagged smis.
4714af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  Condition CheckBothSmi(Register first, Register second);
4724af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
473eb7c144137bd7d461d4996f752f1353a0856fac1ricow@chromium.org  // Are both values non-negative tagged smis.
474eb7c144137bd7d461d4996f752f1353a0856fac1ricow@chromium.org  Condition CheckBothNonNegativeSmi(Register first, Register second);
475b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
476b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Are either value a tagged smi.
477c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org  Condition CheckEitherSmi(Register first,
478c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org                           Register second,
479c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org                           Register scratch = kScratchRegister);
480b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4814af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Is the value the minimum smi value (since we are using
4824af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // two's complement numbers, negating the value is known to yield
4834af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // a non-smi value).
4844af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  Condition CheckIsMinSmi(Register src);
4854af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
4864af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Checks whether an 32-bit integer value is a valid for conversion
4874af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // to a smi.
4884af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  Condition CheckInteger32ValidSmiValue(Register src);
4894af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
4903811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  // Checks whether an 32-bit unsigned integer value is a valid for
4913811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  // conversion to a smi.
4923811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  Condition CheckUInteger32ValidSmiValue(Register src);
4933811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
4940ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  // Check whether src is a Smi, and set dst to zero if it is a smi,
4950ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  // and to one if it isn't.
4960ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  void CheckSmiToIndicator(Register dst, Register src);
4970ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  void CheckSmiToIndicator(Register dst, const Operand& src);
4980ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org
4994af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Test-and-jump functions. Typically combines a check function
5004af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // above with a conditional jump.
5014af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
502e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  // Jump if the value can be represented by a smi.
503e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  void JumpIfValidSmiValue(Register src, Label* on_valid,
504e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org                           Label::Distance near_jump = Label::kFar);
505e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org
5064af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Jump if the value cannot be represented by a smi.
50783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  void JumpIfNotValidSmiValue(Register src, Label* on_invalid,
50883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                              Label::Distance near_jump = Label::kFar);
5094af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
510e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  // Jump if the unsigned integer value can be represented by a smi.
511e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  void JumpIfUIntValidSmiValue(Register src, Label* on_valid,
512e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org                               Label::Distance near_jump = Label::kFar);
513e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org
5143811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  // Jump if the unsigned integer value cannot be represented by a smi.
51583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  void JumpIfUIntNotValidSmiValue(Register src, Label* on_invalid,
51683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                  Label::Distance near_jump = Label::kFar);
5173811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
5184af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Jump to label if the value is a tagged smi.
51983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  void JumpIfSmi(Register src,
52083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                 Label* on_smi,
52183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                 Label::Distance near_jump = Label::kFar);
5224af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
5234af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Jump to label if the value is not a tagged smi.
52483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  void JumpIfNotSmi(Register src,
52583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                    Label* on_not_smi,
52683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                    Label::Distance near_jump = Label::kFar);
5274af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
528eb7c144137bd7d461d4996f752f1353a0856fac1ricow@chromium.org  // Jump to label if the value is not a non-negative tagged smi.
52983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  void JumpUnlessNonNegativeSmi(Register src,
53083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                Label* on_not_smi,
53183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                Label::Distance near_jump = Label::kFar);
5324af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
5339d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  // Jump to label if the value, which must be a tagged smi, has value equal
5344af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // to the constant.
535c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org  void JumpIfSmiEqualsConstant(Register src,
536c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org                               Smi* constant,
53783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                               Label* on_equals,
53883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                               Label::Distance near_jump = Label::kFar);
539c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org
5404af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Jump if either or both register are not smi values.
541c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org  void JumpIfNotBothSmi(Register src1,
542c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org                        Register src2,
54383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                        Label* on_not_both_smi,
54483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                        Label::Distance near_jump = Label::kFar);
5454af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
546eb7c144137bd7d461d4996f752f1353a0856fac1ricow@chromium.org  // Jump if either or both register are not non-negative smi values.
547eb7c144137bd7d461d4996f752f1353a0856fac1ricow@chromium.org  void JumpUnlessBothNonNegativeSmi(Register src1, Register src2,
54883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                    Label* on_not_both_smi,
54983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                    Label::Distance near_jump = Label::kFar);
550b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
5514af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Operations on tagged smi values.
5524af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
5534af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Smis represent a subset of integers. The subset is always equivalent to
5544af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // a two's complement interpretation of a fixed number of bits.
5554af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
5569d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  // Add an integer constant to a tagged smi, giving a tagged smi as result.
5579d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  // No overflow testing on the result is done.
5589d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void SmiAddConstant(Register dst, Register src, Smi* constant);
5599d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
5609dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Add an integer constant to a tagged smi, giving a tagged smi as result.
5619dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // No overflow testing on the result is done.
5629dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  void SmiAddConstant(const Operand& dst, Smi* constant);
5639dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
5644af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Add an integer constant to a tagged smi, giving a tagged smi as result,
5654af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // or jumping to a label if the result cannot be represented by a smi.
5664af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiAddConstant(Register dst,
5674af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                      Register src,
5689d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com                      Smi* constant,
569e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org                      SmiOperationExecutionMode mode,
570e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org                      Label* bailout_label,
57183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                      Label::Distance near_jump = Label::kFar);
5724af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
5734af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Subtract an integer constant from a tagged smi, giving a tagged smi as
574ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  // result. No testing on the result is done. Sets the N and Z flags
575ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  // based on the value of the resulting integer.
5769d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void SmiSubConstant(Register dst, Register src, Smi* constant);
5779d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
5789d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  // Subtract an integer constant from a tagged smi, giving a tagged smi as
5794af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // result, or jumping to a label if the result cannot be represented by a smi.
5804af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiSubConstant(Register dst,
5814af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                      Register src,
5829d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com                      Smi* constant,
583e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org                      SmiOperationExecutionMode mode,
584e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org                      Label* bailout_label,
58583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                      Label::Distance near_jump = Label::kFar);
5864af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
5874af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Negating a smi can give a negative zero or too large positive value.
5889d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  // NOTICE: This operation jumps on success, not failure!
5894af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiNeg(Register dst,
5904af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org              Register src,
59183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org              Label* on_smi_result,
59283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org              Label::Distance near_jump = Label::kFar);
5934af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
5944af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Adds smi values and return the result as a smi.
595d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  // If dst is src1, then src1 will be destroyed if the operation is
596d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  // successful, otherwise kept intact.
5974af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiAdd(Register dst,
5984af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org              Register src1,
5994af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org              Register src2,
60083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org              Label* on_not_smi_result,
60183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org              Label::Distance near_jump = Label::kFar);
6027979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  void SmiAdd(Register dst,
6037979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org              Register src1,
6047979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org              const Operand& src2,
60583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org              Label* on_not_smi_result,
60683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org              Label::Distance near_jump = Label::kFar);
607c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org
608c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org  void SmiAdd(Register dst,
609c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org              Register src1,
610c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org              Register src2);
6114af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
6124af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Subtracts smi values and return the result as a smi.
613c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org  // If dst is src1, then src1 will be destroyed if the operation is
614c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org  // successful, otherwise kept intact.
6154af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiSub(Register dst,
6164af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org              Register src1,
6174af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org              Register src2,
61883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org              Label* on_not_smi_result,
61983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org              Label::Distance near_jump = Label::kFar);
620ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  void SmiSub(Register dst,
621ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org              Register src1,
6229dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com              const Operand& src2,
62383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org              Label* on_not_smi_result,
62483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org              Label::Distance near_jump = Label::kFar);
625c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org
626c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org  void SmiSub(Register dst,
627c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org              Register src1,
628c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org              Register src2);
629c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org
630c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org  void SmiSub(Register dst,
631c3669763e2617aefdac84a072327b201b3dff129jkummerow@chromium.org              Register src1,
632c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org              const Operand& src2);
633ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org
6344af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Multiplies smi values and return the result as a smi,
6354af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // if possible.
6364af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // If dst is src1, then src1 will be destroyed, even if
6374af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // the operation is unsuccessful.
6384af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiMul(Register dst,
6394af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org              Register src1,
6404af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org              Register src2,
64183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org              Label* on_not_smi_result,
64283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org              Label::Distance near_jump = Label::kFar);
6434af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
6444af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Divides one smi by another and returns the quotient.
6454af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Clobbers rax and rdx registers.
6464af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiDiv(Register dst,
6474af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org              Register src1,
6484af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org              Register src2,
64983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org              Label* on_not_smi_result,
65083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org              Label::Distance near_jump = Label::kFar);
6514af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
6524af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Divides one smi by another and returns the remainder.
6534af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Clobbers rax and rdx registers.
6544af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiMod(Register dst,
6554af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org              Register src1,
6564af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org              Register src2,
65783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org              Label* on_not_smi_result,
65883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org              Label::Distance near_jump = Label::kFar);
6594af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
6604af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Bitwise operations.
6614af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiNot(Register dst, Register src);
6624af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiAnd(Register dst, Register src1, Register src2);
6634af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiOr(Register dst, Register src1, Register src2);
6644af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiXor(Register dst, Register src1, Register src2);
6659d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void SmiAndConstant(Register dst, Register src1, Smi* constant);
6669d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void SmiOrConstant(Register dst, Register src1, Smi* constant);
6679d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void SmiXorConstant(Register dst, Register src1, Smi* constant);
6684af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
6694af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiShiftLeftConstant(Register dst,
6704af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                            Register src,
671e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org                            int shift_value,
672e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org                            Label* on_not_smi_result = NULL,
673e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org                            Label::Distance near_jump = Label::kFar);
6744af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiShiftLogicalRightConstant(Register dst,
67504a34e6171ac922cb1a4c5162cf471809c468ad0machenbach@chromium.org                                    Register src,
67604a34e6171ac922cb1a4c5162cf471809c468ad0machenbach@chromium.org                                    int shift_value,
67704a34e6171ac922cb1a4c5162cf471809c468ad0machenbach@chromium.org                                    Label* on_not_smi_result,
67804a34e6171ac922cb1a4c5162cf471809c468ad0machenbach@chromium.org                                    Label::Distance near_jump = Label::kFar);
6794af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiShiftArithmeticRightConstant(Register dst,
6804af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                                       Register src,
6814af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                                       int shift_value);
6824af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
6834af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Shifts a smi value to the left, and returns the result if that is a smi.
6844af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Uses and clobbers rcx, so dst may not be rcx.
6854af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiShiftLeft(Register dst,
6864af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                    Register src1,
687e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org                    Register src2,
688e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org                    Label* on_not_smi_result = NULL,
689e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org                    Label::Distance near_jump = Label::kFar);
6904af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Shifts a smi value to the right, shifting in zero bits at the top, and
6914af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // returns the unsigned intepretation of the result if that is a smi.
6924af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Uses and clobbers rcx, so dst may not be rcx.
6934af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiShiftLogicalRight(Register dst,
694c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org                            Register src1,
695c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org                            Register src2,
69683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                            Label* on_not_smi_result,
69783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                            Label::Distance near_jump = Label::kFar);
6984af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Shifts a smi value to the right, sign extending the top, and
6994af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // returns the signed intepretation of the result. That will always
7004af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // be a valid smi value, since it's numerically smaller than the
7014af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // original.
7024af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Uses and clobbers rcx, so dst may not be rcx.
7034af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SmiShiftArithmeticRight(Register dst,
7044af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                               Register src1,
7054af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                               Register src2);
7064af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
7074af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Specialized operations
7084af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
7094af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Select the non-smi register of two registers where exactly one is a
7104af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // smi. If neither are smis, jump to the failure label.
7114af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void SelectNonSmi(Register dst,
7124af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                    Register src1,
7134af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org                    Register src2,
71483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                    Label* on_not_smis,
71583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                    Label::Distance near_jump = Label::kFar);
7164af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
7174af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Converts, if necessary, a smi to a combination of number and
7184af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // multiplier to be used as a scaled index.
7194af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // The src register contains a *positive* smi value. The shift is the
7204af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // power of two to multiply the index value by (e.g.
7214af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // to index by smi-value * kPointerSize, pass the smi and kPointerSizeLog2).
7224af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // The returned index register may be either src or dst, depending
7234af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // on what is most efficient. If src and dst are different registers,
7244af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // src is always unchanged.
7254af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  SmiIndex SmiToIndex(Register dst, Register src, int shift);
7264af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
7274af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Converts a positive smi to a negative index.
7284af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  SmiIndex SmiToNegativeIndex(Register dst, Register src, int shift);
7294af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
7307979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Add the value of a smi in memory to an int32 register.
7317979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Sets flags as a normal add.
7327979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  void AddSmiField(Register dst, const Operand& src);
7337979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
7349d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  // Basic Smi operations.
7353811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  void Move(Register dst, Smi* source) {
73669ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    LoadSmiConstant(dst, source);
7373811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  }
7383811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
7393811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  void Move(const Operand& dst, Smi* source) {
74069ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org    Register constant = GetSmiConstant(source);
74143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    movp(dst, constant);
7423811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  }
7433811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
7449d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void Push(Smi* smi);
745662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org
7462ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org  // Save away a raw integer with pointer size on the stack as two integers
747662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  // masquerading as smis so that the garbage collector skips visiting them.
7482ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org  void PushRegisterAsTwoSmis(Register src, Register scratch = kScratchRegister);
7492ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org  // Reconstruct a raw integer with pointer size from two integers masquerading
7502ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org  // as smis on the top of stack.
7512ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org  void PopRegisterAsTwoSmis(Register dst, Register scratch = kScratchRegister);
752662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org
7539d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void Test(const Operand& dst, Smi* source);
7549d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
755394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
756eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // ---------------------------------------------------------------------------
757b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // String macros.
75883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org
759528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // Generate code to do a lookup in the number string cache. If the number in
760528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // the register object is found in the cache the generated code falls through
761528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // with the result in the result register. The object and the result register
762528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // can be the same. If the number is not found in the cache the code jumps to
763528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // the label not_found with only the content of register object unchanged.
764528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  void LookupNumberStringCache(Register object,
765528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                               Register result,
766528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                               Register scratch1,
767528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                               Register scratch2,
768528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                               Label* not_found);
769528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
77083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  // If object is a string, its map is loaded into object_map.
77183aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  void JumpIfNotString(Register object,
77283aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org                       Register object_map,
77383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                       Label* not_string,
77483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                       Label::Distance near_jump = Label::kFar);
77583aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org
77683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org
7772c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  void JumpIfNotBothSequentialOneByteStrings(
7782c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      Register first_object, Register second_object, Register scratch1,
7792c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      Register scratch2, Label* on_not_both_flat_one_byte,
78083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      Label::Distance near_jump = Label::kFar);
781b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
7822c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  // Check whether the instance type represents a flat one-byte string. Jump
7832c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  // to the label if not. If the instance type can be scratched specify same
7842c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  // register for both instance type and scratch.
7852c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  void JumpIfInstanceTypeIsNotSequentialOneByte(
7862c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      Register instance_type, Register scratch,
7872c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      Label* on_not_flat_one_byte_string,
78883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      Label::Distance near_jump = Label::kFar);
789ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org
7902c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  void JumpIfBothInstanceTypesAreNotSequentialOneByte(
7912c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      Register first_object_instance_type, Register second_object_instance_type,
7922c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      Register scratch1, Register scratch2, Label* on_fail,
79383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      Label::Distance near_jump = Label::kFar);
794ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org
7959af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  void EmitSeqStringSetCharCheck(Register string,
7969af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org                                 Register index,
7979af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org                                 Register value,
7989af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org                                 uint32_t encoding_mask);
7999af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org
8001510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  // Checks if the given register or operand is a unique name
80106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  void JumpIfNotUniqueNameInstanceType(Register reg, Label* not_unique_name,
80206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                                       Label::Distance distance = Label::kFar);
80306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  void JumpIfNotUniqueNameInstanceType(Operand operand, Label* not_unique_name,
80406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                                       Label::Distance distance = Label::kFar);
8051510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
806b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // ---------------------------------------------------------------------------
80713bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  // Macro instructions.
808eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
809d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  // Load/store with specific representation.
810d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  void Load(Register dst, const Operand& src, Representation r);
811d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  void Store(const Operand& dst, Register src, Representation r);
812d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org
8139d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  // Load a register with a long value as efficiently as possible.
814e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void Set(Register dst, int64_t x);
815f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void Set(const Operand& dst, intptr_t x);
8169085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
817528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // cvtsi2sd instruction only writes to the low 64-bit of dst register, which
818528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // hinders register renaming and makes dependence chains longer. So we use
819528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // xorps to clear the dst register before cvtsi2sd to solve this issue.
820528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  void Cvtlsi2sd(XMMRegister dst, Register src);
821528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  void Cvtlsi2sd(XMMRegister dst, const Operand& src);
822528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
8234a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  // Move if the registers are not identical.
8244a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  void Move(Register target, Register source);
8254a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
82604a34e6171ac922cb1a4c5162cf471809c468ad0machenbach@chromium.org  // TestBit and Load SharedFunctionInfo special field.
82704a34e6171ac922cb1a4c5162cf471809c468ad0machenbach@chromium.org  void TestBitSharedFunctionInfoSpecialField(Register base,
82804a34e6171ac922cb1a4c5162cf471809c468ad0machenbach@chromium.org                                             int offset,
82904a34e6171ac922cb1a4c5162cf471809c468ad0machenbach@chromium.org                                             int bit_index);
83004a34e6171ac922cb1a4c5162cf471809c468ad0machenbach@chromium.org  void LoadSharedFunctionInfoSpecialField(Register dst,
83104a34e6171ac922cb1a4c5162cf471809c468ad0machenbach@chromium.org                                          Register base,
83204a34e6171ac922cb1a4c5162cf471809c468ad0machenbach@chromium.org                                          int offset);
833394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
8345aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  // Handle support
8355aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  void Move(Register dst, Handle<Object> source);
8365aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  void Move(const Operand& dst, Handle<Object> source);
8375aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  void Cmp(Register dst, Handle<Object> source);
8383e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void Cmp(const Operand& dst, Handle<Object> source);
839badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  void Cmp(Register dst, Smi* src);
840badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  void Cmp(const Operand& dst, Smi* src);
8415aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  void Push(Handle<Object> source);
8420c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org
84364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // Load a heap object and handle the case of new-space objects by
84464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // indirecting via a global cell.
845c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  void MoveHeapObject(Register result, Handle<Object> object);
846a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org
84764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // Load a global cell into a register.
84841728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org  void LoadGlobalCell(Register dst, Handle<Cell> cell);
84964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
8500c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  // Emit code to discard a non-negative number of pointer-sized elements
8510c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  // from the stack, clobbering only the rsp register.
85213bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  void Drop(int stack_elements);
853a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  // Emit code to discard a positive number of pointer-sized elements
854a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  // from the stack under the return address which remains on the top,
855a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  // clobbering the rsp register.
856a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  void DropUnderReturnAddress(int stack_elements,
857a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org                              Register scratch = kScratchRegister);
8580c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org
85913bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  void Call(Label* target) { call(target); }
860763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  void Push(Register src);
861763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  void Push(const Operand& src);
862a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  void PushQuad(const Operand& src);
863763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  void Push(Immediate value);
864763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  void PushImm32(int32_t imm32);
865763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  void Pop(Register dst);
866763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  void Pop(const Operand& dst);
867a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  void PopQuad(const Operand& dst);
868763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  void PushReturnAddressFrom(Register src) { pushq(src); }
869763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  void PopReturnAddressTo(Register dst) { popq(dst); }
870e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  void Move(Register dst, ExternalReference ext) {
871fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org    movp(dst, reinterpret_cast<void*>(ext.address()),
872e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org         RelocInfo::EXTERNAL_REFERENCE);
873e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  }
8745aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
8759cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org  // Loads a pointer into a register with a relocation mode.
8769cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org  void Move(Register dst, void* ptr, RelocInfo::Mode rmode) {
8779cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org    // This method must not be used with heap object references. The stored
8789cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org    // address is not GC safe. Use the handle version instead.
879e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(rmode > RelocInfo::LAST_GCED_ENUM);
8809cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org    movp(dst, ptr, rmode);
8819cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org  }
8829cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org
8839cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org  void Move(Register dst, Handle<Object> value, RelocInfo::Mode rmode) {
8849cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org    AllowDeferredHandleDereference using_raw_address;
885e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!RelocInfo::IsNone(rmode));
886e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(value->IsHeapObject());
887e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!isolate()->heap()->InNewSpace(*value));
888fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org    movp(dst, reinterpret_cast<void*>(value.location()), rmode);
8899cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org  }
8909cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org
891eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // Control Flow
892eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void Jump(Address destination, RelocInfo::Mode rmode);
893eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void Jump(ExternalReference ext);
894f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void Jump(const Operand& op);
8955aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  void Jump(Handle<Code> code_object, RelocInfo::Mode rmode);
8965aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
897eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void Call(Address destination, RelocInfo::Mode rmode);
898eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void Call(ExternalReference ext);
899f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void Call(const Operand& op);
9008e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  void Call(Handle<Code> code_object,
9018e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org            RelocInfo::Mode rmode,
902471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org            TypeFeedbackId ast_id = TypeFeedbackId::None());
903eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
904eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org  // The size of the code generated for different call instructions.
905af4fba3c6d2a18866505de3e6798757dd1448c6dmachenbach@chromium.org  int CallSize(Address destination) {
906594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    return kCallSequenceLength;
907eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org  }
908ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  int CallSize(ExternalReference ext);
909eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org  int CallSize(Handle<Code> code_object) {
910eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org    // Code calls use 32-bit relative addressing.
911eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org    return kShortCallInstructionLength;
912eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org  }
913eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org  int CallSize(Register target) {
914eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org    // Opcode: REX_opt FF /2 m64
915eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org    return (target.high_bit() != 0) ? 3 : 2;
916eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org  }
917eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org  int CallSize(const Operand& target) {
918eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org    // Opcode: REX_opt FF /2 m64
919eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org    return (target.requires_rex() ? 2 : 1) + target.operand_size();
920eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org  }
921eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org
92283aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  // Emit call to the code we are currently generating.
92383aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  void CallSelf() {
92483aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org    Handle<Code> self(reinterpret_cast<Code**>(CodeObject().location()));
92583aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org    Call(self, RelocInfo::CODE_TARGET);
92683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  }
92783aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org
9280a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  // Non-x64 instructions.
9290a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  // Push/pop all general purpose registers.
9300a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  // Does not push rsp/rbp nor any of the assembler's special purpose registers
9310a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  // (kScratchRegister, kSmiConstantRegister, kRootRegister).
9320a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  void Pushad();
9330a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  void Popad();
9340ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  // Sets the stack as after performing Popad, without actually loading the
9350ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  // registers.
9360ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  void Dropad();
9370a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
9389085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Compare object type for heap object.
939e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  // Always use unsigned comparisons: above and below, not less and greater.
9409085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Incoming register is heap_object and outgoing register is map.
94186f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  // They may be the same register, and may be kScratchRegister.
9429085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void CmpObjectType(Register heap_object, InstanceType type, Register map);
9439085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9449085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Compare instance type for map.
945e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  // Always use unsigned comparisons: above and below, not less and greater.
9469085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void CmpInstanceType(Register map, InstanceType type);
9479085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
948d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com  // Check if a map for a JSObject indicates that the object has fast elements.
949d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com  // Jump to the specified label if it does not.
950d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com  void CheckFastElements(Register map,
951d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com                         Label* fail,
952d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com                         Label::Distance distance = Label::kFar);
953d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com
954c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Check if a map for a JSObject indicates that the object can have both smi
955c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // and HeapObject elements.  Jump to the specified label if it does not.
956c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void CheckFastObjectElements(Register map,
957c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                               Label* fail,
958c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                               Label::Distance distance = Label::kFar);
959c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
960c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Check if a map for a JSObject indicates that the object has fast smi only
961c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // elements.  Jump to the specified label if it does not.
962830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org  void CheckFastSmiElements(Register map,
963830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org                            Label* fail,
964830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org                            Label::Distance distance = Label::kFar);
965c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
966c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Check to see if maybe_number can be stored as a double in
967394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // FastDoubleElements. If it can, store it at the index specified by index in
968394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // the FastDoubleElements array elements, otherwise jump to fail.  Note that
969394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // index must not be smi-tagged.
970c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void StoreNumberToDoubleElements(Register maybe_number,
971c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                   Register elements,
972394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                   Register index,
973c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                   XMMRegister xmm_scratch,
974fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                   Label* fail,
975fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                   int elements_offset = 0);
976c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
977935a7790c70d49e252069bc2d34eaa72f8c6677fmachenbach@chromium.org  // Compare an object's map with the specified map.
978935a7790c70d49e252069bc2d34eaa72f8c6677fmachenbach@chromium.org  void CompareMap(Register obj, Handle<Map> map);
979f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com
980f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // Check if the map of an object is equal to a specified map and branch to
981f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // label if not. Skip the smi check if not required (object is known to be a
982f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match
9832efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  // against maps that are ElementsKind transition maps of the specified map.
9845c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void CheckMap(Register obj,
9855c838251403b0be9a882540f1922577abba4c872ager@chromium.org                Handle<Map> map,
9865c838251403b0be9a882540f1922577abba4c872ager@chromium.org                Label* fail,
987a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org                SmiCheckType smi_check_type);
9885c838251403b0be9a882540f1922577abba4c872ager@chromium.org
989ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org  // Check if the map of an object is equal to a specified map and branch to a
990ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org  // specified target if equal. Skip the smi check if not required (object is
991ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org  // known to be a heap object)
992ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org  void DispatchMap(Register obj,
9932bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org                   Register unused,
994ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org                   Handle<Map> map,
995ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org                   Handle<Code> success,
996ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org                   SmiCheckType smi_check_type);
997ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org
998b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Check if the object in register heap_object is a string. Afterwards the
999b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // register map contains the object map and the register instance_type
1000b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // contains the instance_type. The registers map and instance_type can be the
1001b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // same in which case it contains the instance type afterwards. Either of the
1002b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // registers map and instance_type can be the same as heap_object.
1003b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  Condition IsObjectStringType(Register heap_object,
1004b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org                               Register map,
1005b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org                               Register instance_type);
1006b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
1007750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  // Check if the object in register heap_object is a name. Afterwards the
1008750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  // register map contains the object map and the register instance_type
1009750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  // contains the instance_type. The registers map and instance_type can be the
1010750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  // same in which case it contains the instance type afterwards. Either of the
1011750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  // registers map and instance_type can be the same as heap_object.
1012750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  Condition IsObjectNameType(Register heap_object,
1013750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                             Register map,
1014750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                             Register instance_type);
1015750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org
101640b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  // FCmp compares and pops the two values on top of the FPU stack.
101740b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  // The flag results are similar to integer cmp, but requires unsigned
10189085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // jcc instructions (je, ja, jae, jb, jbe, je, and jz).
10199085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void FCmp();
10209085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1021c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  void ClampUint8(Register reg);
1022c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1023c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  void ClampDoubleToUint8(XMMRegister input_reg,
1024c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                          XMMRegister temp_xmm_reg,
102589e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org                          Register result_reg);
1026c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1027c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  void SlowTruncateToI(Register result_reg, Register input_reg,
1028c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org      int offset = HeapNumber::kValueOffset - kHeapObjectTag);
1029c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
1030c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  void TruncateHeapNumberToI(Register result_reg, Register input_reg);
1031c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  void TruncateDoubleToI(Register result_reg, XMMRegister input_reg);
1032c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
1033c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  void DoubleToI(Register result_reg, XMMRegister input_reg,
103406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                 XMMRegister scratch, MinusZeroMode minus_zero_mode,
103506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                 Label* lost_precision, Label* is_nan, Label* minus_zero,
103606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                 Label::Distance dst = Label::kFar);
1037c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
10387e6132b924829c353864933f29124419916db550machenbach@chromium.org  void LoadUint32(XMMRegister dst, Register src);
103946839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org
104040cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  void LoadInstanceDescriptors(Register map, Register descriptors);
1041355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  void EnumLength(Register dst, Register map);
104206ab2ec756e44eeaf7500b9794f9d2abc79dc8cfverwaest@chromium.org  void NumberOfOwnDescriptors(Register dst, Register map);
1043355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org
1044355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  template<typename Field>
1045355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  void DecodeField(Register reg) {
10463c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    static const int shift = Field::kShift;
104706ab2ec756e44eeaf7500b9794f9d2abc79dc8cfverwaest@chromium.org    static const int mask = Field::kMask >> Field::kShift;
1048d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org    if (shift != 0) {
1049d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org      shrp(reg, Immediate(shift));
1050d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org    }
1051895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org    andp(reg, Immediate(mask));
1052355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  }
105340cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org
1054d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org  template<typename Field>
1055d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org  void DecodeFieldToSmi(Register reg) {
1056e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org    if (SmiValuesAre32Bits()) {
1057e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org      andp(reg, Immediate(Field::kMask));
1058e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org      shlp(reg, Immediate(kSmiShift - Field::kShift));
1059e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org    } else {
1060e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org      static const int shift = Field::kShift;
1061e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org      static const int mask = (Field::kMask >> Field::kShift) << kSmiTagSize;
1062e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(SmiValuesAre31Bits());
1063e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(kSmiShift == kSmiTagSize);
1064e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK((mask & 0x80000000u) == 0);
1065e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org      if (shift < kSmiShift) {
1066e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org        shlp(reg, Immediate(kSmiShift - shift));
1067e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org      } else if (shift > kSmiShift) {
1068e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org        sarp(reg, Immediate(shift - kSmiShift));
1069e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org      }
1070e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org      andp(reg, Immediate(mask));
1071e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org    }
1072d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org  }
1073d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org
1074c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  // Abort execution if argument is not a number, enabled via --debug-code.
1075c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  void AssertNumber(Register object);
10765c838251403b0be9a882540f1922577abba4c872ager@chromium.org
1077c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  // Abort execution if argument is a smi, enabled via --debug-code.
1078c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  void AssertNotSmi(Register object);
1079ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org
1080c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  // Abort execution if argument is not a smi, enabled via --debug-code.
1081c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  void AssertSmi(Register object);
1082c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  void AssertSmi(const Operand& object);
108325156ded31ef771a2d799ed902483d83b3ebcbdclrn@chromium.org
1084f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  // Abort execution if a 64 bit register containing a 32 bit payload does not
1085c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  // have zeros in the top 32 bits, enabled via --debug-code.
1086c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  void AssertZeroExtended(Register reg);
1087f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1088c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  // Abort execution if argument is not a string, enabled via --debug-code.
1089c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  void AssertString(Register object);
109049edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
1091750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  // Abort execution if argument is not a name, enabled via --debug-code.
1092750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  void AssertName(Register object);
1093750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org
10942904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org  // Abort execution if argument is not undefined or an AllocationSite, enabled
10952904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org  // via --debug-code.
10962904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org  void AssertUndefinedOrAllocationSite(Register object);
10972904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org
1098c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  // Abort execution if argument is not the root value with the given index,
1099c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  // enabled via --debug-code.
1100c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  void AssertRootValue(Register src,
1101c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org                       Heap::RootListIndex root_value_index,
1102594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org                       BailoutReason reason);
11035ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org
11049085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // ---------------------------------------------------------------------------
11059085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Exception handling
11069085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
110704e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // Push a new try handler and link it into try handler chain.
110878d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org  void PushTryHandler(StackHandler::Kind kind, int handler_index);
11099085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
111013bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  // Unlink the stack handler on top of the stack from the try handler chain.
111113bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  void PopTryHandler();
11129085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
111349edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  // Activate the top handler in the try hander chain and pass the
111449edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  // thrown value.
111549edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  void Throw(Register value);
111649edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
111749edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  // Propagate an uncatchable exception out of the current JS stack.
111865a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  void ThrowUncatchable(Register value);
111949edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
11209085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // ---------------------------------------------------------------------------
11219085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Inline caching support
11229085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
11239085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Generate code for checking access rights - used for security checks
11249085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // on access to global objects across environments. The holder register
1125e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  // is left untouched, but the scratch register and kScratchRegister,
1126e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  // which must be different, are clobbered.
11279085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void CheckAccessGlobalProxy(Register holder_reg,
11289085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org                              Register scratch,
11299085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org                              Label* miss);
11309085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1131f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  void GetNumberHash(Register r0, Register scratch);
11329085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
11336db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  void LoadFromNumberDictionary(Label* miss,
11346db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org                                Register elements,
11356db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org                                Register key,
11366db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org                                Register r0,
11376db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org                                Register r1,
11386db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org                                Register r2,
11396db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org                                Register result);
11406db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
11416db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
11429085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // ---------------------------------------------------------------------------
114318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Allocation support
114418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
11452bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  // Allocate an object in new space or old pointer space. If the given space
11462bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  // is exhausted control continues at the gc_required label. The allocated
11472bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  // object is returned in result and end of the new object is returned in
11482bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  // result_end. The register scratch can be passed as no_reg in which case
11492bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  // an additional object reference will be added to the reloc info. The
11502bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  // returned pointers in result and result_end have not yet been tagged as
11512bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  // heap objects. If result_contains_top_on_entry is true the content of
11522bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  // result is known to be the allocation top on entry (could be result_end
11532bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  // from a previous call). If result_contains_top_on_entry is true scratch
115418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // should be no_reg as it is never used.
11552bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  void Allocate(int object_size,
11562bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org                Register result,
11572bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org                Register result_end,
11582bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org                Register scratch,
11592bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org                Label* gc_required,
11602bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org                AllocationFlags flags);
1161c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org
1162f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  void Allocate(int header_size,
1163f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                ScaleFactor element_size,
1164f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                Register element_count,
1165f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                Register result,
1166f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                Register result_end,
1167f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                Register scratch,
1168f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                Label* gc_required,
1169f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                AllocationFlags flags);
1170f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org
1171f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  void Allocate(Register object_size,
1172f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                Register result,
1173f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                Register result_end,
1174f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                Register scratch,
1175f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                Label* gc_required,
1176f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                AllocationFlags flags);
117718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
117818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Undo allocation in new space. The object passed and objects allocated after
117918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // it will no longer be allocated. Make sure that no pointers are left to the
118018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // object(s) no longer allocated as they would be invalid when allocation is
118118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // un-done.
118218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  void UndoAllocationInNewSpace(Register object);
118318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
11843811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  // Allocate a heap number in new space with undefined value. Returns
11853811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  // tagged pointer in result register, or jumps to gc_required if new
11863811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  // space is full.
11873811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  void AllocateHeapNumber(Register result,
11883811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org                          Register scratch,
118958a725587734a6889c689668fd01f0157ed749a6machenbach@chromium.org                          Label* gc_required,
119058a725587734a6889c689668fd01f0157ed749a6machenbach@chromium.org                          MutableMode mode = IMMUTABLE);
11913811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
119213bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  // Allocate a sequential string. All the header fields of the string object
119313bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  // are initialized.
119413bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  void AllocateTwoByteString(Register result,
119513bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                             Register length,
119613bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                             Register scratch1,
119713bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                             Register scratch2,
119813bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                             Register scratch3,
119913bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                             Label* gc_required);
12002c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  void AllocateOneByteString(Register result, Register length,
12012c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org                             Register scratch1, Register scratch2,
12022c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org                             Register scratch3, Label* gc_required);
120313bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org
120413bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  // Allocate a raw cons string object. Only the map field of the result is
120513bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  // initialized.
12061805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  void AllocateTwoByteConsString(Register result,
120713bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                          Register scratch1,
120813bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                          Register scratch2,
120913bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org                          Label* gc_required);
12102c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  void AllocateOneByteConsString(Register result, Register scratch1,
12112c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org                                 Register scratch2, Label* gc_required);
121213bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org
12131805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  // Allocate a raw sliced string object. Only the map field of the result is
12141805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  // initialized.
12151805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  void AllocateTwoByteSlicedString(Register result,
12161805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org                            Register scratch1,
12171805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org                            Register scratch2,
12181805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org                            Label* gc_required);
12192c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  void AllocateOneByteSlicedString(Register result, Register scratch1,
12202c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org                                   Register scratch2, Label* gc_required);
12211805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
122218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // ---------------------------------------------------------------------------
12239085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Support functions.
12249085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
12259085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Check if result is zero and op is negative.
12269085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void NegativeZeroTest(Register result, Register op, Label* then_label);
12279085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
12289085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Check if result is zero and op is negative in code using jump targets.
12299085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void NegativeZeroTest(CodeGenerator* cgen,
12309085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org                        Register result,
12319085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org                        Register op,
12329085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org                        JumpTarget* then_target);
12339085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
12349085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Check if result is zero and any of op1 and op2 are negative.
12359085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Register scratch is destroyed, and it must be different from op2.
12369085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void NegativeZeroTest(Register result, Register op1, Register op2,
12379085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org                        Register scratch, Label* then_label);
12389085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
12399085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Try to get function prototype of a function and puts the value in
12409085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // the result register. Checks that the function really is a
12419085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // function and jumps to the miss label if the fast checks fail. The
124286f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  // function register will be untouched; the other register may be
12439085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // clobbered.
12449085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void TryGetFunctionPrototype(Register function,
12459085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org                               Register result,
1246394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                               Label* miss,
1247394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                               bool miss_on_bound_function = false);
12489085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1249d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  // Picks out an array index from the hash field.
1250d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  // Register use:
1251d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  //   hash - holds the index's hash. Clobbered.
1252d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  //   index - holds the overwritten index on exit.
1253d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  void IndexFromHash(Register hash, Register index);
1254d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org
1255ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org  // Find the function context up the context chain.
1256ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org  void LoadContext(Register dst, int context_chain_length);
1257ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org
12581145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org  // Conditionally load the cached Array transitioned map of type
125946839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  // transitioned_kind from the native context if the map in register
126046839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  // map_in_out is the cached Array map in the native context of
12611145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org  // expected_kind.
12621145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org  void LoadTransitionedArrayMapConditional(
12631145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org      ElementsKind expected_kind,
12641145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org      ElementsKind transitioned_kind,
12651145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org      Register map_in_out,
12661145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org      Register scratch,
12671145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org      Label* no_map_match);
12681145ef852a4e230e1f642eecd8de155f2b26bc53jkummerow@chromium.org
12695f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  // Load the global function with the given index.
12705f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  void LoadGlobalFunction(int index, Register function);
12715f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org
12725f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  // Load the initial map from the global function. The registers
12735f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  // function and map can be the same.
12745f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  void LoadGlobalFunctionInitialMap(Register function, Register map);
12755f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org
12769085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // ---------------------------------------------------------------------------
12779085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Runtime calls
12789085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
12799085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Call a code stub.
1280471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org  void CallStub(CodeStub* stub, TypeFeedbackId ast_id = TypeFeedbackId::None());
12819085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
128213bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  // Tail call a code stub (jump).
128313bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org  void TailCallStub(CodeStub* stub);
128413bd294acf56c7f824d92d4941a2aeb3cec58e0ckmillikin@chromium.org
12859085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Return from a code stub after popping its arguments.
12869085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void StubReturn(int argc);
12879085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
12889085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Call a runtime routine.
1289fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  void CallRuntime(const Runtime::Function* f,
1290fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org                   int num_arguments,
1291fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org                   SaveFPRegsMode save_doubles = kDontSaveFPRegs);
12929085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
12930ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  // Call a runtime function and save the value of XMM registers.
1294fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  void CallRuntimeSaveDoubles(Runtime::FunctionId id) {
1295fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org    const Runtime::Function* function = Runtime::FunctionForId(id);
1296fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org    CallRuntime(function, function->nargs, kSaveFPRegs);
1297fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  }
12980ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org
12999085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Convenience function: Same as above, but takes the fid instead.
1300f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  void CallRuntime(Runtime::FunctionId id,
1301f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                   int num_arguments,
1302f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                   SaveFPRegsMode save_doubles = kDontSaveFPRegs) {
1303f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org    CallRuntime(Runtime::FunctionForId(id), num_arguments, save_doubles);
1304fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  }
13059085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
13065c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Convenience function: call an external reference.
13075c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void CallExternalReference(const ExternalReference& ext,
13085c838251403b0be9a882540f1922577abba4c872ager@chromium.org                             int num_arguments);
13095c838251403b0be9a882540f1922577abba4c872ager@chromium.org
13109085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Tail call of a runtime routine (jump).
1311ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org  // Like JumpToExternalReference, but also takes care of passing the number
1312ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org  // of parameters.
1313ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org  void TailCallExternalReference(const ExternalReference& ext,
1314ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org                                 int num_arguments,
1315ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org                                 int result_size);
1316ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org
1317ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org  // Convenience function: tail call a runtime routine (jump).
1318ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org  void TailCallRuntime(Runtime::FunctionId fid,
1319a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org                       int num_arguments,
1320a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org                       int result_size);
13219085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1322c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // Jump to a runtime routine.
1323ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org  void JumpToExternalReference(const ExternalReference& ext, int result_size);
13249085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1325c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // Prepares stack to put arguments (aligns and so on).  WIN64 calling
1326c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // convention requires to put the pointer to the return value slot into
1327c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // rcx (rcx must be preserverd until CallApiFunctionAndReturn).  Saves
1328c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // context (rsi).  Clobbers rax.  Allocates arg_stack_space * kPointerSize
13294a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  // inside the exit frame (not GCed) accessible via StackSpaceOperand.
1330662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  void PrepareCallApiFunction(int arg_stack_space);
13314a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com
1332c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // Calls an API function.  Allocates HandleScope, extracts returned value
1333c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // from handle and propagates exceptions.  Clobbers r14, r15, rbx and
1334c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // caller-save registers.  Restores context.  On return removes
1335c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // stack_space * kPointerSize (GCed).
1336e014e5bf9ccd6a759add3b35ba610f3a0c752a90machenbach@chromium.org  void CallApiFunctionAndReturn(Register function_address,
1337a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org                                ExternalReference thunk_ref,
1338b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org                                Register thunk_last_arg,
1339bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org                                int stack_space,
1340528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                                Operand return_value_operand,
1341528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                                Operand* context_restore_operand);
1342303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org
1343b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Before calling a C-function from generated code, align arguments on stack.
1344c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org  // After aligning the frame, arguments must be stored in rsp[0], rsp[8],
1345b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // etc., not pushed. The argument count assumes all arguments are word sized.
1346b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // The number of slots reserved for arguments depends on platform. On Windows
1347b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // stack slots are reserved for the arguments passed in registers. On other
1348b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // platforms stack slots are only reserved for the arguments actually passed
1349b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // on the stack.
1350b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void PrepareCallCFunction(int num_arguments);
1351b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
1352b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Calls a C function and cleans up the space for arguments allocated
1353b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // by PrepareCallCFunction. The called function is not allowed to trigger a
1354b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // garbage collection, since that might move the code and invalidate the
1355b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // return address (unless this is somehow accounted for by the called
1356b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // function).
1357b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void CallCFunction(ExternalReference function, int num_arguments);
1358b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void CallCFunction(Register function, int num_arguments);
1359b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
1360b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Calculate the number of stack slots to reserve for arguments when calling a
1361b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // C function.
1362b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  int ArgumentStackSlotsForCFunctionCall(int num_arguments);
13639085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
13649085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // ---------------------------------------------------------------------------
13659085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Utilities
13669085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
13679085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void Ret();
13689085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1369d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  // Return and drop arguments from stack, where the number of arguments
1370d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  // may be bigger than 2^16 - 1.  Requires a scratch register.
1371d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  void Ret(int bytes_dropped, Register scratch);
1372d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com
1373c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  Handle<Object> CodeObject() {
1374e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!code_object_.is_null());
1375c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org    return code_object_;
1376c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  }
13779085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
13787979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Copy length bytes from source to destination.
13797979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Uses scratch register internally (if you have a low-eight register
13807979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // free, do use it, otherwise kScratchRegister will be used).
13817979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // The min_length is a minimum limit on the value that length will have.
13827979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // The algorithm has some special cases that might be omitted if the string
13837979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // is known to always be long.
13847979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  void CopyBytes(Register destination,
13857979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org                 Register source,
13867979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org                 Register length,
13877979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org                 int min_length = 0,
13887979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org                 Register scratch = kScratchRegister);
13897979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
1390c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Initialize fields with filler values.  Fields starting at |start_offset|
1391c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // not including end_offset are overwritten with the value in |filler|.  At
1392c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // the end the loop, |start_offset| takes the value of |end_offset|.
1393c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void InitializeFieldsWithFiller(Register start_offset,
1394c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                  Register end_offset,
1395c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                  Register filler);
1396c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
13979085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1398763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  // Emit code for a truncating division by a constant. The dividend register is
1399bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org  // unchanged, the result is in rdx, and rax gets clobbered.
1400763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  void TruncatingDiv(Register dividend, int32_t divisor);
1401bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org
14029085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // ---------------------------------------------------------------------------
14039085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // StatsCounter support
14049085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
14059085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void SetCounter(StatsCounter* counter, int value);
14069085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void IncrementCounter(StatsCounter* counter, int value);
14079085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void DecrementCounter(StatsCounter* counter, int value);
14089085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
14099085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
14109085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // ---------------------------------------------------------------------------
14119085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Debugging
14129085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
14139085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Calls Abort(msg) if the condition cc is not satisfied.
14149085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Use --debug_code to enable.
1415594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  void Assert(Condition cc, BailoutReason reason);
14169085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
14170b9f850f0e9dc624b9e0c5254393112ecc7f8bc9ricow@chromium.org  void AssertFastElements(Register elements);
14180b9f850f0e9dc624b9e0c5254393112ecc7f8bc9ricow@chromium.org
14199085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Like Assert(), but always enabled.
1420594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  void Check(Condition cc, BailoutReason reason);
14219085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
14229085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Print a message to stdout and abort execution.
1423594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  void Abort(BailoutReason msg);
14249085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1425c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org  // Check that the stack is aligned.
1426c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org  void CheckStackAlignment();
1427c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org
14289085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Verify restrictions about code generated in stubs.
14299085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void set_generating_stub(bool value) { generating_stub_ = value; }
14309085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  bool generating_stub() { return generating_stub_; }
1431c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void set_has_frame(bool value) { has_frame_ = value; }
1432c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  bool has_frame() { return has_frame_; }
1433c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  inline bool AllowThisStubCall(CodeStub* stub);
14349085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
143544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  static int SafepointRegisterStackIndex(Register reg) {
143644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    return SafepointRegisterStackIndex(reg.code());
143744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  }
143844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
1439c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Activation support.
1440c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void EnterFrame(StackFrame::Type type);
1441c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void LeaveFrame(StackFrame::Type type);
1442c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1443be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.org  // Expects object in rax and returns map with validated enum cache
1444be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.org  // in rax.  Assumes that any other register can be used as a scratch.
1445be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.org  void CheckEnumCache(Register null_value,
1446be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.org                      Label* call_runtime);
1447be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.org
1448ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // AllocationMemento support. Arrays may have an associated
1449ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // AllocationMemento object that can be checked for in order to pretransition
145059297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  // to another type.
145159297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  // On entry, receiver_reg should point to the array object.
145259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  // scratch_reg gets clobbered.
1453b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org  // If allocation info is present, condition flags are set to equal.
1454ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  void TestJSArrayForAllocationMemento(Register receiver_reg,
1455b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org                                       Register scratch_reg,
1456b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org                                       Label* no_memento_found);
1457b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org
1458b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org  void JumpIfJSArrayHasAllocationMemento(Register receiver_reg,
1459b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org                                         Register scratch_reg,
1460b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org                                         Label* memento_found) {
1461b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org    Label no_memento_found;
1462b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org    TestJSArrayForAllocationMemento(receiver_reg, scratch_reg,
1463b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org                                    &no_memento_found);
1464b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org    j(equal, memento_found);
1465b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org    bind(&no_memento_found);
1466b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org  }
146759297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org
1468e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  // Jumps to found label if a prototype map has dictionary elements.
1469e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  void JumpIfDictionaryInPrototypeChain(Register object, Register scratch0,
1470e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org                                        Register scratch1, Label* found);
1471e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org
14729085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org private:
14730ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  // Order general registers are pushed by Pushad.
1474b08986cb66c3f6687247cb6da186c1e73057e399whesse@chromium.org  // rax, rcx, rdx, rbx, rsi, rdi, r8, r9, r11, r14, r15.
14751456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  static const int kSafepointPushRegisterIndices[Register::kNumRegisters];
147649edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  static const int kNumSafepointSavedRegisters = 11;
147783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static const int kSmiShift = kSmiTagSize + kSmiShiftSize;
147849edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
14799085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  bool generating_stub_;
1480c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  bool has_frame_;
1481ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  bool root_array_available_;
148269ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org
148369ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  // Returns a register holding the smi value. The register MUST NOT be
148469ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  // modified. It may be the "smi 1 constant" register.
148569ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  Register GetSmiConstant(Smi* value);
148669ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org
14874ef23eea527ce7f45bdc5edd52bd4d1a989e2359machenbach@chromium.org  int64_t RootRegisterDelta(ExternalReference other);
1488000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.org
148969ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  // Moves the smi value to the destination register.
149069ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org  void LoadSmiConstant(Register dst, Smi* value);
149169ea3965ef6e0d3f020a402cf7e6b96b9cb651aekmillikin@chromium.org
14925c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // This handle will be patched with the code object on installation.
14935c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Handle<Object> code_object_;
14949085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
14959085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Helper functions for generating invokes.
14969085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void InvokePrologue(const ParameterCount& expected,
14979085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org                      const ParameterCount& actual,
14989085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org                      Handle<Code> code_constant,
1499eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org                      Register code_register,
150083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                      Label* done,
15012efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org                      bool* definitely_mismatches,
15023a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                      InvokeFlag flag,
150340cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org                      Label::Distance near_jump = Label::kFar,
1504e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org                      const CallWrapper& call_wrapper = NullCallWrapper());
15059085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1506d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  void EnterExitFramePrologue(bool save_rax);
15074a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com
15084a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  // Allocates arg_stack_space * kPointerSize memory (not GCed) on the stack
15094a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  // accessible via StackSpaceOperand.
15100ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  void EnterExitFrameEpilogue(int arg_stack_space, bool save_doubles);
15114a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com
1512528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  void LeaveExitFrameEpilogue(bool restore_context);
1513e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org
151418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Allocation support helpers.
1515ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  // Loads the top of new-space into the result register.
1516ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  // Otherwise the address of the new-space top is loaded into scratch (if
1517ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  // scratch is valid), and the new-space top is loaded into result.
151818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  void LoadAllocationTopHelper(Register result,
151918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org                               Register scratch,
1520a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org                               AllocationFlags flags);
15212bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org
152238de99aae2d4efc5796aa6935c1648447ec32fc8machenbach@chromium.org  void MakeSureDoubleAlignedHelper(Register result,
152338de99aae2d4efc5796aa6935c1648447ec32fc8machenbach@chromium.org                                   Register scratch,
152438de99aae2d4efc5796aa6935c1648447ec32fc8machenbach@chromium.org                                   Label* gc_required,
152538de99aae2d4efc5796aa6935c1648447ec32fc8machenbach@chromium.org                                   AllocationFlags flags);
152638de99aae2d4efc5796aa6935c1648447ec32fc8machenbach@chromium.org
1527ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  // Update allocation top with value in result_end register.
1528ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  // If scratch is valid, it contains the address of the allocation top.
15292bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  void UpdateAllocationTopHelper(Register result_end,
15302bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org                                 Register scratch,
15312bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org                                 AllocationFlags flags);
1532e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org
1533c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Helper for implementing JumpIfNotInNewSpace and JumpIfInNewSpace.
1534c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void InNewSpace(Register object,
1535c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                  Register scratch,
1536c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                  Condition cc,
1537c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                  Label* branch,
1538c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                  Label::Distance distance = Label::kFar);
1539c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1540c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Helper for finding the mark bits for an address.  Afterwards, the
1541c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // bitmap register points at the word with the mark bits and the mask
1542c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // the position of the first bit.  Uses rcx as scratch and leaves addr_reg
1543c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // unchanged.
1544c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  inline void GetMarkBits(Register addr_reg,
1545c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                          Register bitmap_reg,
1546c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                          Register mask_reg);
15473a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
154804e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // Helper for throwing exceptions.  Compute a handler address and jump to
154904e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // it.  See the implementation for register usage.
155004e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  void JumpToHandlerEntry();
155104e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org
15523a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // Compute memory operands for safepoint stack slots.
15533a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  Operand SafepointRegisterSlot(Register reg);
15543a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  static int SafepointRegisterStackIndex(int reg_code) {
15553a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    return kNumSafepointRegisters - kSafepointPushRegisterIndices[reg_code] - 1;
15563a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  }
15573a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
1558a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // Needs access to SafepointRegisterStackIndex for compiled frame
15593a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // traversal.
1560a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  friend class StandardFrame;
15619085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org};
15629085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
15639085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
15644af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org// The code patcher is used to patch (typically) small parts of code e.g. for
15654af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org// debugging and other types of instrumentation. When using the code patcher
15664af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org// the exact number of bytes specified must be emitted. Is not legal to emit
15674af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org// relocation information. If any of these constraints are violated it causes
15684af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org// an assertion.
15694af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.orgclass CodePatcher {
15704af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org public:
15714af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  CodePatcher(byte* address, int size);
15724af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  virtual ~CodePatcher();
15734af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
15744af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  // Macro assembler to emit code.
15754af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  MacroAssembler* masm() { return &masm_; }
15764af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
15774af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org private:
15784af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  byte* address_;  // The address of the code being patched.
15794af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  int size_;  // Number of bytes of the expected patch size.
15804af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  MacroAssembler masm_;  // Macro assembler used to generate the code.
15814af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org};
15824af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
15834af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
15849085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// -----------------------------------------------------------------------------
15859085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// Static helper functions.
15869085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
15879085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// Generate an Operand for loading a field from an object.
15881b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.orginline Operand FieldOperand(Register object, int offset) {
15899085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  return Operand(object, offset - kHeapObjectTag);
15909085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org}
15919085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
15929085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
15939085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// Generate an Operand for loading an indexed field from an object.
15941b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.orginline Operand FieldOperand(Register object,
15951b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org                            Register index,
15961b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org                            ScaleFactor scale,
15971b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org                            int offset) {
15989085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  return Operand(object, index, scale, offset - kHeapObjectTag);
15999085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org}
16009085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
16019085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
16021b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.orginline Operand ContextOperand(Register context, int index) {
16034a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  return Operand(context, Context::SlotOffset(index));
16044a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com}
16054a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com
16064a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com
16071b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.orginline Operand GlobalObjectOperand() {
160846839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  return ContextOperand(rsi, Context::GLOBAL_OBJECT_INDEX);
16094a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com}
16104a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com
16114a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com
16124a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com// Provides access to exit frame stack space (not GCed).
16131b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.orginline Operand StackSpaceOperand(int index) {
16144a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com#ifdef _WIN64
16154a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  const int kShaddowSpace = 4;
16164a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  return Operand(rsp, (index + kShaddowSpace) * kPointerSize);
16174a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com#else
16184a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  return Operand(rsp, index * kPointerSize);
16194a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com#endif
16204a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com}
16214a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com
16224a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com
1623d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.orginline Operand StackOperandForReturnAddress(int32_t disp) {
1624d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org  return Operand(rsp, disp);
1625d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org}
1626d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org
16274a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com
16289085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#ifdef GENERATED_CODE_COVERAGE
16299085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgextern void LogGeneratedCodeCoverage(const char* file_line);
16309085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#define CODE_COVERAGE_STRINGIFY(x) #x
16319085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x)
16329085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__)
16334cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org#define ACCESS_MASM(masm) {                                                  \
16344cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org    Address x64_coverage_function = FUNCTION_ADDR(LogGeneratedCodeCoverage); \
16354cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org    masm->pushfq();                                                          \
16364cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org    masm->Pushad();                                                          \
1637763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org    masm->Push(Immediate(reinterpret_cast<int>(&__FILE_LINE__)));            \
16384cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org    masm->Call(x64_coverage_function, RelocInfo::EXTERNAL_REFERENCE);        \
1639763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org    masm->Pop(rax);                                                          \
16404cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org    masm->Popad();                                                           \
16414cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org    masm->popfq();                                                           \
16424cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org  }                                                                          \
16439085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  masm->
16449085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#else
16459085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#define ACCESS_MASM(masm) masm->
16469085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#endif
16479085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
16489085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org} }  // namespace v8::internal
16499085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
16509085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#endif  // V8_X64_MACRO_ASSEMBLER_X64_H_
1651