13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef V8_ARM_MACRO_ASSEMBLER_ARM_H_ 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define V8_ARM_MACRO_ASSEMBLER_ARM_H_ 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/assembler.h" 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/bailout-reason.h" 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/frames.h" 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/globals.h" 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Give alias names to registers for calling conventions. 17014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kReturnRegister0 = {Register::kCode_r0}; 18014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kReturnRegister1 = {Register::kCode_r1}; 19109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochconst Register kReturnRegister2 = {Register::kCode_r2}; 20014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kJSFunctionRegister = {Register::kCode_r1}; 21014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kContextRegister = {Register::kCode_r7}; 22bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochconst Register kAllocateSizeRegister = {Register::kCode_r1}; 23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kInterpreterAccumulatorRegister = {Register::kCode_r0}; 24014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kInterpreterBytecodeOffsetRegister = {Register::kCode_r5}; 25014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kInterpreterBytecodeArrayRegister = {Register::kCode_r6}; 26014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kInterpreterDispatchTableRegister = {Register::kCode_r8}; 27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kJavaScriptCallArgCountRegister = {Register::kCode_r0}; 28014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kJavaScriptCallNewTargetRegister = {Register::kCode_r3}; 29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kRuntimeCallFunctionRegister = {Register::kCode_r1}; 30014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kRuntimeCallArgCountRegister = {Register::kCode_r0}; 31014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// ---------------------------------------------------------------------------- 333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Static helper functions 343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Generate a MemOperand for loading a field from an object. 363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochinline MemOperand FieldMemOperand(Register object, int offset) { 373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return MemOperand(object, offset - kHeapObjectTag); 383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Give alias names to registers 42014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register cp = {Register::kCode_r7}; // JavaScript context pointer. 43014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register pp = {Register::kCode_r8}; // Constant pool pointer. 44014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kRootRegister = {Register::kCode_r10}; // Roots array pointer. 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Flags used for AllocateHeapNumber 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochenum TaggingMode { 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Tag the result. 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TAG_RESULT, 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Don't tag 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DONT_TAG_RESULT 528defd9ff6930b4e24729971a61cf7469daf119beSteve Block}; 538defd9ff6930b4e24729971a61cf7469daf119beSteve Block 548defd9ff6930b4e24729971a61cf7469daf119beSteve Block 553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochenum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET }; 563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochenum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK }; 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochenum PointersToHereCheck { 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kPointersToHereMaybeInteresting, 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kPointersToHereAreAlwaysInteresting 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochenum LinkRegisterStatus { kLRHasNotBeenSaved, kLRHasBeenSaved }; 623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRegister GetRegisterThatIsNotOneOf(Register reg1, 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg2 = no_reg, 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg3 = no_reg, 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg4 = no_reg, 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg5 = no_reg, 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg6 = no_reg); 70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool AreAliased(Register reg1, 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg2, 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg3 = no_reg, 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg4 = no_reg, 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg5 = no_reg, 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg6 = no_reg, 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg7 = no_reg, 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg8 = no_reg); 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochenum TargetAddressStorageMode { 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CAN_INLINE_TARGET_ADDRESS, 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NEVER_INLINE_TARGET_ADDRESS 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// MacroAssembler implements a collection of frequently used macros. 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass MacroAssembler: public Assembler { 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 92014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MacroAssembler(Isolate* isolate, void* buffer, int size, 93014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CodeObjectRequired create_code_object); 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Returns the size of a call in instructions. Note, the value returned is 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // only valid as long as no entries are added to the constant pool between 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // checking the call size and emitting the actual call. 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static int CallSize(Register target, Condition cond = al); 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int CallSize(Address target, RelocInfo::Mode rmode, Condition cond = al); 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int CallStubSize(CodeStub* stub, 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TypeFeedbackId ast_id = TypeFeedbackId::None(), 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond = al); 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Jump, Call, and Ret pseudo instructions implementing inter-working. 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Jump(Register target, Condition cond = al); 1073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void Jump(Address target, RelocInfo::Mode rmode, Condition cond = al); 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Jump(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al); 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Call(Register target, Condition cond = al); 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Call(Address target, RelocInfo::Mode rmode, 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond = al, 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TargetAddressStorageMode mode = CAN_INLINE_TARGET_ADDRESS); 11313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch void Call(Handle<Code> code, RelocInfo::Mode rmode = RelocInfo::CODE_TARGET, 11413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch TypeFeedbackId ast_id = TypeFeedbackId::None(), Condition cond = al, 11513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch TargetAddressStorageMode mode = CAN_INLINE_TARGET_ADDRESS); 116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int CallSize(Handle<Code> code, 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RelocInfo::Mode rmode = RelocInfo::CODE_TARGET, 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TypeFeedbackId ast_id = TypeFeedbackId::None(), 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond = al); 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Ret(Condition cond = al); 121e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 12213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Used for patching in calls to the deoptimizer. 12313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch void CallDeoptimizer(Address target); 12413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch static int CallDeoptimizerSize(); 12513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 126f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Emit code that loads |parameter_index|'th parameter from the stack to 127f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // the register according to the CallInterfaceDescriptor definition. 128f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // |sp_to_caller_sp_offset_in_words| specifies the number of words pushed 129f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // below the caller's sp. 130f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch template <class Descriptor> 131f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void LoadParameterFromStack( 132f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Register reg, typename Descriptor::ParameterIndices parameter_index, 133f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch int sp_to_ra_offset_in_words = 0) { 134f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch DCHECK(Descriptor::kPassLastArgsOnStack); 135f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch UNIMPLEMENTED(); 136f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 137f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 138e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Emit code to discard a non-negative number of pointer-sized elements 139e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // from the stack, clobbering only the sp register. 140e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void Drop(int count, Condition cond = al); 141109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch void Drop(Register count, Condition cond = al); 142e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void Ret(int drop, Condition cond = al); 1446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Swap two registers. If the scratch register is omitted then a slightly 1466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // less efficient form using xor instead of mov is emitted. 1477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch void Swap(Register reg1, 1487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register reg2, 1497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch = no_reg, 1507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Condition cond = al); 1516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Mls(Register dst, Register src1, Register src2, Register srcA, 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond = al); 1549dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen void And(Register dst, Register src1, const Operand& src2, 1559dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Condition cond = al); 1569dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen void Ubfx(Register dst, Register src, int lsb, int width, 1579dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Condition cond = al); 1589dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen void Sbfx(Register dst, Register src, int lsb, int width, 1599dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Condition cond = al); 160e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // The scratch register is not used for ARMv7. 161e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // scratch can be the same register as src (in which case it is trashed), but 162e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // not the same as dst. 163e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void Bfi(Register dst, 164e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register src, 165e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register scratch, 166e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int lsb, 167e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int width, 168e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Condition cond = al); 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Bfc(Register dst, Register src, int lsb, int width, Condition cond = al); 1709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 171e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void Call(Label* target); 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Push(Register src) { push(src); } 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Pop(Register dst) { pop(dst); } 174257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Register move. May do nothing if the registers are identical. 176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void Move(Register dst, Smi* smi) { mov(dst, Operand(smi)); } 177e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void Move(Register dst, Handle<Object> value); 1783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void Move(Register dst, Register src, Condition cond = al); 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Move(Register dst, const Operand& src, SBit sbit = LeaveCC, 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond = al) { 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!src.is_reg() || !src.rm().is(dst) || sbit != LeaveCC) { 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(dst, src, sbit, cond); 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 185f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void Move(SwVfpRegister dst, SwVfpRegister src, Condition cond = al); 186f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void Move(DwVfpRegister dst, DwVfpRegister src, Condition cond = al); 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Load(Register dst, const MemOperand& src, Representation r); 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Store(Register src, const MemOperand& dst, Representation r); 190257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load an object from the root table. 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void LoadRoot(Register destination, 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::RootListIndex index, 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Condition cond = al); 19525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // Store an object to the root table. 19625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen void StoreRoot(Register source, 19725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Heap::RootListIndex index, 19825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Condition cond = al); 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // --------------------------------------------------------------------------- 2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // GC Support 2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void IncrementalMarkingRecordWriteHelper(Register object, 2043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register value, 2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register address); 2063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch enum RememberedSetFinalAction { 2083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kReturnAtEnd, 2093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kFallThroughAtEnd 2103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch }; 2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Record in the remembered set the fact that we have a pointer to new space 2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // at the address pointed to by the addr register. Only works if addr is not 2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // in new space. 2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void RememberedSetHelper(Register object, // Used for debug code. 2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register addr, 2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SaveFPRegsMode save_fp, 2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RememberedSetFinalAction and_then); 2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CheckPageFlag(Register object, 2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int mask, 2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition cc, 2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* condition_met); 2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if object is in new space. Jumps if the object is not in new space. 2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The register scratch can be object itself, but scratch will be clobbered. 2293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void JumpIfNotInNewSpace(Register object, 2303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* branch) { 232109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch InNewSpace(object, scratch, eq, branch); 2333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if object is in new space. Jumps if the object is in new space. 2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The register scratch can be object itself, but it will be clobbered. 2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void JumpIfInNewSpace(Register object, 2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* branch) { 240109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch InNewSpace(object, scratch, ne, branch); 2413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if an object has a given incremental marking color. 2443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void HasColor(Register object, 2453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch0, 2463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1, 2473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* has_color, 2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int first_bit, 2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int second_bit); 2508defd9ff6930b4e24729971a61cf7469daf119beSteve Block 2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void JumpIfBlack(Register object, 2529dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Register scratch0, 2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1, 2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* on_black); 2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Checks the color of an object. If the object is white we jump to the 257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // incremental marker. 258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void JumpIfWhite(Register value, Register scratch1, Register scratch2, 259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register scratch3, Label* value_is_white); 2603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Notify the garbage collector that we wrote a pointer into an object. 2623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // |object| is the object being stored into, |value| is the object being 2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // stored. value and scratch registers are clobbered by the operation. 2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The offset is the offset from the start of the object, not the offset from 265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // the tagged HeapObject pointer. For use with FieldMemOperand(reg, off). 2663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void RecordWriteField( 2673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object, 2683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int offset, 2693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register value, 2703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 2713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LinkRegisterStatus lr_status, 2723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SaveFPRegsMode save_fp, 2733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, 274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SmiCheck smi_check = INLINE_SMI_CHECK, 275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PointersToHereCheck pointers_to_here_check_for_value = 276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kPointersToHereMaybeInteresting); 2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // As above, but the offset has the tag presubtracted. For use with 2793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // MemOperand(reg, off). 2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch inline void RecordWriteContextSlot( 2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register context, 2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int offset, 2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register value, 2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 2853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LinkRegisterStatus lr_status, 2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SaveFPRegsMode save_fp, 2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, 288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SmiCheck smi_check = INLINE_SMI_CHECK, 289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PointersToHereCheck pointers_to_here_check_for_value = 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kPointersToHereMaybeInteresting) { 2913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RecordWriteField(context, 2923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch offset + kHeapObjectTag, 2933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value, 2943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 2953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lr_status, 2963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch save_fp, 2973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch remembered_set_action, 298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch smi_check, 299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch pointers_to_here_check_for_value); 3003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 301592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 302109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Notify the garbage collector that we wrote a code entry into a 303109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // JSFunction. Only scratch is clobbered by the operation. 304109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch void RecordWriteCodeEntryField(Register js_function, Register code_entry, 305109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register scratch); 306109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void RecordWriteForMap( 308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object, 309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register map, 310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register dst, 311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LinkRegisterStatus lr_status, 312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SaveFPRegsMode save_fp); 313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // For a given |object| notify the garbage collector that the slot |address| 3153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // has been written. |value| is the object being stored. The value and 3163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // address registers are clobbered by the operation. 3173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void RecordWrite( 3183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object, 3193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register address, 3203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register value, 3213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LinkRegisterStatus lr_status, 3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SaveFPRegsMode save_fp, 3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, 324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SmiCheck smi_check = INLINE_SMI_CHECK, 325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PointersToHereCheck pointers_to_here_check_for_value = 326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kPointersToHereMaybeInteresting); 3278defd9ff6930b4e24729971a61cf7469daf119beSteve Block 3283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Push a handle. 3293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void Push(Handle<Object> handle); 330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Push(Smi* smi) { Push(Handle<Smi>(smi, isolate())); } 3313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 3326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Push two registers. Pushes leftmost register first (to highest address). 3336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void Push(Register src1, Register src2, Condition cond = al) { 3346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (src1.code() > src2.code()) { 3356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block stm(db_w, sp, src1.bit() | src2.bit(), cond); 3366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 3376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block str(src1, MemOperand(sp, 4, NegPreIndex), cond); 3386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block str(src2, MemOperand(sp, 4, NegPreIndex), cond); 3396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Push three registers. Pushes leftmost register first (to highest address). 3436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void Push(Register src1, Register src2, Register src3, Condition cond = al) { 3446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (src1.code() > src2.code()) { 3456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (src2.code() > src3.code()) { 3466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond); 3476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 3486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block stm(db_w, sp, src1.bit() | src2.bit(), cond); 3496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block str(src3, MemOperand(sp, 4, NegPreIndex), cond); 3506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 3526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block str(src1, MemOperand(sp, 4, NegPreIndex), cond); 3536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Push(src2, src3, cond); 3546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Push four registers. Pushes leftmost register first (to highest address). 3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void Push(Register src1, 3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register src2, 3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register src3, 3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register src4, 3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition cond = al) { 3636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (src1.code() > src2.code()) { 3646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (src2.code() > src3.code()) { 3656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (src3.code() > src4.code()) { 3666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block stm(db_w, 3676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block sp, 3686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block src1.bit() | src2.bit() | src3.bit() | src4.bit(), 3696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block cond); 3706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 3716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond); 3726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block str(src4, MemOperand(sp, 4, NegPreIndex), cond); 3736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 3756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block stm(db_w, sp, src1.bit() | src2.bit(), cond); 3766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Push(src3, src4, cond); 3776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 3796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block str(src1, MemOperand(sp, 4, NegPreIndex), cond); 3806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Push(src2, src3, src4, cond); 3816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 384014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Push five registers. Pushes leftmost register first (to highest address). 385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void Push(Register src1, Register src2, Register src3, Register src4, 386014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register src5, Condition cond = al) { 387014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (src1.code() > src2.code()) { 388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (src2.code() > src3.code()) { 389014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (src3.code() > src4.code()) { 390014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (src4.code() > src5.code()) { 391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch stm(db_w, sp, 392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch src1.bit() | src2.bit() | src3.bit() | src4.bit() | src5.bit(), 393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch cond); 394014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 395014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch stm(db_w, sp, src1.bit() | src2.bit() | src3.bit() | src4.bit(), 396014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch cond); 397014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch str(src5, MemOperand(sp, 4, NegPreIndex), cond); 398014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 399014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 400014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond); 401014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Push(src4, src5, cond); 402014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 404014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch stm(db_w, sp, src1.bit() | src2.bit(), cond); 405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Push(src3, src4, src5, cond); 406014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 407014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 408014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch str(src1, MemOperand(sp, 4, NegPreIndex), cond); 409014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Push(src2, src3, src4, src5, cond); 410014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 411014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 412014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 413e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Pop two registers. Pops rightmost register first (from lower address). 414e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void Pop(Register src1, Register src2, Condition cond = al) { 415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!src1.is(src2)); 416e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (src1.code() > src2.code()) { 417e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ldm(ia_w, sp, src1.bit() | src2.bit(), cond); 418e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 419e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ldr(src2, MemOperand(sp, 4, PostIndex), cond); 420e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ldr(src1, MemOperand(sp, 4, PostIndex), cond); 421e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 422e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 423e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Pop three registers. Pops rightmost register first (from lower address). 4253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void Pop(Register src1, Register src2, Register src3, Condition cond = al) { 426014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!AreAliased(src1, src2, src3)); 4273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (src1.code() > src2.code()) { 4283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (src2.code() > src3.code()) { 4293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond); 4303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 4313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ldr(src3, MemOperand(sp, 4, PostIndex), cond); 4323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ldm(ia_w, sp, src1.bit() | src2.bit(), cond); 4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Pop(src2, src3, cond); 436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ldr(src1, MemOperand(sp, 4, PostIndex), cond); 4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Pop four registers. Pops rightmost register first (from lower address). 4413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void Pop(Register src1, 4423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register src2, 4433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register src3, 4443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register src4, 4453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition cond = al) { 446014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!AreAliased(src1, src2, src3, src4)); 4473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (src1.code() > src2.code()) { 4483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (src2.code() > src3.code()) { 4493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (src3.code() > src4.code()) { 4503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ldm(ia_w, 4513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch sp, 4523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch src1.bit() | src2.bit() | src3.bit() | src4.bit(), 4533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cond); 4543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 4553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ldr(src4, MemOperand(sp, 4, PostIndex), cond); 4563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond); 4573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 4593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Pop(src3, src4, cond); 4603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ldm(ia_w, sp, src1.bit() | src2.bit(), cond); 4613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 4633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Pop(src2, src3, src4, cond); 4643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ldr(src1, MemOperand(sp, 4, PostIndex), cond); 4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push a fixed frame, consisting of lr, fp, constant pool (if 4693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // FLAG_enable_embedded_constant_pool) 4703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch void PushCommonFrame(Register marker_reg = no_reg); 4713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 4723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Push a standard frame, consisting of lr, fp, constant pool (if 4733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // FLAG_enable_embedded_constant_pool), context and JS function 4743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch void PushStandardFrame(Register function_reg); 4753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 4763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch void PopCommonFrame(Register marker_reg = no_reg); 477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Push and pop the registers that can hold pointers, as defined by the 479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // RegList constant kSafepointSavedRegisters. 480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void PushSafepointRegisters(); 481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void PopSafepointRegisters(); 482e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Store value in register src in the safepoint stack slot for 483e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // register dst. 484e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void StoreToSafepointRegisterSlot(Register src, Register dst); 485e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Load the value of the src register from its safepoint stack slot 486e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // into register dst. 487e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void LoadFromSafepointRegisterSlot(Register dst, Register src); 488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 489f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load two consecutive registers with two consecutive memory locations. 490f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke void Ldrd(Register dst1, 491f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register dst2, 492f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke const MemOperand& src, 493f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Condition cond = al); 494f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 495f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Store two consecutive registers to two consecutive memory locations. 496f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke void Strd(Register src1, 497f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register src2, 498f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke const MemOperand& dst, 499f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Condition cond = al); 500f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the value is a NaN, canonicalize the value else, do nothing. 502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void VFPCanonicalizeNaN(const DwVfpRegister dst, 503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const DwVfpRegister src, 504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Condition cond = al); 505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void VFPCanonicalizeNaN(const DwVfpRegister value, 506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Condition cond = al) { 507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VFPCanonicalizeNaN(value, value, cond); 508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 509b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 510014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Compare single values and move the result to the normal condition flags. 511014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void VFPCompareAndSetFlags(const SwVfpRegister src1, const SwVfpRegister src2, 512014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const Condition cond = al); 513014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void VFPCompareAndSetFlags(const SwVfpRegister src1, const float src2, 514014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const Condition cond = al); 515014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 516b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Compare double values and move the result to the normal condition flags. 517b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch void VFPCompareAndSetFlags(const DwVfpRegister src1, 518b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch const DwVfpRegister src2, 519b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch const Condition cond = al); 520b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch void VFPCompareAndSetFlags(const DwVfpRegister src1, 521b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch const double src2, 522b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch const Condition cond = al); 523b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 524014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Compare single values and then load the fpscr flags to a register. 525014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void VFPCompareAndLoadFlags(const SwVfpRegister src1, 526014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const SwVfpRegister src2, 527014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const Register fpscr_flags, 528014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const Condition cond = al); 529014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void VFPCompareAndLoadFlags(const SwVfpRegister src1, const float src2, 530014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const Register fpscr_flags, 531014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const Condition cond = al); 532014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 533b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Compare double values and then load the fpscr flags to a register. 534b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch void VFPCompareAndLoadFlags(const DwVfpRegister src1, 535b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch const DwVfpRegister src2, 536b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch const Register fpscr_flags, 537b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch const Condition cond = al); 538b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch void VFPCompareAndLoadFlags(const DwVfpRegister src1, 539b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch const double src2, 540b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch const Register fpscr_flags, 541b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch const Condition cond = al); 542b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 5433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void Vmov(const DwVfpRegister dst, 5443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch const double imm, 545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register scratch = no_reg); 546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void VmovHigh(Register dst, DwVfpRegister src); 548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void VmovHigh(DwVfpRegister dst, Register src); 549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void VmovLow(Register dst, DwVfpRegister src); 550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void VmovLow(DwVfpRegister dst, Register src); 551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 552c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Simulate s-register moves for imaginary s32 - s63 registers. 553c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch void VmovExtended(Register dst, int src_code); 554c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch void VmovExtended(int dst_code, Register src); 555c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Move between s-registers and imaginary s-registers. 556c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch void VmovExtended(int dst_code, int src_code, Register scratch); 557c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch void VmovExtended(int dst_code, const MemOperand& src, Register scratch); 558c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch void VmovExtended(const MemOperand& dst, int src_code, Register scratch); 559c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 5603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch void LslPair(Register dst_low, Register dst_high, Register src_low, 5613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Register src_high, Register scratch, Register shift); 5623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch void LslPair(Register dst_low, Register dst_high, Register src_low, 5633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Register src_high, uint32_t shift); 5643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch void LsrPair(Register dst_low, Register dst_high, Register src_low, 5653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Register src_high, Register scratch, Register shift); 5663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch void LsrPair(Register dst_low, Register dst_high, Register src_low, 5673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Register src_high, uint32_t shift); 5683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch void AsrPair(Register dst_low, Register dst_high, Register src_low, 5693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Register src_high, Register scratch, Register shift); 5703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch void AsrPair(Register dst_low, Register dst_high, Register src_low, 5713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Register src_high, uint32_t shift); 5723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Loads the number from object into dst register. 574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If |object| is neither smi nor heap number, |not_number| is jumped to 575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // with |object| still intact. 576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void LoadNumber(Register object, 577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LowDwVfpRegister dst, 578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register heap_number_map, 579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch, 580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* not_number); 581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Loads the number from object into double_dst in the double format. 583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Control will jump to not_int32 if the value cannot be exactly represented 584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // by a 32-bit integer. 585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Floating point value in the 32-bit integer range that are not exact integer 586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // won't be loaded. 587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void LoadNumberAsInt32Double(Register object, 588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DwVfpRegister double_dst, 589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register heap_number_map, 590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch, 591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LowDwVfpRegister double_scratch, 592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* not_int32); 593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Loads the number from object into dst as a 32-bit integer. 595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Control will jump to not_int32 if the object cannot be exactly represented 596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // by a 32-bit integer. 597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Floating point value in the 32-bit integer range that are not exact integer 598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // won't be converted. 599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void LoadNumberAsInt32(Register object, 600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register dst, 601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register heap_number_map, 602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch, 603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DwVfpRegister double_scratch0, 604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LowDwVfpRegister double_scratch1, 605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* not_int32); 606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Generates function and stub prologue code. 6083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch void StubPrologue(StackFrame::Type type); 609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Prologue(bool code_pre_aging); 6103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 61180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Enter exit frame. 6121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // stack_space - extra stack space, used for alignment before call to C. 613f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch void EnterExitFrame(bool save_doubles, int stack_space = 0, 614f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch StackFrame::Type frame_type = StackFrame::EXIT); 615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Leave the current exit frame. Expects the return value in r0. 617e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Expect the number of values, pushed prior to the exit frame, to 618e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // remove in a register (or no_reg, if there is nothing to remove). 619014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void LeaveExitFrame(bool save_doubles, Register argument_count, 620014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool restore_context, 621014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool argument_count_is_length = false); 622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the actual activation frame alignment for target environment. 6246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static int ActivationFrameAlignment(); 625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 626d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void LoadContext(Register dst, int context_chain_length); 627d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 628014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Load the global object from the current context. 629014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void LoadGlobalObject(Register dst) { 630014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LoadNativeContextSlot(Context::EXTENSION_INDEX, dst); 631014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 632014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 633014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Load the global proxy from the current context. 634014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void LoadGlobalProxy(Register dst) { 635014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LoadNativeContextSlot(Context::GLOBAL_PROXY_INDEX, dst); 636014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 637014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 6383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Conditionally load the cached Array transitioned map of type 639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // transitioned_kind from the native context if the map in register 640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // map_in_out is the cached Array map in the native context of 6413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // expected_kind. 6423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void LoadTransitionedArrayMapConditional( 6433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind expected_kind, 6443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind transitioned_kind, 6453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register map_in_out, 6463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 6473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* no_map_match); 6483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 649014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void LoadNativeContextSlot(int index, Register dst); 6508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 6518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Load the initial map from the global function. The registers 6528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // function and map can be the same, function is then overwritten. 6538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang void LoadGlobalFunctionInitialMap(Register function, 6548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Register map, 6558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Register scratch); 6568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 657c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch void InitializeRootRegister() { 6583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference roots_array_start = 6593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference::roots_array_start(isolate()); 6603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(kRootRegister, Operand(roots_array_start)); 661c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch } 662c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // JavaScript invokes 665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Removes current frame and its arguments from the stack preserving 6673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // the arguments and a return address pushed to the stack for the next call. 6683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Both |callee_args_count| and |caller_args_count_reg| do not include 6693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // receiver. |callee_args_count| is not modified, |caller_args_count_reg| 6703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // is trashed. 6713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch void PrepareForTailCall(const ParameterCount& callee_args_count, 6723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Register caller_args_count_reg, Register scratch0, 6733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Register scratch1); 6743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the JavaScript function code by either calling or jumping. 676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void InvokeFunctionCode(Register function, Register new_target, 677014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const ParameterCount& expected, 678014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const ParameterCount& actual, InvokeFlag flag, 679014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const CallWrapper& call_wrapper); 680014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 681014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void FloodFunctionIfStepping(Register fun, Register new_target, 682014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const ParameterCount& expected, 683014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const ParameterCount& actual); 684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the JavaScript function in the given register. Changes the 686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // current context to the context in the function before invoking. 687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void InvokeFunction(Register function, 688014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register new_target, 689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 690b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch InvokeFlag flag, 691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CallWrapper& call_wrapper); 692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void InvokeFunction(Register function, 694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const ParameterCount& expected, 695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const ParameterCount& actual, 696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InvokeFlag flag, 697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CallWrapper& call_wrapper); 698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void InvokeFunction(Handle<JSFunction> function, 700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const ParameterCount& expected, 701402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu const ParameterCount& actual, 702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch InvokeFlag flag, 703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CallWrapper& call_wrapper); 704402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void IsObjectJSStringType(Register object, 706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register scratch, 707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label* fail); 708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void IsObjectNameType(Register object, 710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch, 711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fail); 712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Debugger Support 715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 716402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu void DebugBreak(); 717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exception handling 720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 721014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Push a new stack handler and link into stack handler chain. 722014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void PushStackHandler(); 723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 724014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Unlink the stack handler on top of the stack from the stack handler chain. 725e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Must preserve the result register. 726014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void PopStackHandler(); 727e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Inline caching support 730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 731c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch void GetNumberHash(Register t0, Register scratch); 7323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang inline void MarkCode(NopMarkerTypes type) { 7348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang nop(type); 7358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 7368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 7378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Check if the given instruction is a 'type' marker. 7383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // i.e. check if is is a mov r<type>, r<type> (referenced as nop(type)) 7398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // These instructions are generated to mark special location in the code, 7408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // like some special IC code. 7418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang static inline bool IsMarkedCode(Instr instr, int type) { 742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER)); 7438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang return IsNop(instr, type); 7448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 7458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 7468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 7478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang static inline int GetCodeMarker(Instr instr) { 7488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang int dst_reg_offset = 12; 7498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang int dst_mask = 0xf << dst_reg_offset; 7508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang int src_mask = 0xf; 7518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang int dst_reg = (instr & dst_mask) >> dst_reg_offset; 7528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang int src_reg = instr & src_mask; 7538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang uint32_t non_register_mask = ~(dst_mask | src_mask); 7548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang uint32_t mov_mask = al | 13 << 21; 7558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 7568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Return <n> if we have a mov rn rn, else return -1. 7578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang int type = ((instr & non_register_mask) == mov_mask) && 7588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang (dst_reg == src_reg) && 7598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang (FIRST_IC_MARKER <= dst_reg) && (dst_reg < LAST_CODE_MARKER) 7608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang ? src_reg 7618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang : -1; 762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((type == -1) || 7638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang ((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER))); 7648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang return type; 7658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 7668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocation support 770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 771014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Allocate an object in new space or old space. The object_size is 772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // specified either in bytes or in words if the allocation flag SIZE_IN_WORDS 773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is passed. If the space is exhausted control continues at the gc_required 774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // label. The allocated object is returned in result. If the flag 775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // tag_allocated_object is true the result is tagged as as a heap object. 776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // All registers are clobbered also when control continues at the gc_required 777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // label. 778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Allocate(int object_size, 779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result, 780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1, 781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2, 782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* gc_required, 783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationFlags flags); 784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 785014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void Allocate(Register object_size, Register result, Register result_end, 786014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register scratch, Label* gc_required, AllocationFlags flags); 7873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 788bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // FastAllocate is right now only used for folded allocations. It just 789bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // increments the top pointer without checking against limit. This can only 790bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // be done if it was proved earlier that the allocation will succeed. 791bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch void FastAllocate(int object_size, Register result, Register scratch1, 792bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register scratch2, AllocationFlags flags); 793bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 794bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch void FastAllocate(Register object_size, Register result, Register result_end, 795bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register scratch, AllocationFlags flags); 796bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 7973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void AllocateTwoByteString(Register result, 7983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register length, 7993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register scratch1, 8003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register scratch2, 8013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register scratch3, 8023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Label* gc_required); 803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void AllocateOneByteString(Register result, Register length, 804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1, Register scratch2, 805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch3, Label* gc_required); 8063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void AllocateTwoByteConsString(Register result, 8073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register length, 8083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register scratch1, 8093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register scratch2, 8103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Label* gc_required); 811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void AllocateOneByteConsString(Register result, Register length, 812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1, Register scratch2, 813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* gc_required); 814589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch void AllocateTwoByteSlicedString(Register result, 815589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register length, 816589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register scratch1, 817589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register scratch2, 818589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label* gc_required); 819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void AllocateOneByteSlicedString(Register result, Register length, 820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1, Register scratch2, 821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* gc_required); 8223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 82325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // Allocates a heap number or jumps to the gc_required label if the young 82425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // space is full and a scavenge is needed. All registers are clobbered also 82525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // when control continues at the gc_required label. 8266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void AllocateHeapNumber(Register result, 8276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch1, 8286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch2, 8299dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Register heap_number_map, 830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* gc_required, 831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MutableMode mode = IMMUTABLE); 8328defd9ff6930b4e24729971a61cf7469daf119beSteve Block void AllocateHeapNumberWithValue(Register result, 8338defd9ff6930b4e24729971a61cf7469daf119beSteve Block DwVfpRegister value, 8348defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register scratch1, 8358defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register scratch2, 8368defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register heap_number_map, 8378defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label* gc_required); 8388defd9ff6930b4e24729971a61cf7469daf119beSteve Block 839014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Allocate and initialize a JSValue wrapper with the specified {constructor} 840014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // and {value}. 841014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void AllocateJSValue(Register result, Register constructor, Register value, 842014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register scratch1, Register scratch2, 843014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label* gc_required); 8443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 845014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Initialize fields with filler values. Fields starting at |current_address| 846014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // not including |end_address| are overwritten with the value in |filler|. At 847014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // the end the loop, |current_address| takes the value of |end_address|. 848014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void InitializeFieldsWithFiller(Register current_address, 849014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register end_address, Register filler); 8503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Support functions. 853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 854014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Machine code version of Map::GetConstructor(). 855014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // |temp| holds |result|'s map when done, and |temp2| its instance type. 856014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void GetMapConstructor(Register result, Register map, Register temp, 857014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register temp2); 858014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Try to get function prototype of a function and puts the value in 860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the result register. Checks that the function really is a 861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // function and jumps to the miss label if the fast checks fail. The 862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // function register will be untouched; the other registers may be 863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // clobbered. 864014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void TryGetFunctionPrototype(Register function, Register result, 865014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register scratch, Label* miss); 866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compare object type for heap object. heap_object contains a non-Smi 868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // whose object type should be compared with the given type. This both 869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sets the flags and leaves the object type in the type_reg register. 870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // It leaves the map in the map register (unless the type_reg and map register 871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // are the same register). It leaves the heap object in the heap_object 872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // register unless the heap_object register is the same register as one of the 873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // other registers. 874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Type_reg can be no_reg. In that case ip is used. 875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void CompareObjectType(Register heap_object, 876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register map, 877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register type_reg, 878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstanceType type); 879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compare instance type in a map. map contains a valid map object whose 881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // object type should be compared with the given type. This both 882589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // sets the flags and leaves the object type in the type_reg register. 883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void CompareInstanceType(Register map, 884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register type_reg, 885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstanceType type); 886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if a map for a JSObject indicates that the object can have both smi 8883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // and HeapObject elements. Jump to the specified label if it does not. 8893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CheckFastObjectElements(Register map, 8903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 8913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* fail); 8923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if a map for a JSObject indicates that the object has fast smi only 8943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // elements. Jump to the specified label if it does not. 895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void CheckFastSmiElements(Register map, 896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch, 897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fail); 8983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check to see if maybe_number can be stored as a double in 9003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // FastDoubleElements. If it can, store it at the index specified by key in 901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the FastDoubleElements array elements. Otherwise jump to fail. 9023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void StoreNumberToDoubleElements(Register value_reg, 9033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register key_reg, 9043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register elements_reg, 9053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1, 906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LowDwVfpRegister double_scratch, 907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fail, 908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int elements_offset = 0); 9093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Compare an object's map with the specified map and its transitioned 9113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // elements maps if mode is ALLOW_ELEMENT_TRANSITION_MAPS. Condition flags are 9123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // set with result of map compare. If multiple map compares are required, the 9133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // compare sequences branches to early_success. 9143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CompareMap(Register obj, 9153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 9163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> map, 917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* early_success); 918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // As above, but the map of the object is already loaded into the register 920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // which is preserved by the code generated. 921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void CompareMap(Register obj_map, 922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> map, 923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* early_success); 9243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if the map of an object is equal to a specified map and branch to 9263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // label if not. Skip the smi check if not required (object is known to be a 9273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match 9283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // against maps that are ElementsKind transition maps of the specified map. 9293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void CheckMap(Register obj, 9303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register scratch, 9313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Handle<Map> map, 9323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Label* fail, 933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SmiCheckType smi_check_type); 934257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 9353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch void CheckMap(Register obj, 9377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch, 9387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Heap::RootListIndex index, 9397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label* fail, 940257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SmiCheckType smi_check_type); 941257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 942257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 943958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check if the map of an object is equal to a specified weak map and branch 944958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // to a specified target if equal. Skip the smi check if not required 945958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // (object is known to be a heap object) 946958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier void DispatchWeakMap(Register obj, Register scratch1, Register scratch2, 947958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<WeakCell> cell, Handle<Code> success, 948958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier SmiCheckType smi_check_type); 949958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 950958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Compare the given value and the value of weak cell. 951958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier void CmpWeakValue(Register value, Handle<WeakCell> cell, Register scratch); 9527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 953014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void GetWeakValue(Register value, Handle<WeakCell> cell); 954014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 955958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load the value of the weak cell in the value register. Branch to the given 956958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // miss label if the weak cell was cleared. 957958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier void LoadWeakValue(Register value, Handle<WeakCell> cell, Label* miss); 9587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 959e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Compare the object in a register to a value from the root list. 960e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Uses the ip register as scratch. 961e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void CompareRoot(Register obj, Heap::RootListIndex index); 962014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void PushRoot(Heap::RootListIndex index) { 963014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LoadRoot(ip, index); 964014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Push(ip); 965014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 966e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 967014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Compare the object in a register to a value and jump if they are equal. 968014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void JumpIfRoot(Register with, Heap::RootListIndex index, Label* if_equal) { 969014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CompareRoot(with, index); 970014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch b(eq, if_equal); 971014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 972014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 973014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Compare the object in a register to a value and jump if they are not equal. 974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void JumpIfNotRoot(Register with, Heap::RootListIndex index, 975014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label* if_not_equal) { 976014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CompareRoot(with, index); 977014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch b(ne, if_not_equal); 978014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 979e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 9803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Load and check the instance type of an object for being a string. 9813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Loads the type into the second argument register. 982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Returns a condition that will be enabled if the object was a string 983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // and the passed-in condition passed. If the passed-in condition failed 984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // then flags remain unchanged. 9853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Condition IsObjectStringType(Register obj, 986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register type, 987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond = al) { 988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ldr(type, FieldMemOperand(obj, HeapObject::kMapOffset), cond); 989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ldrb(type, FieldMemOperand(type, Map::kInstanceTypeOffset), cond); 990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch tst(type, Operand(kIsNotStringMask), cond); 991014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_EQ(0u, kStringTag); 9923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return eq; 9933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 9943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Get the number of least significant bits from a register 9973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits); 9981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void GetLeastBitsFromInt32(Register dst, Register src, int mun_least_bits); 9993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the value of a smi object into a double register. 1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The register value must be between d0 and d15. 1002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void SmiToDouble(LowDwVfpRegister value, Register smi); 1003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if a double can be exactly represented as a signed 32-bit integer. 1005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Z flag set to one if true. 1006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void TestDoubleIsInt32(DwVfpRegister double_input, 1007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LowDwVfpRegister double_scratch); 1008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Try to convert a double to a signed 32-bit integer. 1010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Z flag set to one and result assigned if the conversion is exact. 1011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void TryDoubleToInt32Exact(Register result, 1012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DwVfpRegister double_input, 1013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LowDwVfpRegister double_scratch); 1014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Floor a double and writes the value to the result register. 1016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Go to exact if the conversion is exact (to be able to test -0), 1017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // fall through calling code if an overflow occurred, else go to done. 1018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // In return, input_high is loaded with high bits of input. 1019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void TryInt32Floor(Register result, 1020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DwVfpRegister double_input, 1021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register input_high, 1022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LowDwVfpRegister double_scratch, 1023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* done, 1024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* exact); 1025d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Performs a truncating conversion of a floating point number as used by 1027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the JS bitwise operations. See ECMA-262 9.5: ToInt32. Goes to 'done' if it 1028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // succeeds, otherwise falls through if result is saturated. On return 1029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 'result' either holds answer, or is clobbered on fall through. 1030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 1031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Only public for the test code in test-code-stubs-arm.cc. 1032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void TryInlineTruncateDoubleToI(Register result, 1033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DwVfpRegister input, 1034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* done); 103544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 103644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Performs a truncating conversion of a floating point number as used by 103744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // the JS bitwise operations. See ECMA-262 9.5: ToInt32. 1038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Exits with 'result' holding the answer. 1039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void TruncateDoubleToI(Register result, DwVfpRegister double_input); 1040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Performs a truncating conversion of a heap number as used by 1042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the JS bitwise operations. See ECMA-262 9.5: ToInt32. 'result' and 'input' 1043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // must be different registers. Exits with 'result' holding the answer. 1044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void TruncateHeapNumberToI(Register result, Register object); 1045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Converts the smi or heap number in object to an int32 using the rules 1047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // for ToInt32 as described in ECMAScript 9.5.: the value is truncated 1048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // and brought into the range -2^31 .. +2^31 - 1. 'result' and 'input' must be 1049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // different registers. 1050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void TruncateNumberToI(Register object, 1051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result, 1052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register heap_number_map, 1053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1, 1054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* not_int32); 1055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check whether d16-d31 are available on the CPU. The result is given by the 1057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Z condition flag: Z==0 if d16-d31 available, Z==1 otherwise. 1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void CheckFor32DRegs(Register scratch); 1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Does a runtime check for 16/32 FP registers. Either way, pushes 32 double 1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // values to location, saving [d0..(d15|d31)]. 1062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void SaveFPRegs(Register location, Register scratch); 1063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Does a runtime check for 16/32 FP registers. Either way, pops 32 double 1065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // values to location, restoring [d0..(d15|d31)]. 1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void RestoreFPRegs(Register location, Register scratch); 1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1068f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Perform a floating-point min or max operation with the 1069f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // (IEEE-754-compatible) semantics of ARM64's fmin/fmax. Some cases, typically 1070f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // NaNs or +/-0.0, are expected to be rare and are handled in out-of-line 1071f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // code. The specific behaviour depends on supported instructions. 1072f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // 1073f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // These functions assume (and assert) that !left.is(right). It is permitted 1074f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // for the result to alias either input register. 1075f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void FloatMax(SwVfpRegister result, SwVfpRegister left, SwVfpRegister right, 1076f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label* out_of_line); 1077f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void FloatMin(SwVfpRegister result, SwVfpRegister left, SwVfpRegister right, 1078f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label* out_of_line); 1079f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void FloatMax(DwVfpRegister result, DwVfpRegister left, DwVfpRegister right, 1080f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label* out_of_line); 1081f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void FloatMin(DwVfpRegister result, DwVfpRegister left, DwVfpRegister right, 1082f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label* out_of_line); 1083f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1084f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Generate out-of-line cases for the macros above. 1085f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void FloatMaxOutOfLine(SwVfpRegister result, SwVfpRegister left, 1086f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch SwVfpRegister right); 1087f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void FloatMinOutOfLine(SwVfpRegister result, SwVfpRegister left, 1088f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch SwVfpRegister right); 1089f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void FloatMaxOutOfLine(DwVfpRegister result, DwVfpRegister left, 1090f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch DwVfpRegister right); 1091f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void FloatMinOutOfLine(DwVfpRegister result, DwVfpRegister left, 1092f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch DwVfpRegister right); 1093f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Runtime calls 1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call a code stub. 1098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void CallStub(CodeStub* stub, 1099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TypeFeedbackId ast_id = TypeFeedbackId::None(), 1100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond = al); 1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 11023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Call a code stub. 11033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void TailCallStub(CodeStub* stub, Condition cond = al); 11043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call a runtime routine. 1106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void CallRuntime(const Runtime::Function* f, 1107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int num_arguments, 1108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SaveFPRegsMode save_doubles = kDontSaveFPRegs); 1109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void CallRuntimeSaveDoubles(Runtime::FunctionId fid) { 1110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const Runtime::Function* function = Runtime::FunctionForId(fid); 1111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallRuntime(function, function->nargs, kSaveFPRegs); 1112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Convenience function: Same as above, but takes the fid instead. 1115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void CallRuntime(Runtime::FunctionId fid, 1116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SaveFPRegsMode save_doubles = kDontSaveFPRegs) { 1117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const Runtime::Function* function = Runtime::FunctionForId(fid); 1118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CallRuntime(function, function->nargs, save_doubles); 1119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Convenience function: Same as above, but takes the fid instead. 1122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void CallRuntime(Runtime::FunctionId fid, int num_arguments, 1123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SaveFPRegsMode save_doubles = kDontSaveFPRegs) { 1124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CallRuntime(Runtime::FunctionForId(fid), num_arguments, save_doubles); 1125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1127402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Convenience function: call an external reference. 1128402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu void CallExternalReference(const ExternalReference& ext, 1129402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu int num_arguments); 1130402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 11316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Convenience function: tail call a runtime routine (jump). 1132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void TailCallRuntime(Runtime::FunctionId fid); 1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int CalculateStackPassedWords(int num_reg_arguments, 1135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int num_double_arguments); 1136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 11376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Before calling a C-function from generated code, align arguments on stack. 11386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // After aligning the frame, non-register arguments must be stored in 11396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // sp[0], sp[4], etc., not pushed. The argument count assumes all arguments 1140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // are word sized. If double arguments are used, this function assumes that 1141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // all double arguments are stored before core registers; otherwise the 1142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // correct alignment of the double values is not guaranteed. 11436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Some compilers/platforms require the stack to be aligned when calling 11446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // C++ code. 11456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Needs a scratch register to do some arithmetic. This register will be 11466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // trashed. 1147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void PrepareCallCFunction(int num_reg_arguments, 1148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int num_double_registers, 1149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch); 1150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void PrepareCallCFunction(int num_reg_arguments, 1151257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch); 1152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // There are two ways of passing double arguments on ARM, depending on 1154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // whether soft or hard floating point ABI is used. These functions 1155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // abstract parameter passing for the three different ways we call 1156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // C functions from generated code. 1157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void MovToFloatParameter(DwVfpRegister src); 1158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void MovToFloatParameters(DwVfpRegister src1, DwVfpRegister src2); 1159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void MovToFloatResult(DwVfpRegister src); 11606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Calls a C function and cleans up the space for arguments allocated 11626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // by PrepareCallCFunction. The called function is not allowed to trigger a 11636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // garbage collection, since that might move the code and invalidate the 11646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // return address (unless this is somehow accounted for by the called 11656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // function). 11666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void CallCFunction(ExternalReference function, int num_arguments); 11673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CallCFunction(Register function, int num_arguments); 1168257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void CallCFunction(ExternalReference function, 1169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int num_reg_arguments, 1170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int num_double_arguments); 11713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CallCFunction(Register function, 1172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int num_reg_arguments, 1173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int num_double_arguments); 11746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void MovFromFloatParameter(DwVfpRegister dst); 1176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void MovFromFloatResult(DwVfpRegister dst); 1177e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to a runtime routine. 1179f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch void JumpToExternalReference(const ExternalReference& builtin, 1180f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch bool builtin_exit_frame = false); 1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 11828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Handle<Object> CodeObject() { 1183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!code_object_.is_null()); 11848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return code_object_; 11858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emit code for a truncating division by a constant. The dividend register is 1189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // unchanged and ip gets clobbered. Dividend and result must be different. 1190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void TruncatingDiv(Register result, Register dividend, int32_t divisor); 1191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // StatsCounter support 1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SetCounter(StatsCounter* counter, int value, 1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, Register scratch2); 1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void IncrementCounter(StatsCounter* counter, int value, 1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, Register scratch2); 1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void DecrementCounter(StatsCounter* counter, int value, 1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, Register scratch2); 1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Debugging 1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Calls Abort(msg) if the condition cond is not satisfied. 1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Use --debug_code to enable. 1208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Assert(Condition cond, BailoutReason reason); 1209756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick void AssertFastElements(Register elements); 1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Like Assert(), but always enabled. 1212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Check(Condition cond, BailoutReason reason); 1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Print a message to stdout and abort execution. 1215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Abort(BailoutReason msg); 1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Verify restrictions about code generated in stubs. 1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void set_generating_stub(bool value) { generating_stub_ = value; } 1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool generating_stub() { return generating_stub_; } 12203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void set_has_frame(bool value) { has_frame_ = value; } 12213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool has_frame() { return has_frame_; } 12223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch inline bool AllowThisStubCall(CodeStub* stub); 1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // EABI variant for double arguments in use. 1225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool use_eabi_hardfloat() { 1226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef __arm__ 1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return base::OS::ArmUsingHardFloat(); 1228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#elif USE_EABI_HARDFLOAT 1229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return true; 1230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#else 1231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return false; 1232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif 1233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1235d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // --------------------------------------------------------------------------- 12361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Number utilities 12371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 12381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check whether the value of reg is a power of two and not zero. If not 12391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // control continues at the label not_power_of_two. If reg is a power of two 12401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // the register scratch contains the value of (reg - 1) when control falls 12411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // through. 12421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void JumpIfNotPowerOfTwoOrZero(Register reg, 12431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register scratch, 12441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label* not_power_of_two_or_zero); 124544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check whether the value of reg is a power of two and not zero. 124644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Control falls through if it is, with scratch containing the mask 124744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // value (reg - 1). 124844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Otherwise control jumps to the 'zero_and_neg' label if the value of reg is 124944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // zero or negative, or jumps to the 'not_power_of_two' label if the value is 125044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // strictly positive but not a power of two. 125144f0eee88ff00398ff7f715fab053374d808c90dSteve Block void JumpIfNotPowerOfTwoOrZeroAndNeg(Register reg, 125244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch, 125344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* zero_and_neg, 125444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* not_power_of_two); 12551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 12561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // --------------------------------------------------------------------------- 12573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Smi utilities 12583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void SmiTag(Register reg, SBit s = LeaveCC) { 1260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch add(reg, reg, Operand(reg), s); 1261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 12621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void SmiTag(Register dst, Register src, SBit s = LeaveCC) { 12631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block add(dst, src, Operand(src), s); 12641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 1265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1266b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Try to convert int32 to smi. If the value is to large, preserve 1267b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // the original value and jump to not_a_smi. Destroys scratch and 1268b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // sets flags. 1269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void TrySmiTag(Register reg, Label* not_a_smi) { 1270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TrySmiTag(reg, reg, not_a_smi); 1271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void TrySmiTag(Register reg, Register src, Label* not_a_smi) { 1273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SmiTag(ip, src, SetCC); 1274b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch b(vs, not_a_smi); 1275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(reg, ip); 1276b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 1277b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1279e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void SmiUntag(Register reg, SBit s = LeaveCC) { 1280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(reg, Operand::SmiUntag(reg), s); 1281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1282e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void SmiUntag(Register dst, Register src, SBit s = LeaveCC) { 1283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(dst, Operand::SmiUntag(src), s); 12841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 1285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 12863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Untag the source value into destination and jump if source is a smi. 12873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Souce and destination can be the same register. 12883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void UntagAndJumpIfSmi(Register dst, Register src, Label* smi_case); 12893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 12903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Untag the source value into destination and jump if source is not a smi. 12913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Souce and destination can be the same register. 12923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void UntagAndJumpIfNotSmi(Register dst, Register src, Label* non_smi_case); 12933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Test if the register contains a smi (Z == 0 (eq) if true). 1295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline void SmiTst(Register value) { 1296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch tst(value, Operand(kSmiTagMask)); 1297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline void NonNegativeSmiTst(Register value) { 1299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch tst(value, Operand(kSmiTagMask | kSmiSignMask)); 1300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Jump if the register contains a smi. 13021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block inline void JumpIfSmi(Register value, Label* smi_label) { 13031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block tst(value, Operand(kSmiTagMask)); 13041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block b(eq, smi_label); 13051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 13061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Jump if either of the registers contain a non-smi. 13071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block inline void JumpIfNotSmi(Register value, Label* not_smi_label) { 13081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block tst(value, Operand(kSmiTagMask)); 13091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block b(ne, not_smi_label); 13101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 13113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Jump if either of the registers contain a non-smi. 13123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void JumpIfNotBothSmi(Register reg1, Register reg2, Label* on_not_both_smi); 13133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Jump if either of the registers contain a smi. 13143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi); 13153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Abort execution if argument is a number, enabled via --debug-code. 13173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch void AssertNotNumber(Register object); 13183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 1319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Abort execution if argument is a smi, enabled via --debug-code. 1320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void AssertNotSmi(Register object); 1321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void AssertSmi(Register object); 1322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Abort execution if argument is not a string, enabled via --debug-code. 1324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void AssertString(Register object); 13251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Abort execution if argument is not a name, enabled via --debug-code. 1327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void AssertName(Register object); 1328e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1329014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Abort execution if argument is not a JSFunction, enabled via --debug-code. 1330014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void AssertFunction(Register object); 1331014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1332014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Abort execution if argument is not a JSBoundFunction, 1333014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // enabled via --debug-code. 1334014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void AssertBoundFunction(Register object); 1335014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1336bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Abort execution if argument is not a JSGeneratorObject, 1337bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // enabled via --debug-code. 1338bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch void AssertGeneratorObject(Register object); 1339bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1340109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Abort execution if argument is not a JSReceiver, enabled via --debug-code. 1341109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch void AssertReceiver(Register object); 1342109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Abort execution if argument is not undefined or an AllocationSite, enabled 1344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // via --debug-code. 1345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void AssertUndefinedOrAllocationSite(Register object, Register scratch); 1346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Abort execution if reg is not the root value with the given index, 1348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // enabled via --debug-code. 1349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void AssertIsRoot(Register reg, Heap::RootListIndex index); 13501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 13511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // --------------------------------------------------------------------------- 13521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // HeapNumber utilities 13531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 13541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void JumpIfNotHeapNumber(Register object, 13551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register heap_number_map, 13561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register scratch, 13571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label* on_not_heap_number); 1358756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 13593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // --------------------------------------------------------------------------- 1360d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // String utilities 1361d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Checks if both objects are sequential one-byte strings and jumps to label 1363d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // if either is not. Assumes that neither object is a smi. 1364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void JumpIfNonSmisNotBothSequentialOneByteStrings(Register object1, 1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object2, 1366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1, 1367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2, 1368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* failure); 1369d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Checks if both objects are sequential one-byte strings and jumps to label 1371d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // if either is not. 1372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void JumpIfNotBothSequentialOneByteStrings(Register first, Register second, 1373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1, 1374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2, 1375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* not_flat_one_byte_strings); 1376d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Checks if both instance types are sequential one-byte strings and jumps to 13786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // label if either is not. 1379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void JumpIfBothInstanceTypesAreNotSequentialOneByte( 1380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register first_object_instance_type, Register second_object_instance_type, 1381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1, Register scratch2, Label* failure); 1382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if instance type is sequential one-byte string and jump to label if 13846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // it is not. 1385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void JumpIfInstanceTypeIsNotSequentialOneByte(Register type, Register scratch, 1386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* failure); 1387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void JumpIfNotUniqueNameInstanceType(Register reg, Label* not_unique_name); 13896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EmitSeqStringSetCharCheck(Register string, 1391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register index, 1392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value, 1393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t encoding_mask); 13946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void ClampUint8(Register output_reg, Register input_reg); 1397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void ClampDoubleToUint8(Register result_reg, 1399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DwVfpRegister input_reg, 1400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LowDwVfpRegister double_scratch); 1401257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1403257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void LoadInstanceDescriptors(Register map, Register descriptors); 1404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EnumLength(Register dst, Register map); 1405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void NumberOfOwnDescriptors(Register dst, Register map); 1406014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void LoadAccessor(Register dst, Register holder, int accessor_index, 1407014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch AccessorComponent accessor); 1408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template<typename Field> 1410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DecodeField(Register dst, Register src) { 1411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Ubfx(dst, src, Field::kShift, Field::kSize); 1412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template<typename Field> 1415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DecodeField(Register reg) { 1416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DecodeField<Field>(reg, reg); 1417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template<typename Field> 1420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DecodeFieldToSmi(Register dst, Register src) { 1421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int shift = Field::kShift; 1422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int mask = Field::kMask >> shift << kSmiTagSize; 1423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT((mask & (0x80000000u >> (kSmiTagSize - 1))) == 0); 1424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 1425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (shift < kSmiTagSize) { 1426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(dst, Operand(src, LSL, kSmiTagSize - shift)); 1427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch and_(dst, dst, Operand(mask)); 1428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (shift > kSmiTagSize) { 1429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(dst, Operand(src, LSR, shift - kSmiTagSize)); 1430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch and_(dst, dst, Operand(mask)); 1431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch and_(dst, src, Operand(mask)); 1433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template<typename Field> 1437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DecodeFieldToSmi(Register reg) { 1438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DecodeField<Field>(reg, reg); 1439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1440257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1441014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Load the type feedback vector from a JavaScript frame. 1442014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void EmitLoadTypeFeedbackVector(Register vector); 1443014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 14443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Activation support. 1445958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier void EnterFrame(StackFrame::Type type, 1446958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool load_constant_pool_pointer_reg = false); 1447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Returns the pc offset at which the frame ends. 1448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int LeaveFrame(StackFrame::Type type); 14493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1450f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch void EnterBuiltinFrame(Register context, Register target, Register argc); 1451f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch void LeaveBuiltinFrame(Register context, Register target, Register argc); 1452f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 14533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Expects object in r0 and returns map with validated enum cache 14543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // in r0. Assumes that any other register can be used as a scratch. 1455109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch void CheckEnumCache(Label* call_runtime); 14563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // AllocationMemento support. Arrays may have an associated 1458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // AllocationMemento object that can be checked for in order to pretransition 1459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to another type. 1460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // On entry, receiver_reg should point to the array object. 1461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // scratch_reg gets clobbered. 1462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If allocation info is present, condition flags are set to eq. 1463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void TestJSArrayForAllocationMemento(Register receiver_reg, 1464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch_reg, 1465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* no_memento_found); 1466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void JumpIfJSArrayHasAllocationMemento(Register receiver_reg, 1468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch_reg, 1469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* memento_found) { 1470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label no_memento_found; 1471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TestJSArrayForAllocationMemento(receiver_reg, scratch_reg, 1472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &no_memento_found); 1473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch b(eq, memento_found); 1474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bind(&no_memento_found); 1475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Jumps to found label if a prototype map has dictionary elements. 1478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void JumpIfDictionaryInPrototypeChain(Register object, Register scratch0, 1479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1, Label* found); 1480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1481014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Loads the constant pool pointer (pp) register. 1482014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void LoadConstantPoolPointerRegisterFromCodeTargetAddress( 1483014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register code_target_address); 1484014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void LoadConstantPoolPointerRegister(); 1485014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 148744f0eee88ff00398ff7f715fab053374d808c90dSteve Block void CallCFunctionHelper(Register function, 1488257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int num_reg_arguments, 1489257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int num_double_arguments); 149044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 14913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = al); 1492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Helper functions for generating invokes. 1494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void InvokePrologue(const ParameterCount& expected, 1495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 1496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* done, 14973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool* definitely_mismatches, 1498b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch InvokeFlag flag, 1499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CallWrapper& call_wrapper); 1500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 15016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void InitializeNewString(Register string, 15026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register length, 15036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Heap::RootListIndex map_index, 15046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch1, 15056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch2); 15066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Helper for implementing JumpIfNotInNewSpace and JumpIfInNewSpace. 15083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void InNewSpace(Register object, 15093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 15103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition cond, // eq for new space, ne otherwise. 15113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* branch); 15123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Helper for finding the mark bits for an address. Afterwards, the 15143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // bitmap register points at the word with the mark bits and the mask 15153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the position of the first bit. Leaves addr_reg unchanged. 15163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch inline void GetMarkBits(Register addr_reg, 15173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register bitmap_reg, 15183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register mask_reg); 15193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1520e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Compute memory operands for safepoint stack slots. 1521e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch static int SafepointRegisterStackIndex(int reg_code); 1522e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch MemOperand SafepointRegisterSlot(Register reg); 1523e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch MemOperand SafepointRegistersAndDoublesSlot(Register reg); 1524e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1525f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Implementation helpers for FloatMin and FloatMax. 1526f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch template <typename T> 1527f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void FloatMaxHelper(T result, T left, T right, Label* out_of_line); 1528f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch template <typename T> 1529f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void FloatMinHelper(T result, T left, T right, Label* out_of_line); 1530f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch template <typename T> 1531f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void FloatMaxOutOfLineHelper(T result, T left, T right); 1532f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch template <typename T> 1533f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void FloatMinOutOfLineHelper(T result, T left, T right); 1534f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 15353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu bool generating_stub_; 15363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool has_frame_; 15373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // This handle will be patched with the code object on installation. 15383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Handle<Object> code_object_; 1539e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Needs access to SafepointRegisterStackIndex for compiled frame 1541e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // traversal. 1542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch friend class StandardFrame; 1543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The code patcher is used to patch (typically) small parts of code e.g. for 1547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// debugging and other types of instrumentation. When using the code patcher 1548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the exact number of bytes specified must be emitted. It is not legal to emit 1549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// relocation information. If any of these constraints are violated it causes 1550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// an assertion to fail. 1551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass CodePatcher { 1552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 1553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch enum FlushICache { 1554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FLUSH, 1555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DONT_FLUSH 1556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 1557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1558014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CodePatcher(Isolate* isolate, byte* address, int instructions, 1559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FlushICache flush_cache = FLUSH); 1560014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ~CodePatcher(); 1561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Macro assembler to emit code. 1563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MacroAssembler* masm() { return &masm_; } 1564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Emit an instruction directly. 15661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void Emit(Instr instr); 1567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Emit an address directly. 1569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Emit(Address addr); 1570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 15711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Emit the condition part of an instruction leaving the rest of the current 15721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // instruction unchanged. 15731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void EmitCondition(Condition cond); 15741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 1576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* address_; // The address of the code being patched. 1577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int size_; // Number of bytes of the expected patch size. 1578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MacroAssembler masm_; // Macro assembler used to generate the code. 1579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FlushICache flush_cache_; // Whether to flush the I cache after patching. 1580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 1581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------- 1584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Static helper functions. 1585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1586014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochinline MemOperand ContextMemOperand(Register context, int index = 0) { 15878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang return MemOperand(context, Context::SlotOffset(index)); 15888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang} 15898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 15908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 1591014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochinline MemOperand NativeContextMemOperand() { 1592014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return ContextMemOperand(cp, Context::NATIVE_CONTEXT_INDEX); 15938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang} 15948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 1595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define ACCESS_MASM(masm) masm-> 1596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1597014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 1598014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 1599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // V8_ARM_MACRO_ASSEMBLER_ARM_H_ 1601