macro-assembler-arm.h revision 3ef787dbeca8a5fb1086949cda830dccee07bfbd
13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef V8_ARM_MACRO_ASSEMBLER_ARM_H_
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define V8_ARM_MACRO_ASSEMBLER_ARM_H_
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "assembler.h"
323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "frames.h"
33257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#include "v8globals.h"
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// ----------------------------------------------------------------------------
393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Static helper functions
403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Generate a MemOperand for loading a field from an object.
423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochinline MemOperand FieldMemOperand(Register object, int offset) {
433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  return MemOperand(object, offset - kHeapObjectTag);
443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochinline Operand SmiUntagOperand(Register object) {
481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return Operand(object, ASR, kSmiTagSize);
491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Give alias names to registers
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst Register cp = { 8 };  // JavaScript context pointer
55c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdochconst Register kRootRegister = { 10 };  // Roots array pointer.
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen// Flags used for the AllocateInNewSpace functions.
5825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsenenum AllocationFlags {
5925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // No special flags.
6025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  NO_ALLOCATION_FLAGS = 0,
6125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // Return the pointer to the allocated already tagged as a heap object.
6225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  TAG_OBJECT = 1 << 0,
6325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // The content of the result register already contains the allocation top in
6425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // new space.
6525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  RESULT_CONTAINS_TOP = 1 << 1,
6625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // Specify that the requested size of the space to allocate is specified in
6725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // words instead of bytes.
6825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  SIZE_IN_WORDS = 1 << 2
6925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen};
7025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
7125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
728defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Flags used for the ObjectToDoubleVFPRegister function.
738defd9ff6930b4e24729971a61cf7469daf119beSteve Blockenum ObjectToDoubleFlags {
748defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // No special flags.
758defd9ff6930b4e24729971a61cf7469daf119beSteve Block  NO_OBJECT_TO_DOUBLE_FLAGS = 0,
768defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Object is known to be a non smi.
778defd9ff6930b4e24729971a61cf7469daf119beSteve Block  OBJECT_NOT_SMI = 1 << 0,
788defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Don't load NaNs or infinities, branch to the non number case instead.
798defd9ff6930b4e24729971a61cf7469daf119beSteve Block  AVOID_NANS_AND_INFINITIES = 1 << 1
808defd9ff6930b4e24729971a61cf7469daf119beSteve Block};
818defd9ff6930b4e24729971a61cf7469daf119beSteve Block
828defd9ff6930b4e24729971a61cf7469daf119beSteve Block
833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochenum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET };
843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochenum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK };
853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochenum LinkRegisterStatus { kLRHasNotBeenSaved, kLRHasBeenSaved };
863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool AreAliased(Register r1, Register r2, Register r3, Register r4);
893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// MacroAssembler implements a collection of frequently used macros.
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass MacroAssembler: public Assembler {
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // The isolate parameter can be NULL if the macro assembler should
958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // not use isolate-dependent functionality. In this case, it's the
968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // responsibility of the caller to never invoke such function on the
978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // macro assembler.
988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  MacroAssembler(Isolate* isolate, void* buffer, int size);
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Jump, Call, and Ret pseudo instructions implementing inter-working.
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Jump(Register target, Condition cond = al);
1023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void Jump(Address target, RelocInfo::Mode rmode, Condition cond = al);
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Jump(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al);
10442effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  static int CallSize(Register target, Condition cond = al);
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Call(Register target, Condition cond = al);
1063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  static int CallSize(Address target,
10742effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch                      RelocInfo::Mode rmode,
10842effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch                      Condition cond = al);
1093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void Call(Address target, RelocInfo::Mode rmode, Condition cond = al);
1103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  static int CallSize(Handle<Code> code,
1113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                      RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
1123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                      unsigned ast_id = kNoASTId,
1133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                      Condition cond = al);
114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void Call(Handle<Code> code,
1153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
1163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            unsigned ast_id = kNoASTId,
117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            Condition cond = al);
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Ret(Condition cond = al);
119e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
120e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Emit code to discard a non-negative number of pointer-sized elements
121e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // from the stack, clobbering only the sp register.
122e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void Drop(int count, Condition cond = al);
123e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void Ret(int drop, Condition cond = al);
1256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Swap two registers.  If the scratch register is omitted then a slightly
1276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // less efficient form using xor instead of mov is emitted.
1287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  void Swap(Register reg1,
1297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            Register reg2,
1307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            Register scratch = no_reg,
1317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            Condition cond = al);
1326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1339dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
1349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  void And(Register dst, Register src1, const Operand& src2,
1359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen           Condition cond = al);
1369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  void Ubfx(Register dst, Register src, int lsb, int width,
1379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen            Condition cond = al);
1389dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  void Sbfx(Register dst, Register src, int lsb, int width,
1399dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen            Condition cond = al);
140e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // The scratch register is not used for ARMv7.
141e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // scratch can be the same register as src (in which case it is trashed), but
142e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // not the same as dst.
143e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void Bfi(Register dst,
144e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch           Register src,
145e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch           Register scratch,
146e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch           int lsb,
147e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch           int width,
148e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch           Condition cond = al);
1499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  void Bfc(Register dst, int lsb, int width, Condition cond = al);
15050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  void Usat(Register dst, int satpos, const Operand& src,
15150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen            Condition cond = al);
1529dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
153e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void Call(Label* target);
154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Register move. May do nothing if the registers are identical.
156e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void Move(Register dst, Handle<Object> value);
1573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void Move(Register dst, Register src, Condition cond = al);
158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void Move(DoubleRegister dst, DoubleRegister src);
159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load an object from the root table.
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void LoadRoot(Register destination,
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                Heap::RootListIndex index,
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                Condition cond = al);
16425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // Store an object to the root table.
16525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  void StoreRoot(Register source,
16625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen                 Heap::RootListIndex index,
16725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen                 Condition cond = al);
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void LoadHeapObject(Register dst, Handle<HeapObject> object);
170c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
1713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void LoadObject(Register result, Handle<Object> object) {
1723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (object->IsHeapObject()) {
1733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      LoadHeapObject(result, Handle<HeapObject>::cast(object));
1743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
1753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Move(result, object);
1763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ---------------------------------------------------------------------------
1803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // GC Support
1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void IncrementalMarkingRecordWriteHelper(Register object,
1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           Register value,
1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           Register address);
1853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  enum RememberedSetFinalAction {
1873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    kReturnAtEnd,
1883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    kFallThroughAtEnd
1893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
1903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Record in the remembered set the fact that we have a pointer to new space
1923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // at the address pointed to by the addr register.  Only works if addr is not
1933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // in new space.
1943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void RememberedSetHelper(Register object,  // Used for debug code.
1953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Register addr,
1963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Register scratch,
1973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           SaveFPRegsMode save_fp,
1983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           RememberedSetFinalAction and_then);
1993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CheckPageFlag(Register object,
2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     Register scratch,
2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     int mask,
2033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     Condition cc,
2043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     Label* condition_met);
2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if object is in new space.  Jumps if the object is not in new space.
2073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The register scratch can be object itself, but scratch will be clobbered.
2083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void JumpIfNotInNewSpace(Register object,
2093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Register scratch,
2103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Label* branch) {
2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    InNewSpace(object, scratch, ne, branch);
2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if object is in new space.  Jumps if the object is in new space.
2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The register scratch can be object itself, but it will be clobbered.
2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void JumpIfInNewSpace(Register object,
2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Register scratch,
2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Label* branch) {
2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    InNewSpace(object, scratch, eq, branch);
2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if an object has a given incremental marking color.
2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void HasColor(Register object,
2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                Register scratch0,
2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                Register scratch1,
2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                Label* has_color,
2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                int first_bit,
2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                int second_bit);
2298defd9ff6930b4e24729971a61cf7469daf119beSteve Block
2303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void JumpIfBlack(Register object,
2319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                   Register scratch0,
2323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   Register scratch1,
2333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   Label* on_black);
2343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Checks the color of an object.  If the object is already grey or black
2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // then we just fall through, since it is already live.  If it is white and
2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // we can determine that it doesn't need to be scanned, then we just mark it
2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // black and fall through.  For the rest we jump to the label so the
2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // incremental marker can fix its assumptions.
2403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void EnsureNotWhite(Register object,
2413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      Register scratch1,
2423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      Register scratch2,
2433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      Register scratch3,
2443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      Label* object_is_white_and_not_data);
2453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Detects conservatively whether an object is data-only, i.e. it does need to
2473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // be scanned by the garbage collector.
2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void JumpIfDataObject(Register value,
2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Register scratch,
2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Label* not_data_object);
2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Notify the garbage collector that we wrote a pointer into an object.
2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // |object| is the object being stored into, |value| is the object being
2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // stored.  value and scratch registers are clobbered by the operation.
2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The offset is the offset from the start of the object, not the offset from
2563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the tagged HeapObject pointer.  For use with FieldOperand(reg, off).
2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void RecordWriteField(
2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register object,
2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      int offset,
2603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register value,
2613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register scratch,
2623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      LinkRegisterStatus lr_status,
2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SaveFPRegsMode save_fp,
2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SmiCheck smi_check = INLINE_SMI_CHECK);
2663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // As above, but the offset has the tag presubtracted.  For use with
2683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // MemOperand(reg, off).
2693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline void RecordWriteContextSlot(
2703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register context,
2713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      int offset,
2723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register value,
2733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register scratch,
2743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      LinkRegisterStatus lr_status,
2753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SaveFPRegsMode save_fp,
2763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SmiCheck smi_check = INLINE_SMI_CHECK) {
2783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RecordWriteField(context,
2793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     offset + kHeapObjectTag,
2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     value,
2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     scratch,
2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     lr_status,
2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     save_fp,
2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     remembered_set_action,
2853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     smi_check);
2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
287592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
2883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // For a given |object| notify the garbage collector that the slot |address|
2893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // has been written.  |value| is the object being stored. The value and
2903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // address registers are clobbered by the operation.
2913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void RecordWrite(
2923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register object,
2933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register address,
2943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register value,
2953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      LinkRegisterStatus lr_status,
2963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SaveFPRegsMode save_fp,
2973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
2983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SmiCheck smi_check = INLINE_SMI_CHECK);
2998defd9ff6930b4e24729971a61cf7469daf119beSteve Block
3003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Push a handle.
3013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void Push(Handle<Object> handle);
3023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Push two registers.  Pushes leftmost register first (to highest address).
3046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void Push(Register src1, Register src2, Condition cond = al) {
3056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(!src1.is(src2));
3066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (src1.code() > src2.code()) {
3076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      stm(db_w, sp, src1.bit() | src2.bit(), cond);
3086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
3096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      str(src1, MemOperand(sp, 4, NegPreIndex), cond);
3106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      str(src2, MemOperand(sp, 4, NegPreIndex), cond);
3116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
3126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Push three registers.  Pushes leftmost register first (to highest address).
3156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void Push(Register src1, Register src2, Register src3, Condition cond = al) {
3166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(!src1.is(src2));
3176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(!src2.is(src3));
3186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(!src1.is(src3));
3196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (src1.code() > src2.code()) {
3206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (src2.code() > src3.code()) {
3216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
3226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      } else {
3236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        stm(db_w, sp, src1.bit() | src2.bit(), cond);
3246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        str(src3, MemOperand(sp, 4, NegPreIndex), cond);
3256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
3266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
3276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      str(src1, MemOperand(sp, 4, NegPreIndex), cond);
3286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Push(src2, src3, cond);
3296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
3306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Push four registers.  Pushes leftmost register first (to highest address).
3333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Push(Register src1,
3343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Register src2,
3353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Register src3,
3363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Register src4,
3373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Condition cond = al) {
3386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(!src1.is(src2));
3396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(!src2.is(src3));
3406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(!src1.is(src3));
3416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(!src1.is(src4));
3426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(!src2.is(src4));
3436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(!src3.is(src4));
3446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (src1.code() > src2.code()) {
3456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (src2.code() > src3.code()) {
3466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        if (src3.code() > src4.code()) {
3476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          stm(db_w,
3486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              sp,
3496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              src1.bit() | src2.bit() | src3.bit() | src4.bit(),
3506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              cond);
3516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        } else {
3526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
3536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          str(src4, MemOperand(sp, 4, NegPreIndex), cond);
3546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
3556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      } else {
3566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        stm(db_w, sp, src1.bit() | src2.bit(), cond);
3576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Push(src3, src4, cond);
3586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
3596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
3606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      str(src1, MemOperand(sp, 4, NegPreIndex), cond);
3616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Push(src2, src3, src4, cond);
3626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
3636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
365e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Pop two registers. Pops rightmost register first (from lower address).
366e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void Pop(Register src1, Register src2, Condition cond = al) {
367e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ASSERT(!src1.is(src2));
368e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (src1.code() > src2.code()) {
369e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      ldm(ia_w, sp, src1.bit() | src2.bit(), cond);
370e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
371e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      ldr(src2, MemOperand(sp, 4, PostIndex), cond);
372e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      ldr(src1, MemOperand(sp, 4, PostIndex), cond);
373e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
374e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
375e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Pop three registers.  Pops rightmost register first (from lower address).
3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Pop(Register src1, Register src2, Register src3, Condition cond = al) {
3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(!src1.is(src2));
3793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(!src2.is(src3));
3803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(!src1.is(src3));
3813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (src1.code() > src2.code()) {
3823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (src2.code() > src3.code()) {
3833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
3843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
3853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ldr(src3, MemOperand(sp, 4, PostIndex), cond);
3863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ldm(ia_w, sp, src1.bit() | src2.bit(), cond);
3873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
3883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
3893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Pop(src2, src3, cond);
3903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      str(src1, MemOperand(sp, 4, PostIndex), cond);
3913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
3923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Pop four registers.  Pops rightmost register first (from lower address).
3953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Pop(Register src1,
3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Register src2,
3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Register src3,
3983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Register src4,
3993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Condition cond = al) {
4003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(!src1.is(src2));
4013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(!src2.is(src3));
4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(!src1.is(src3));
4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(!src1.is(src4));
4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(!src2.is(src4));
4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(!src3.is(src4));
4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (src1.code() > src2.code()) {
4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (src2.code() > src3.code()) {
4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (src3.code() > src4.code()) {
4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ldm(ia_w,
4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              sp,
4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              src1.bit() | src2.bit() | src3.bit() | src4.bit(),
4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              cond);
4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ldr(src4, MemOperand(sp, 4, PostIndex), cond);
4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
4183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Pop(src3, src4, cond);
4193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ldm(ia_w, sp, src1.bit() | src2.bit(), cond);
4203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
4213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Pop(src2, src3, src4, cond);
4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ldr(src1, MemOperand(sp, 4, PostIndex), cond);
4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
4253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Push and pop the registers that can hold pointers, as defined by the
428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // RegList constant kSafepointSavedRegisters.
429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void PushSafepointRegisters();
430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void PopSafepointRegisters();
431b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void PushSafepointRegistersAndDoubles();
432b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void PopSafepointRegistersAndDoubles();
433e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Store value in register src in the safepoint stack slot for
434e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // register dst.
435e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void StoreToSafepointRegisterSlot(Register src, Register dst);
436e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void StoreToSafepointRegistersAndDoublesSlot(Register src, Register dst);
437e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Load the value of the src register from its safepoint stack slot
438e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // into register dst.
439e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void LoadFromSafepointRegisterSlot(Register dst, Register src);
440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
441f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load two consecutive registers with two consecutive memory locations.
442f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  void Ldrd(Register dst1,
443f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            Register dst2,
444f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            const MemOperand& src,
445f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            Condition cond = al);
446f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
447f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Store two consecutive registers to two consecutive memory locations.
448f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  void Strd(Register src1,
449f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            Register src2,
450f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            const MemOperand& dst,
451f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            Condition cond = al);
452f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
453b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Clear specified FPSCR bits.
454b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void ClearFPSCRBits(const uint32_t bits_to_clear,
455b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                      const Register scratch,
456b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                      const Condition cond = al);
457b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
458b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Compare double values and move the result to the normal condition flags.
459b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void VFPCompareAndSetFlags(const DwVfpRegister src1,
460b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                             const DwVfpRegister src2,
461b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                             const Condition cond = al);
462b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void VFPCompareAndSetFlags(const DwVfpRegister src1,
463b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                             const double src2,
464b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                             const Condition cond = al);
465b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
466b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Compare double values and then load the fpscr flags to a register.
467b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void VFPCompareAndLoadFlags(const DwVfpRegister src1,
468b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                              const DwVfpRegister src2,
469b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                              const Register fpscr_flags,
470b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                              const Condition cond = al);
471b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void VFPCompareAndLoadFlags(const DwVfpRegister src1,
472b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                              const double src2,
473b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                              const Register fpscr_flags,
474b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                              const Condition cond = al);
475b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
4763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void Vmov(const DwVfpRegister dst,
4773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            const double imm,
4783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            const Condition cond = al);
4793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
48080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Enter exit frame.
4811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // stack_space - extra stack space, used for alignment before call to C.
4821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void EnterExitFrame(bool save_doubles, int stack_space = 0);
483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Leave the current exit frame. Expects the return value in r0.
485e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Expect the number of values, pushed prior to the exit frame, to
486e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // remove in a register (or no_reg, if there is nothing to remove).
487e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void LeaveExitFrame(bool save_doubles, Register argument_count);
488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the actual activation frame alignment for target environment.
4906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static int ActivationFrameAlignment();
491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
492d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void LoadContext(Register dst, int context_chain_length);
493d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Conditionally load the cached Array transitioned map of type
4953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // transitioned_kind from the global context if the map in register
4963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // map_in_out is the cached Array map in the global context of
4973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // expected_kind.
4983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void LoadTransitionedArrayMapConditional(
4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ElementsKind expected_kind,
5003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ElementsKind transitioned_kind,
5013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register map_in_out,
5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register scratch,
5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label* no_map_match);
5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load the initial map for new Arrays from a JSFunction.
5063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void LoadInitialArrayMap(Register function_in,
5073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Register scratch,
5083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Register map_out);
5093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  void LoadGlobalFunction(int index, Register function);
5118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
5128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Load the initial map from the global function. The registers
5138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // function and map can be the same, function is then overwritten.
5148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  void LoadGlobalFunctionInitialMap(Register function,
5158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                    Register map,
5168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                    Register scratch);
5178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
518c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  void InitializeRootRegister() {
5193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ExternalReference roots_array_start =
5203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ExternalReference::roots_array_start(isolate());
5213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(kRootRegister, Operand(roots_array_start));
522c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  }
523c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // JavaScript invokes
526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up call kind marking in ecx. The method takes ecx as an
528257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // explicit first parameter to make the code more readable at the
529257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // call sites.
530257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void SetCallKind(Register dst, CallKind kind);
531257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Invoke the JavaScript function code by either calling or jumping.
533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void InvokeCode(Register code,
534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  const ParameterCount& expected,
535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  const ParameterCount& actual,
536b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                  InvokeFlag flag,
537257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  const CallWrapper& call_wrapper,
538257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  CallKind call_kind);
539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void InvokeCode(Handle<Code> code,
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  const ParameterCount& expected,
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  const ParameterCount& actual,
543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  RelocInfo::Mode rmode,
544257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  InvokeFlag flag,
545257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  CallKind call_kind);
546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Invoke the JavaScript function in the given register. Changes the
548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // current context to the context in the function before invoking.
549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void InvokeFunction(Register function,
550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      const ParameterCount& actual,
551b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                      InvokeFlag flag,
552257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      const CallWrapper& call_wrapper,
553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      CallKind call_kind);
554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void InvokeFunction(Handle<JSFunction> function,
556402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                      const ParameterCount& actual,
557257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      InvokeFlag flag,
5583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      const CallWrapper& call_wrapper,
559257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      CallKind call_kind);
560402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void IsObjectJSObjectType(Register heap_object,
562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                            Register map,
563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                            Register scratch,
564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                            Label* fail);
565b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void IsInstanceJSObjectType(Register map,
567b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                              Register scratch,
568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                              Label* fail);
569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void IsObjectJSStringType(Register object,
571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                            Register scratch,
572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                            Label* fail);
573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Debugger Support
577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
578402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  void DebugBreak();
579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Exception handling
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Push a new try handler and link into try handler chain.
5853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void PushTryHandler(StackHandler::Kind kind, int handler_index);
586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
587e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Unlink the stack handler on top of the stack from the try handler chain.
588e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Must preserve the result register.
589e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void PopTryHandler();
590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Passes thrown value to the handler of top of the try handler chain.
592e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void Throw(Register value);
593e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
594e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Propagates an uncatchable exception to the top of the current JS stack's
595e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // handler chain.
5963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void ThrowUncatchable(Register value);
597e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Inline caching support
600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Generate code for checking access rights - used for security checks
602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // on access to global objects across environments. The holder register
603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is left untouched, whereas both scratch registers are clobbered.
604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void CheckAccessGlobalProxy(Register holder_reg,
605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Register scratch,
606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Label* miss);
607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
608c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  void GetNumberHash(Register t0, Register scratch);
6093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void LoadFromNumberDictionary(Label* miss,
6113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                Register elements,
6123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                Register key,
6133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                Register result,
6143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                Register t0,
6153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                Register t1,
6163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                Register t2);
6173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  inline void MarkCode(NopMarkerTypes type) {
6208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    nop(type);
6218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  }
6228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
6238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Check if the given instruction is a 'type' marker.
6243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // i.e. check if is is a mov r<type>, r<type> (referenced as nop(type))
6258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // These instructions are generated to mark special location in the code,
6268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // like some special IC code.
6278a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  static inline bool IsMarkedCode(Instr instr, int type) {
6288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    ASSERT((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER));
6298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    return IsNop(instr, type);
6308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  }
6318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
6328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
6338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  static inline int GetCodeMarker(Instr instr) {
6348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    int dst_reg_offset = 12;
6358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    int dst_mask = 0xf << dst_reg_offset;
6368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    int src_mask = 0xf;
6378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    int dst_reg = (instr & dst_mask) >> dst_reg_offset;
6388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    int src_reg = instr & src_mask;
6398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    uint32_t non_register_mask = ~(dst_mask | src_mask);
6408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    uint32_t mov_mask = al | 13 << 21;
6418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
6428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    // Return <n> if we have a mov rn rn, else return -1.
6438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    int type = ((instr & non_register_mask) == mov_mask) &&
6448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang               (dst_reg == src_reg) &&
6458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang               (FIRST_IC_MARKER <= dst_reg) && (dst_reg < LAST_CODE_MARKER)
6468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                   ? src_reg
6478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                   : -1;
6488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    ASSERT((type == -1) ||
6498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang           ((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER)));
6508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    return type;
6518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  }
6528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocation support
656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
657086aeeaae12517475c22695a200be45495516549Ben Murdoch  // Allocate an object in new space. The object_size is specified
658086aeeaae12517475c22695a200be45495516549Ben Murdoch  // either in bytes or in words if the allocation flag SIZE_IN_WORDS
659086aeeaae12517475c22695a200be45495516549Ben Murdoch  // is passed. If the new space is exhausted control continues at the
660086aeeaae12517475c22695a200be45495516549Ben Murdoch  // gc_required label. The allocated object is returned in result. If
661086aeeaae12517475c22695a200be45495516549Ben Murdoch  // the flag tag_allocated_object is true the result is tagged as as
662086aeeaae12517475c22695a200be45495516549Ben Murdoch  // a heap object. All registers are clobbered also when control
663086aeeaae12517475c22695a200be45495516549Ben Murdoch  // continues at the gc_required label.
664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void AllocateInNewSpace(int object_size,
665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Register result,
666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Register scratch1,
667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Register scratch2,
668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Label* gc_required,
669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          AllocationFlags flags);
670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void AllocateInNewSpace(Register object_size,
671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Register result,
672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Register scratch1,
673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Register scratch2,
674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Label* gc_required,
675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          AllocationFlags flags);
676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Undo allocation in new space. The object passed and objects allocated after
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // it will no longer be allocated. The caller must make sure that no pointers
679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // are left to the object(s) no longer allocated as they would be invalid when
680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // allocation is undone.
681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void UndoAllocationInNewSpace(Register object, Register scratch);
682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
6843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void AllocateTwoByteString(Register result,
6853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                             Register length,
6863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                             Register scratch1,
6873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                             Register scratch2,
6883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                             Register scratch3,
6893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                             Label* gc_required);
6903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void AllocateAsciiString(Register result,
6913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                           Register length,
6923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                           Register scratch1,
6933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                           Register scratch2,
6943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                           Register scratch3,
6953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                           Label* gc_required);
6963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void AllocateTwoByteConsString(Register result,
6973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                 Register length,
6983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                 Register scratch1,
6993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                 Register scratch2,
7003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                 Label* gc_required);
7013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void AllocateAsciiConsString(Register result,
7023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                               Register length,
7033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                               Register scratch1,
7043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                               Register scratch2,
7053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                               Label* gc_required);
706589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  void AllocateTwoByteSlicedString(Register result,
707589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                   Register length,
708589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                   Register scratch1,
709589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                   Register scratch2,
710589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                   Label* gc_required);
711589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  void AllocateAsciiSlicedString(Register result,
712589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                 Register length,
713589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                 Register scratch1,
714589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                 Register scratch2,
715589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                 Label* gc_required);
7163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
71725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // Allocates a heap number or jumps to the gc_required label if the young
71825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // space is full and a scavenge is needed. All registers are clobbered also
71925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // when control continues at the gc_required label.
7206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void AllocateHeapNumber(Register result,
7216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                          Register scratch1,
7226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                          Register scratch2,
7239dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                          Register heap_number_map,
7246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                          Label* gc_required);
7258defd9ff6930b4e24729971a61cf7469daf119beSteve Block  void AllocateHeapNumberWithValue(Register result,
7268defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                   DwVfpRegister value,
7278defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                   Register scratch1,
7288defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                   Register scratch2,
7298defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                   Register heap_number_map,
7308defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                   Label* gc_required);
7318defd9ff6930b4e24729971a61cf7469daf119beSteve Block
732bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Copies a fixed number of fields of heap objects from src to dst.
733bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  void CopyFields(Register dst, Register src, RegList temps, int field_count);
7343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
735e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Copies a number of bytes from src to dst. All registers are clobbered. On
736e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // exit src and dst will point to the place just after where the last byte was
737e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // read or written and length will be zero.
738e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void CopyBytes(Register src,
739e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 Register dst,
740e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 Register length,
741e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 Register scratch);
742e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
7433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Initialize fields with filler values.  Fields starting at |start_offset|
7443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // not including end_offset are overwritten with the value in |filler|.  At
7453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the end the loop, |start_offset| takes the value of |end_offset|.
7463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void InitializeFieldsWithFiller(Register start_offset,
7473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  Register end_offset,
7483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  Register filler);
7493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Support functions.
752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Try to get function prototype of a function and puts the value in
754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the result register. Checks that the function really is a
755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // function and jumps to the miss label if the fast checks fail. The
756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // function register will be untouched; the other registers may be
757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // clobbered.
758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void TryGetFunctionPrototype(Register function,
759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               Register result,
760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               Register scratch,
7613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Label* miss,
7623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               bool miss_on_bound_function = false);
763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compare object type for heap object.  heap_object contains a non-Smi
765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // whose object type should be compared with the given type.  This both
766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sets the flags and leaves the object type in the type_reg register.
767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // It leaves the map in the map register (unless the type_reg and map register
768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // are the same register).  It leaves the heap object in the heap_object
769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // register unless the heap_object register is the same register as one of the
770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // other registers.
771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void CompareObjectType(Register heap_object,
772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         Register map,
773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         Register type_reg,
774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         InstanceType type);
775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compare instance type in a map.  map contains a valid map object whose
777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object type should be compared with the given type.  This both
778589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // sets the flags and leaves the object type in the type_reg register.
779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void CompareInstanceType(Register map,
780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                           Register type_reg,
781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                           InstanceType type);
782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
7843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check if a map for a JSObject indicates that the object has fast elements.
7853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Jump to the specified label if it does not.
7863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void CheckFastElements(Register map,
7873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                         Register scratch,
7883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                         Label* fail);
7893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if a map for a JSObject indicates that the object can have both smi
7913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // and HeapObject elements.  Jump to the specified label if it does not.
7923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CheckFastObjectElements(Register map,
7933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Register scratch,
7943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Label* fail);
7953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if a map for a JSObject indicates that the object has fast smi only
7973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // elements.  Jump to the specified label if it does not.
7983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CheckFastSmiOnlyElements(Register map,
7993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                Register scratch,
8003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                Label* fail);
8013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check to see if maybe_number can be stored as a double in
8033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // FastDoubleElements. If it can, store it at the index specified by key in
8043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the FastDoubleElements array elements. Otherwise jump to fail, in which
8053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // case scratch2, scratch3 and scratch4 are unmodified.
8063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void StoreNumberToDoubleElements(Register value_reg,
8073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   Register key_reg,
8083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   Register receiver_reg,
8093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   Register elements_reg,
8103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   Register scratch1,
8113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   Register scratch2,
8123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   Register scratch3,
8133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   Register scratch4,
8143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   Label* fail);
8153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Compare an object's map with the specified map and its transitioned
8173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // elements maps if mode is ALLOW_ELEMENT_TRANSITION_MAPS. Condition flags are
8183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // set with result of map compare. If multiple map compares are required, the
8193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // compare sequences branches to early_success.
8203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CompareMap(Register obj,
8213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  Register scratch,
8223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  Handle<Map> map,
8233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  Label* early_success,
8243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  CompareMapMode mode = REQUIRE_EXACT_MAP);
8253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if the map of an object is equal to a specified map and branch to
8273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // label if not. Skip the smi check if not required (object is known to be a
8283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match
8293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // against maps that are ElementsKind transition maps of the specified map.
8303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void CheckMap(Register obj,
8313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                Register scratch,
8323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                Handle<Map> map,
8333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                Label* fail,
8343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                SmiCheckType smi_check_type,
8353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                CompareMapMode mode = REQUIRE_EXACT_MAP);
836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
8373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
8387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  void CheckMap(Register obj,
8397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                Register scratch,
8407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                Heap::RootListIndex index,
8417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                Label* fail,
842257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                SmiCheckType smi_check_type);
843257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
845257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check if the map of an object is equal to a specified map and branch to a
846257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // specified target if equal. Skip the smi check if not required (object is
847257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // known to be a heap object)
848257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void DispatchMap(Register obj,
849257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                   Register scratch,
850257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                   Handle<Map> map,
851257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                   Handle<Code> success,
852257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                   SmiCheckType smi_check_type);
8537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
8547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
855e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Compare the object in a register to a value from the root list.
856e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Uses the ip register as scratch.
857e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void CompareRoot(Register obj, Heap::RootListIndex index);
858e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
859e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
8603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Load and check the instance type of an object for being a string.
8613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Loads the type into the second argument register.
8623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Returns a condition that will be enabled if the object was a string.
8633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Condition IsObjectStringType(Register obj,
8643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                               Register type) {
8653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    ldr(type, FieldMemOperand(obj, HeapObject::kMapOffset));
8663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    ldrb(type, FieldMemOperand(type, Map::kInstanceTypeOffset));
8673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    tst(type, Operand(kIsNotStringMask));
8683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    ASSERT_EQ(0, kStringTag);
8693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    return eq;
8703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
8713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
8723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Generates code for reporting that an illegal operation has
874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // occurred.
875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void IllegalOperation(int num_arguments);
876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
87780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Picks out an array index from the hash field.
87880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Register use:
87980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //   hash - holds the index's hash. Clobbered.
88080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //   index - holds the overwritten index on exit.
88180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void IndexFromHash(Register hash, Register index);
88280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
8833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Get the number of least significant bits from a register
8843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits);
8851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void GetLeastBitsFromInt32(Register dst, Register src, int mun_least_bits);
8863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
887d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Uses VFP instructions to Convert a Smi to a double.
888d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void IntegerToDoubleConversionWithVFP3(Register inReg,
889d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                         Register outHighReg,
890d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                         Register outLowReg);
891d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
8928defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Load the value of a number object into a VFP double register. If the object
8938defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // is not a number a jump to the label not_number is performed and the VFP
8948defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // double register is unchanged.
8958defd9ff6930b4e24729971a61cf7469daf119beSteve Block  void ObjectToDoubleVFPRegister(
8968defd9ff6930b4e24729971a61cf7469daf119beSteve Block      Register object,
8978defd9ff6930b4e24729971a61cf7469daf119beSteve Block      DwVfpRegister value,
8988defd9ff6930b4e24729971a61cf7469daf119beSteve Block      Register scratch1,
8998defd9ff6930b4e24729971a61cf7469daf119beSteve Block      Register scratch2,
9008defd9ff6930b4e24729971a61cf7469daf119beSteve Block      Register heap_number_map,
9018defd9ff6930b4e24729971a61cf7469daf119beSteve Block      SwVfpRegister scratch3,
9028defd9ff6930b4e24729971a61cf7469daf119beSteve Block      Label* not_number,
9038defd9ff6930b4e24729971a61cf7469daf119beSteve Block      ObjectToDoubleFlags flags = NO_OBJECT_TO_DOUBLE_FLAGS);
9048defd9ff6930b4e24729971a61cf7469daf119beSteve Block
9058defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Load the value of a smi object into a VFP double register. The register
9068defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // scratch1 can be the same register as smi in which case smi will hold the
9078defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // untagged value afterwards.
9088defd9ff6930b4e24729971a61cf7469daf119beSteve Block  void SmiToDoubleVFPRegister(Register smi,
9098defd9ff6930b4e24729971a61cf7469daf119beSteve Block                              DwVfpRegister value,
9108defd9ff6930b4e24729971a61cf7469daf119beSteve Block                              Register scratch1,
9118defd9ff6930b4e24729971a61cf7469daf119beSteve Block                              SwVfpRegister scratch2);
9128defd9ff6930b4e24729971a61cf7469daf119beSteve Block
9139ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  // Convert the HeapNumber pointed to by source to a 32bits signed integer
9149ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  // dest. If the HeapNumber does not fit into a 32bits signed integer branch
9151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // to not_int32 label. If VFP3 is available double_scratch is used but not
9161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // scratch2.
9179ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  void ConvertToInt32(Register source,
9189ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick                      Register dest,
9199ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick                      Register scratch,
9209ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick                      Register scratch2,
9211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      DwVfpRegister double_scratch,
9229ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick                      Label *not_int32);
9239ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick
92444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Truncates a double using a specific rounding mode.
92544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Clears the z flag (ne condition) if an overflow occurs.
92644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // If exact_conversion is true, the z flag is also cleared if the conversion
9273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // was inexact, i.e. if the double value could not be converted exactly
92844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // to a 32bit integer.
929e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void EmitVFPTruncate(VFPRoundingMode rounding_mode,
930e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                       SwVfpRegister result,
931e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                       DwVfpRegister double_input,
932e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                       Register scratch1,
933e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                       Register scratch2,
934e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                       CheckForInexactConversion check
935e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                           = kDontCheckForInexactConversion);
936e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
93744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Helper for EmitECMATruncate.
93844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // This will truncate a floating-point value outside of the singed 32bit
93944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // integer range to a 32bit signed integer.
94044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Expects the double value loaded in input_high and input_low.
94144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Exits with the answer in 'result'.
94244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Note that this code does not work for values in the 32bit range!
94344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void EmitOutOfInt32RangeTruncate(Register result,
94444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                   Register input_high,
94544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                   Register input_low,
94644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                   Register scratch);
94744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
94844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Performs a truncating conversion of a floating point number as used by
94944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // the JS bitwise operations. See ECMA-262 9.5: ToInt32.
95044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Exits with 'result' holding the answer and all other registers clobbered.
95144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void EmitECMATruncate(Register result,
95244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                        DwVfpRegister double_input,
95344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                        SwVfpRegister single_scratch,
95444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                        Register scratch,
95544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                        Register scratch2,
95644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                        Register scratch3);
95744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
9586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Count leading zeros in a 32 bit word.  On ARM5 and later it uses the clz
9596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // instruction.  On pre-ARM5 hardware this routine gives the wrong answer
9608defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // for 0 (31 instead of 32).  Source and scratch can be the same in which case
9618defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // the source is clobbered.  Source and zeros can also be the same in which
9628defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // case scratch should be a different register.
9638defd9ff6930b4e24729971a61cf7469daf119beSteve Block  void CountLeadingZeros(Register zeros,
9648defd9ff6930b4e24729971a61cf7469daf119beSteve Block                         Register source,
9658defd9ff6930b4e24729971a61cf7469daf119beSteve Block                         Register scratch);
966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Runtime calls
969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call a code stub.
971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void CallStub(CodeStub* stub, Condition cond = al);
972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Call a code stub.
9743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void TailCallStub(CodeStub* stub, Condition cond = al);
9753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call a runtime routine.
97744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void CallRuntime(const Runtime::Function* f, int num_arguments);
978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void CallRuntimeSaveDoubles(Runtime::FunctionId id);
979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Convenience function: Same as above, but takes the fid instead.
981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void CallRuntime(Runtime::FunctionId fid, int num_arguments);
982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
983402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Convenience function: call an external reference.
984402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  void CallExternalReference(const ExternalReference& ext,
985402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                             int num_arguments);
986402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Tail call of a runtime routine (jump).
9886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Like JumpToExternalReference, but also takes care of passing the number
989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // of parameters.
9906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void TailCallExternalReference(const ExternalReference& ext,
9916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                 int num_arguments,
9926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                 int result_size);
9936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Convenience function: tail call a runtime routine (jump).
9956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void TailCallRuntime(Runtime::FunctionId fid,
996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       int num_arguments,
997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       int result_size);
998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
999257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int CalculateStackPassedWords(int num_reg_arguments,
1000257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                int num_double_arguments);
1001257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Before calling a C-function from generated code, align arguments on stack.
10036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // After aligning the frame, non-register arguments must be stored in
10046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // sp[0], sp[4], etc., not pushed. The argument count assumes all arguments
1005257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // are word sized. If double arguments are used, this function assumes that
1006257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // all double arguments are stored before core registers; otherwise the
1007257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // correct alignment of the double values is not guaranteed.
10086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Some compilers/platforms require the stack to be aligned when calling
10096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // C++ code.
10106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Needs a scratch register to do some arithmetic. This register will be
10116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // trashed.
1012257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void PrepareCallCFunction(int num_reg_arguments,
1013257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            int num_double_registers,
1014257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register scratch);
1015257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void PrepareCallCFunction(int num_reg_arguments,
1016257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register scratch);
1017257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1018257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // There are two ways of passing double arguments on ARM, depending on
1019257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // whether soft or hard floating point ABI is used. These functions
1020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // abstract parameter passing for the three different ways we call
1021257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // C functions from generated code.
1022257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void SetCallCDoubleArguments(DoubleRegister dreg);
1023257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void SetCallCDoubleArguments(DoubleRegister dreg1, DoubleRegister dreg2);
1024257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void SetCallCDoubleArguments(DoubleRegister dreg, Register reg);
10256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Calls a C function and cleans up the space for arguments allocated
10276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // by PrepareCallCFunction. The called function is not allowed to trigger a
10286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // garbage collection, since that might move the code and invalidate the
10296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // return address (unless this is somehow accounted for by the called
10306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // function).
10316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void CallCFunction(ExternalReference function, int num_arguments);
10323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CallCFunction(Register function, int num_arguments);
1033257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void CallCFunction(ExternalReference function,
1034257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                     int num_reg_arguments,
1035257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                     int num_double_arguments);
10363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CallCFunction(Register function,
1037257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                     int num_reg_arguments,
1038257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                     int num_double_arguments);
10396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1040e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void GetCFunctionDoubleResult(const DoubleRegister dst);
1041e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
10423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Calls an API function.  Allocates HandleScope, extracts returned value
10433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // from handle and propagates exceptions.  Restores context.  stack_space
10443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // - space to be unwound on exit (includes the call JS arguments space and
10453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the additional space allocated for the fast call).
10463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CallApiFunctionAndReturn(ExternalReference function, int stack_space);
10471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to a runtime routine.
10496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void JumpToExternalReference(const ExternalReference& builtin);
1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Invoke specified builtin JavaScript function. Adds an entry to
1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the unresolved list if the name does not resolve.
1053b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void InvokeBuiltin(Builtins::JavaScript id,
1054257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                     InvokeFlag flag,
1055257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                     const CallWrapper& call_wrapper = NullCallWrapper());
1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Store the code object for the given builtin in the target register and
1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // setup the function in r1.
1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void GetBuiltinEntry(Register target, Builtins::JavaScript id);
1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1061791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  // Store the function for the given builtin in the target register.
1062791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  void GetBuiltinFunction(Register target, Builtins::JavaScript id);
1063791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
10648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Handle<Object> CodeObject() {
10658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    ASSERT(!code_object_.is_null());
10668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return code_object_;
10678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // StatsCounter support
1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void SetCounter(StatsCounter* counter, int value,
1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  Register scratch1, Register scratch2);
1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void IncrementCounter(StatsCounter* counter, int value,
1076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        Register scratch1, Register scratch2);
1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void DecrementCounter(StatsCounter* counter, int value,
1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        Register scratch1, Register scratch2);
1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Debugging
1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Calls Abort(msg) if the condition cond is not satisfied.
1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Use --debug_code to enable.
10861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void Assert(Condition cond, const char* msg);
10879dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  void AssertRegisterIsRoot(Register reg, Heap::RootListIndex index);
1088756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  void AssertFastElements(Register elements);
1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Like Assert(), but always enabled.
10911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void Check(Condition cond, const char* msg);
1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Print a message to stdout and abort execution.
1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Abort(const char* msg);
1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Verify restrictions about code generated in stubs.
1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void set_generating_stub(bool value) { generating_stub_ = value; }
1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool generating_stub() { return generating_stub_; }
1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; }
1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool allow_stub_calls() { return allow_stub_calls_; }
11013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void set_has_frame(bool value) { has_frame_ = value; }
11023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool has_frame() { return has_frame_; }
11033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline bool AllowThisStubCall(CodeStub* stub);
1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // EABI variant for double arguments in use.
1106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool use_eabi_hardfloat() {
1107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#if USE_EABI_HARDFLOAT
1108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return true;
1109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#else
1110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return false;
1111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif
1112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1114d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // ---------------------------------------------------------------------------
11151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Number utilities
11161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
11171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check whether the value of reg is a power of two and not zero. If not
11181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // control continues at the label not_power_of_two. If reg is a power of two
11191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // the register scratch contains the value of (reg - 1) when control falls
11201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // through.
11211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void JumpIfNotPowerOfTwoOrZero(Register reg,
11221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                 Register scratch,
11231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                 Label* not_power_of_two_or_zero);
112444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check whether the value of reg is a power of two and not zero.
112544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Control falls through if it is, with scratch containing the mask
112644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // value (reg - 1).
112744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Otherwise control jumps to the 'zero_and_neg' label if the value of reg is
112844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // zero or negative, or jumps to the 'not_power_of_two' label if the value is
112944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // strictly positive but not a power of two.
113044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void JumpIfNotPowerOfTwoOrZeroAndNeg(Register reg,
113144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       Register scratch,
113244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       Label* zero_and_neg,
113344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       Label* not_power_of_two);
11341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
11351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ---------------------------------------------------------------------------
11363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Smi utilities
11373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void SmiTag(Register reg, SBit s = LeaveCC) {
1139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    add(reg, reg, Operand(reg), s);
1140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
11411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void SmiTag(Register dst, Register src, SBit s = LeaveCC) {
11421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    add(dst, src, Operand(src), s);
11431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
1144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1145b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Try to convert int32 to smi. If the value is to large, preserve
1146b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // the original value and jump to not_a_smi. Destroys scratch and
1147b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // sets flags.
1148b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void TrySmiTag(Register reg, Label* not_a_smi, Register scratch) {
1149b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    mov(scratch, reg);
1150b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    SmiTag(scratch, SetCC);
1151b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    b(vs, not_a_smi);
1152b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    mov(reg, scratch);
1153b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
1154b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1155e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void SmiUntag(Register reg, SBit s = LeaveCC) {
1156e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    mov(reg, Operand(reg, ASR, kSmiTagSize), s);
1157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1158e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void SmiUntag(Register dst, Register src, SBit s = LeaveCC) {
1159e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    mov(dst, Operand(src, ASR, kSmiTagSize), s);
11601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
1161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
11623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Untag the source value into destination and jump if source is a smi.
11633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Souce and destination can be the same register.
11643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void UntagAndJumpIfSmi(Register dst, Register src, Label* smi_case);
11653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Untag the source value into destination and jump if source is not a smi.
11673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Souce and destination can be the same register.
11683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void UntagAndJumpIfNotSmi(Register dst, Register src, Label* non_smi_case);
11693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Jump the register contains a smi.
11711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  inline void JumpIfSmi(Register value, Label* smi_label) {
11721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    tst(value, Operand(kSmiTagMask));
11731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    b(eq, smi_label);
11741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
11751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Jump if either of the registers contain a non-smi.
11761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  inline void JumpIfNotSmi(Register value, Label* not_smi_label) {
11771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    tst(value, Operand(kSmiTagMask));
11781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    b(ne, not_smi_label);
11791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
11803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Jump if either of the registers contain a non-smi.
11813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void JumpIfNotBothSmi(Register reg1, Register reg2, Label* on_not_both_smi);
11823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Jump if either of the registers contain a smi.
11833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi);
11843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1185756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Abort execution if argument is a smi. Used in debug code.
1186756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  void AbortIfSmi(Register object);
11871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void AbortIfNotSmi(Register object);
11881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1189e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Abort execution if argument is a string. Used in debug code.
1190e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void AbortIfNotString(Register object);
1191e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
11921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Abort execution if argument is not the root value with the given index.
11931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void AbortIfNotRootValue(Register src,
11941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                           Heap::RootListIndex root_value_index,
11951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                           const char* message);
11961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
11971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ---------------------------------------------------------------------------
11981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // HeapNumber utilities
11991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
12001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void JumpIfNotHeapNumber(Register object,
12011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                           Register heap_number_map,
12021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                           Register scratch,
12031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                           Label* on_not_heap_number);
1204756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
12053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // ---------------------------------------------------------------------------
1206d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // String utilities
1207d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1208d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Checks if both objects are sequential ASCII strings and jumps to label
1209d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // if either is not. Assumes that neither object is a smi.
1210d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void JumpIfNonSmisNotBothSequentialAsciiStrings(Register object1,
1211d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                                  Register object2,
1212d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                                  Register scratch1,
1213d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                                  Register scratch2,
12146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                                  Label* failure);
1215d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1216d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Checks if both objects are sequential ASCII strings and jumps to label
1217d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // if either is not.
1218d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void JumpIfNotBothSequentialAsciiStrings(Register first,
1219d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                           Register second,
1220d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                           Register scratch1,
1221d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                           Register scratch2,
1222d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                           Label* not_flat_ascii_strings);
1223d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
12246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Checks if both instance types are sequential ASCII strings and jumps to
12256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // label if either is not.
12266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void JumpIfBothInstanceTypesAreNotSequentialAscii(
12276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Register first_object_instance_type,
12286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Register second_object_instance_type,
12296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Register scratch1,
12306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Register scratch2,
12316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Label* failure);
12326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check if instance type is sequential ASCII string and jump to label if
12346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // it is not.
12356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void JumpIfInstanceTypeIsNotSequentialAscii(Register type,
12366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                              Register scratch,
12376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                              Label* failure);
12386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ---------------------------------------------------------------------------
12411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Patching helpers.
12421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
12431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Get the location of a relocated constant (its address in the constant pool)
12441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // from its load site.
12451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void GetRelocatedValueLocation(Register ldr_location,
12461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                 Register result);
12471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
12481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void ClampUint8(Register output_reg, Register input_reg);
1250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void ClampDoubleToUint8(Register result_reg,
1252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                          DoubleRegister input_reg,
1253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                          DoubleRegister temp_double_reg);
1254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void LoadInstanceDescriptors(Register map, Register descriptors);
1257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
12583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Activation support.
12593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void EnterFrame(StackFrame::Type type);
12603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void LeaveFrame(StackFrame::Type type);
12613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Expects object in r0 and returns map with validated enum cache
12633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // in r0.  Assumes that any other register can be used as a scratch.
12643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CheckEnumCache(Register null_value, Label* call_runtime);
12653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
126744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void CallCFunctionHelper(Register function,
1268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                           int num_reg_arguments,
1269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                           int num_double_arguments);
127044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
12713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = al);
1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Helper functions for generating invokes.
1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void InvokePrologue(const ParameterCount& expected,
1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      const ParameterCount& actual,
1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Handle<Code> code_constant,
1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register code_reg,
1278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Label* done,
12793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      bool* definitely_mismatches,
1280b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                      InvokeFlag flag,
1281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      const CallWrapper& call_wrapper,
1282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      CallKind call_kind);
1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void InitializeNewString(Register string,
12856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           Register length,
12866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           Heap::RootListIndex map_index,
12876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           Register scratch1,
12886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           Register scratch2);
12896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Helper for implementing JumpIfNotInNewSpace and JumpIfInNewSpace.
12913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void InNewSpace(Register object,
12923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  Register scratch,
12933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  Condition cond,  // eq for new space, ne otherwise.
12943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  Label* branch);
12953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Helper for finding the mark bits for an address.  Afterwards, the
12973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // bitmap register points at the word with the mark bits and the mask
12983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the position of the first bit.  Leaves addr_reg unchanged.
12993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline void GetMarkBits(Register addr_reg,
13003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          Register bitmap_reg,
13013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          Register mask_reg);
13023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Helper for throwing exceptions.  Compute a handler address and jump to
13043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // it.  See the implementation for register usage.
13053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void JumpToHandlerEntry();
13063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1307e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Compute memory operands for safepoint stack slots.
1308e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  static int SafepointRegisterStackIndex(int reg_code);
1309e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  MemOperand SafepointRegisterSlot(Register reg);
1310e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  MemOperand SafepointRegistersAndDoublesSlot(Register reg);
1311e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
13123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  bool generating_stub_;
13133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  bool allow_stub_calls_;
13143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool has_frame_;
13153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // This handle will be patched with the code object on installation.
13163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Handle<Object> code_object_;
1317e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1318e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Needs access to SafepointRegisterStackIndex for optimized frame
1319e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // traversal.
1320e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  friend class OptimizedFrame;
1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT
1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The code patcher is used to patch (typically) small parts of code e.g. for
1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// debugging and other types of instrumentation. When using the code patcher
1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the exact number of bytes specified must be emitted. It is not legal to emit
1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// relocation information. If any of these constraints are violated it causes
1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// an assertion to fail.
1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass CodePatcher {
1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CodePatcher(byte* address, int instructions);
1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual ~CodePatcher();
1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Macro assembler to emit code.
1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MacroAssembler* masm() { return &masm_; }
1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit an instruction directly.
13391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void Emit(Instr instr);
1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit an address directly.
1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Emit(Address addr);
1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Emit the condition part of an instruction leaving the rest of the current
13451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // instruction unchanged.
13461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void EmitCondition(Condition cond);
13471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* address_;  // The address of the code being patched.
1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int instructions_;  // Number of instructions of the expected patch size.
1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int size_;  // Number of bytes of the expected patch size.
1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MacroAssembler masm_;  // Macro assembler used to generate the code.
1353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
1354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // ENABLE_DEBUGGER_SUPPORT
1355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Static helper functions.
1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochinline MemOperand ContextOperand(Register context, int index) {
13618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  return MemOperand(context, Context::SlotOffset(index));
13628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
13638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
13648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
13653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochinline MemOperand GlobalObjectOperand()  {
13668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  return ContextOperand(cp, Context::GLOBAL_INDEX);
13678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
13688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
13698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef GENERATED_CODE_COVERAGE
1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define CODE_COVERAGE_STRINGIFY(x) #x
1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x)
1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__)
1374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm->
1375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else
1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define ACCESS_MASM(masm) masm->
1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
1381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // V8_ARM_MACRO_ASSEMBLER_ARM_H_
1383