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