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); 18762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch void Move(QwNeonRegister dst, QwNeonRegister src); 18862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Register swap. 18962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch void Swap(DwVfpRegister srcdst0, DwVfpRegister srcdst1); 19062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch void Swap(QwNeonRegister srcdst0, QwNeonRegister srcdst1); 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Load(Register dst, const MemOperand& src, Representation r); 193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Store(Register src, const MemOperand& dst, Representation r); 194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load an object from the root table. 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void LoadRoot(Register destination, 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::RootListIndex index, 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Condition cond = al); 19925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // Store an object to the root table. 20025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen void StoreRoot(Register source, 20125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Heap::RootListIndex index, 20225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Condition cond = al); 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // --------------------------------------------------------------------------- 2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // GC Support 2063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void IncrementalMarkingRecordWriteHelper(Register object, 2083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register value, 2093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register address); 2103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch enum RememberedSetFinalAction { 2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kReturnAtEnd, 2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kFallThroughAtEnd 2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch }; 2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Record in the remembered set the fact that we have a pointer to new space 2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // at the address pointed to by the addr register. Only works if addr is not 2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // in new space. 2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void RememberedSetHelper(Register object, // Used for debug code. 2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register addr, 2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SaveFPRegsMode save_fp, 2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RememberedSetFinalAction and_then); 2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CheckPageFlag(Register object, 2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int mask, 2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition cc, 2293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* condition_met); 2303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if object is in new space. Jumps if the object is not in new space. 2323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The register scratch can be object itself, but scratch will be clobbered. 2333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void JumpIfNotInNewSpace(Register object, 2343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* branch) { 236109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch InNewSpace(object, scratch, eq, branch); 2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if object is in new space. Jumps if the object is in new space. 2403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The register scratch can be object itself, but it will be clobbered. 2413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void JumpIfInNewSpace(Register object, 2423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 2433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* branch) { 244109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch InNewSpace(object, scratch, ne, branch); 2453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if an object has a given incremental marking color. 2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void HasColor(Register object, 2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch0, 2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1, 2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* has_color, 2523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int first_bit, 2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int second_bit); 2548defd9ff6930b4e24729971a61cf7469daf119beSteve Block 2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void JumpIfBlack(Register object, 2569dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Register scratch0, 2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1, 2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* on_black); 2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Checks the color of an object. If the object is white we jump to the 261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // incremental marker. 262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void JumpIfWhite(Register value, Register scratch1, Register scratch2, 263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register scratch3, Label* value_is_white); 2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Notify the garbage collector that we wrote a pointer into an object. 2663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // |object| is the object being stored into, |value| is the object being 2673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // stored. value and scratch registers are clobbered by the operation. 2683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The offset is the offset from the start of the object, not the offset from 269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // the tagged HeapObject pointer. For use with FieldMemOperand(reg, off). 2703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void RecordWriteField( 2713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object, 2723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int offset, 2733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register value, 2743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 2753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LinkRegisterStatus lr_status, 2763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SaveFPRegsMode save_fp, 2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, 278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SmiCheck smi_check = INLINE_SMI_CHECK, 279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PointersToHereCheck pointers_to_here_check_for_value = 280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kPointersToHereMaybeInteresting); 2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // As above, but the offset has the tag presubtracted. For use with 2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // MemOperand(reg, off). 2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch inline void RecordWriteContextSlot( 2853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register context, 2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int offset, 2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register value, 2883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 2893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LinkRegisterStatus lr_status, 2903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SaveFPRegsMode save_fp, 2913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, 292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SmiCheck smi_check = INLINE_SMI_CHECK, 293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PointersToHereCheck pointers_to_here_check_for_value = 294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kPointersToHereMaybeInteresting) { 2953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RecordWriteField(context, 2963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch offset + kHeapObjectTag, 2973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value, 2983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 2993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lr_status, 3003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch save_fp, 3013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch remembered_set_action, 302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch smi_check, 303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch pointers_to_here_check_for_value); 3043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 305592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 306109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Notify the garbage collector that we wrote a code entry into a 307109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // JSFunction. Only scratch is clobbered by the operation. 308109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch void RecordWriteCodeEntryField(Register js_function, Register code_entry, 309109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register scratch); 310109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void RecordWriteForMap( 312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object, 313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register map, 314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register dst, 315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LinkRegisterStatus lr_status, 316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SaveFPRegsMode save_fp); 317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // For a given |object| notify the garbage collector that the slot |address| 3193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // has been written. |value| is the object being stored. The value and 3203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // address registers are clobbered by the operation. 3213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void RecordWrite( 3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object, 3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register address, 3243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register value, 3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LinkRegisterStatus lr_status, 3263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SaveFPRegsMode save_fp, 3273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, 328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SmiCheck smi_check = INLINE_SMI_CHECK, 329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PointersToHereCheck pointers_to_here_check_for_value = 330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kPointersToHereMaybeInteresting); 3318defd9ff6930b4e24729971a61cf7469daf119beSteve Block 3323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Push a handle. 3333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void Push(Handle<Object> handle); 334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Push(Smi* smi) { Push(Handle<Smi>(smi, isolate())); } 3353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 3366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Push two registers. Pushes leftmost register first (to highest address). 3376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void Push(Register src1, Register src2, Condition cond = al) { 3386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (src1.code() > src2.code()) { 3396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block stm(db_w, sp, src1.bit() | src2.bit(), cond); 3406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 3416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block str(src1, MemOperand(sp, 4, NegPreIndex), cond); 3426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block str(src2, MemOperand(sp, 4, NegPreIndex), cond); 3436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Push three registers. Pushes leftmost register first (to highest address). 3476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void Push(Register src1, Register src2, Register src3, Condition cond = al) { 3486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (src1.code() > src2.code()) { 3496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (src2.code() > src3.code()) { 3506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond); 3516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 3526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block stm(db_w, sp, src1.bit() | src2.bit(), cond); 3536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block str(src3, MemOperand(sp, 4, NegPreIndex), cond); 3546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 3566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block str(src1, MemOperand(sp, 4, NegPreIndex), cond); 3576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Push(src2, src3, cond); 3586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Push four registers. Pushes leftmost register first (to highest address). 3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void Push(Register src1, 3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register src2, 3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register src3, 3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register src4, 3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition cond = al) { 3676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (src1.code() > src2.code()) { 3686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (src2.code() > src3.code()) { 3696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (src3.code() > src4.code()) { 3706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block stm(db_w, 3716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block sp, 3726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block src1.bit() | src2.bit() | src3.bit() | src4.bit(), 3736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block cond); 3746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 3756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond); 3766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block str(src4, MemOperand(sp, 4, NegPreIndex), cond); 3776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 3796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block stm(db_w, sp, src1.bit() | src2.bit(), cond); 3806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Push(src3, src4, cond); 3816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 3836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block str(src1, MemOperand(sp, 4, NegPreIndex), cond); 3846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Push(src2, src3, src4, cond); 3856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Push five registers. Pushes leftmost register first (to highest address). 389014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void Push(Register src1, Register src2, Register src3, Register src4, 390014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register src5, Condition cond = al) { 391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (src1.code() > src2.code()) { 392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (src2.code() > src3.code()) { 393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (src3.code() > src4.code()) { 394014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (src4.code() > src5.code()) { 395014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch stm(db_w, sp, 396014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch src1.bit() | src2.bit() | src3.bit() | src4.bit() | src5.bit(), 397014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch cond); 398014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 399014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch stm(db_w, sp, src1.bit() | src2.bit() | src3.bit() | src4.bit(), 400014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch cond); 401014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch str(src5, MemOperand(sp, 4, NegPreIndex), cond); 402014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 404014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond); 405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Push(src4, src5, cond); 406014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 407014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 408014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch stm(db_w, sp, src1.bit() | src2.bit(), cond); 409014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Push(src3, src4, src5, cond); 410014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 411014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 412014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch str(src1, MemOperand(sp, 4, NegPreIndex), cond); 413014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Push(src2, src3, src4, src5, cond); 414014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 415014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 416014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 417e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Pop two registers. Pops rightmost register first (from lower address). 418e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void Pop(Register src1, Register src2, Condition cond = al) { 419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!src1.is(src2)); 420e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (src1.code() > src2.code()) { 421e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ldm(ia_w, sp, src1.bit() | src2.bit(), cond); 422e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 423e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ldr(src2, MemOperand(sp, 4, PostIndex), cond); 424e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ldr(src1, MemOperand(sp, 4, PostIndex), cond); 425e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 426e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 427e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Pop three registers. Pops rightmost register first (from lower address). 4293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void Pop(Register src1, Register src2, Register src3, Condition cond = al) { 430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!AreAliased(src1, src2, src3)); 4313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (src1.code() > src2.code()) { 4323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (src2.code() > src3.code()) { 4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond); 4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ldr(src3, MemOperand(sp, 4, PostIndex), cond); 4363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ldm(ia_w, sp, src1.bit() | src2.bit(), cond); 4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 4393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Pop(src2, src3, cond); 440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ldr(src1, MemOperand(sp, 4, PostIndex), cond); 4413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Pop four registers. Pops rightmost register first (from lower address). 4453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void Pop(Register src1, 4463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register src2, 4473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register src3, 4483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register src4, 4493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition cond = al) { 450014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!AreAliased(src1, src2, src3, src4)); 4513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (src1.code() > src2.code()) { 4523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (src2.code() > src3.code()) { 4533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (src3.code() > src4.code()) { 4543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ldm(ia_w, 4553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch sp, 4563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch src1.bit() | src2.bit() | src3.bit() | src4.bit(), 4573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cond); 4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 4593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ldr(src4, MemOperand(sp, 4, PostIndex), cond); 4603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond); 4613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 4633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Pop(src3, src4, cond); 4643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ldm(ia_w, sp, src1.bit() | src2.bit(), cond); 4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Pop(src2, src3, src4, cond); 4683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ldr(src1, MemOperand(sp, 4, PostIndex), cond); 4693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push a fixed frame, consisting of lr, fp, constant pool (if 4733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // FLAG_enable_embedded_constant_pool) 4743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch void PushCommonFrame(Register marker_reg = no_reg); 4753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 4763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Push a standard frame, consisting of lr, fp, constant pool (if 4773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // FLAG_enable_embedded_constant_pool), context and JS function 4783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch void PushStandardFrame(Register function_reg); 4793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 4803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch void PopCommonFrame(Register marker_reg = no_reg); 481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Push and pop the registers that can hold pointers, as defined by the 483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // RegList constant kSafepointSavedRegisters. 484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void PushSafepointRegisters(); 485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void PopSafepointRegisters(); 486e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Store value in register src in the safepoint stack slot for 487e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // register dst. 488e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void StoreToSafepointRegisterSlot(Register src, Register dst); 489e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Load the value of the src register from its safepoint stack slot 490e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // into register dst. 491e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void LoadFromSafepointRegisterSlot(Register dst, Register src); 492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 493f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load two consecutive registers with two consecutive memory locations. 494f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke void Ldrd(Register dst1, 495f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register dst2, 496f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke const MemOperand& src, 497f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Condition cond = al); 498f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 499f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Store two consecutive registers to two consecutive memory locations. 500f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke void Strd(Register src1, 501f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register src2, 502f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke const MemOperand& dst, 503f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Condition cond = al); 504f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the value is a NaN, canonicalize the value else, do nothing. 506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void VFPCanonicalizeNaN(const DwVfpRegister dst, 507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const DwVfpRegister src, 508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Condition cond = al); 509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void VFPCanonicalizeNaN(const DwVfpRegister value, 510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Condition cond = al) { 511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VFPCanonicalizeNaN(value, value, cond); 512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 513b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 514014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Compare single values and move the result to the normal condition flags. 515014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void VFPCompareAndSetFlags(const SwVfpRegister src1, const SwVfpRegister src2, 516014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const Condition cond = al); 517014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void VFPCompareAndSetFlags(const SwVfpRegister src1, const float src2, 518014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const Condition cond = al); 519014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 520b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Compare double values and move the result to the normal condition flags. 521b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch void VFPCompareAndSetFlags(const DwVfpRegister src1, 522b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch const DwVfpRegister src2, 523b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch const Condition cond = al); 524b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch void VFPCompareAndSetFlags(const DwVfpRegister src1, 525b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch const double src2, 526b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch const Condition cond = al); 527b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 528014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Compare single values and then load the fpscr flags to a register. 529014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void VFPCompareAndLoadFlags(const SwVfpRegister src1, 530014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const SwVfpRegister src2, 531014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const Register fpscr_flags, 532014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const Condition cond = al); 533014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void VFPCompareAndLoadFlags(const SwVfpRegister src1, const float src2, 534014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const Register fpscr_flags, 535014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const Condition cond = al); 536014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 537b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Compare double values and then load the fpscr flags to a register. 538b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch void VFPCompareAndLoadFlags(const DwVfpRegister src1, 539b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch const DwVfpRegister src2, 540b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch const Register fpscr_flags, 541b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch const Condition cond = al); 542b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch void VFPCompareAndLoadFlags(const DwVfpRegister src1, 543b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch const double src2, 544b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch const Register fpscr_flags, 545b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch const Condition cond = al); 546b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 5473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void Vmov(const DwVfpRegister dst, 5483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch const double imm, 549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register scratch = no_reg); 550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void VmovHigh(Register dst, DwVfpRegister src); 552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void VmovHigh(DwVfpRegister dst, Register src); 553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void VmovLow(Register dst, DwVfpRegister src); 554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void VmovLow(DwVfpRegister dst, Register src); 555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 556c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Simulate s-register moves for imaginary s32 - s63 registers. 557c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch void VmovExtended(Register dst, int src_code); 558c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch void VmovExtended(int dst_code, Register src); 559c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Move between s-registers and imaginary s-registers. 560c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch void VmovExtended(int dst_code, int src_code, Register scratch); 561c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch void VmovExtended(int dst_code, const MemOperand& src, Register scratch); 562c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch void VmovExtended(const MemOperand& dst, int src_code, Register scratch); 563c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 56462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch void ExtractLane(Register dst, QwNeonRegister src, NeonDataType dt, int lane); 56562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch void ExtractLane(SwVfpRegister dst, QwNeonRegister src, Register scratch, 56662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int lane); 56762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch void ReplaceLane(QwNeonRegister dst, QwNeonRegister src, Register src_lane, 56862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch NeonDataType dt, int lane); 56962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch void ReplaceLane(QwNeonRegister dst, QwNeonRegister src, 57062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SwVfpRegister src_lane, Register scratch, int lane); 57162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch void Swizzle(QwNeonRegister dst, QwNeonRegister src, Register scratch, 57262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch NeonSize size, uint32_t lanes); 57362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 5743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch void LslPair(Register dst_low, Register dst_high, Register src_low, 5753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Register src_high, Register scratch, Register shift); 5763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch void LslPair(Register dst_low, Register dst_high, Register src_low, 5773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Register src_high, uint32_t shift); 5783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch void LsrPair(Register dst_low, Register dst_high, Register src_low, 5793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Register src_high, Register scratch, Register shift); 5803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch void LsrPair(Register dst_low, Register dst_high, Register src_low, 5813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Register src_high, uint32_t shift); 5823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch void AsrPair(Register dst_low, Register dst_high, Register src_low, 5833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Register src_high, Register scratch, Register shift); 5843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch void AsrPair(Register dst_low, Register dst_high, Register src_low, 5853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Register src_high, uint32_t shift); 5863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Loads the number from object into dst register. 588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If |object| is neither smi nor heap number, |not_number| is jumped to 589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // with |object| still intact. 590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void LoadNumber(Register object, 591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LowDwVfpRegister dst, 592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register heap_number_map, 593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch, 594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* not_number); 595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Loads the number from object into double_dst in the double format. 597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Control will jump to not_int32 if the value cannot be exactly represented 598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // by a 32-bit integer. 599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Floating point value in the 32-bit integer range that are not exact integer 600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // won't be loaded. 601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void LoadNumberAsInt32Double(Register object, 602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DwVfpRegister double_dst, 603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register heap_number_map, 604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch, 605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LowDwVfpRegister double_scratch, 606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* not_int32); 607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Loads the number from object into dst as a 32-bit integer. 609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Control will jump to not_int32 if the object cannot be exactly represented 610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // by a 32-bit integer. 611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Floating point value in the 32-bit integer range that are not exact integer 612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // won't be converted. 613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void LoadNumberAsInt32(Register object, 614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register dst, 615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register heap_number_map, 616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch, 617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DwVfpRegister double_scratch0, 618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LowDwVfpRegister double_scratch1, 619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* not_int32); 620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Generates function and stub prologue code. 6223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch void StubPrologue(StackFrame::Type type); 623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Prologue(bool code_pre_aging); 6243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 62580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Enter exit frame. 6261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // stack_space - extra stack space, used for alignment before call to C. 627f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch void EnterExitFrame(bool save_doubles, int stack_space = 0, 628f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch StackFrame::Type frame_type = StackFrame::EXIT); 629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Leave the current exit frame. Expects the return value in r0. 631e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Expect the number of values, pushed prior to the exit frame, to 632e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // remove in a register (or no_reg, if there is nothing to remove). 633014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void LeaveExitFrame(bool save_doubles, Register argument_count, 634014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool restore_context, 635014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool argument_count_is_length = false); 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the actual activation frame alignment for target environment. 6386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static int ActivationFrameAlignment(); 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 640d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void LoadContext(Register dst, int context_chain_length); 641d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 642014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Load the global object from the current context. 643014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void LoadGlobalObject(Register dst) { 644014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LoadNativeContextSlot(Context::EXTENSION_INDEX, dst); 645014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 646014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 647014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Load the global proxy from the current context. 648014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void LoadGlobalProxy(Register dst) { 649014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LoadNativeContextSlot(Context::GLOBAL_PROXY_INDEX, dst); 650014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 651014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 652014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void LoadNativeContextSlot(int index, Register dst); 6538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 6548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Load the initial map from the global function. The registers 6558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // function and map can be the same, function is then overwritten. 6568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang void LoadGlobalFunctionInitialMap(Register function, 6578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Register map, 6588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Register scratch); 6598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 660c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch void InitializeRootRegister() { 6613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference roots_array_start = 6623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference::roots_array_start(isolate()); 6633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(kRootRegister, Operand(roots_array_start)); 664c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch } 665c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // JavaScript invokes 668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Removes current frame and its arguments from the stack preserving 6703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // the arguments and a return address pushed to the stack for the next call. 6713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Both |callee_args_count| and |caller_args_count_reg| do not include 6723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // receiver. |callee_args_count| is not modified, |caller_args_count_reg| 6733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // is trashed. 6743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch void PrepareForTailCall(const ParameterCount& callee_args_count, 6753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Register caller_args_count_reg, Register scratch0, 6763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Register scratch1); 6773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the JavaScript function code by either calling or jumping. 679014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void InvokeFunctionCode(Register function, Register new_target, 680014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const ParameterCount& expected, 681014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const ParameterCount& actual, InvokeFlag flag, 682014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const CallWrapper& call_wrapper); 683014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 68462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // On function call, call into the debugger if necessary. 68562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch void CheckDebugHook(Register fun, Register new_target, 68662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const ParameterCount& expected, 68762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const ParameterCount& actual); 688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the JavaScript function in the given register. Changes the 690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // current context to the context in the function before invoking. 691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void InvokeFunction(Register function, 692014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register new_target, 693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 694b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch InvokeFlag flag, 695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CallWrapper& call_wrapper); 696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void InvokeFunction(Register function, 698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const ParameterCount& expected, 699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const ParameterCount& actual, 700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InvokeFlag flag, 701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CallWrapper& call_wrapper); 702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void InvokeFunction(Handle<JSFunction> function, 704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const ParameterCount& expected, 705402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu const ParameterCount& actual, 706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch InvokeFlag flag, 707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CallWrapper& call_wrapper); 708402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void IsObjectJSStringType(Register object, 710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register scratch, 711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label* fail); 712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void IsObjectNameType(Register object, 714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch, 715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fail); 716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 71762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Frame restart support 71862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch void MaybeDropFrames(); 719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exception handling 721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 722014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Push a new stack handler and link into stack handler chain. 723014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void PushStackHandler(); 724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 725014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Unlink the stack handler on top of the stack from the stack handler chain. 726e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Must preserve the result register. 727014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void PopStackHandler(); 728e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Inline caching support 731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 732c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch void GetNumberHash(Register t0, Register scratch); 7333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang inline void MarkCode(NopMarkerTypes type) { 7358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang nop(type); 7368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 7378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 7388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Check if the given instruction is a 'type' marker. 7393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // i.e. check if is is a mov r<type>, r<type> (referenced as nop(type)) 7408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // These instructions are generated to mark special location in the code, 7418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // like some special IC code. 7428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang static inline bool IsMarkedCode(Instr instr, int type) { 743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER)); 7448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang return IsNop(instr, type); 7458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 7468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 7478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 7488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang static inline int GetCodeMarker(Instr instr) { 7498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang int dst_reg_offset = 12; 7508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang int dst_mask = 0xf << dst_reg_offset; 7518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang int src_mask = 0xf; 7528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang int dst_reg = (instr & dst_mask) >> dst_reg_offset; 7538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang int src_reg = instr & src_mask; 7548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang uint32_t non_register_mask = ~(dst_mask | src_mask); 7558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang uint32_t mov_mask = al | 13 << 21; 7568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 7578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Return <n> if we have a mov rn rn, else return -1. 7588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang int type = ((instr & non_register_mask) == mov_mask) && 7598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang (dst_reg == src_reg) && 7608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang (FIRST_IC_MARKER <= dst_reg) && (dst_reg < LAST_CODE_MARKER) 7618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang ? src_reg 7628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang : -1; 763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((type == -1) || 7648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang ((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER))); 7658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang return type; 7668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 7678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocation support 771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 772014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Allocate an object in new space or old space. The object_size is 773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // specified either in bytes or in words if the allocation flag SIZE_IN_WORDS 774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is passed. If the space is exhausted control continues at the gc_required 775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // label. The allocated object is returned in result. If the flag 776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // tag_allocated_object is true the result is tagged as as a heap object. 777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // All registers are clobbered also when control continues at the gc_required 778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // label. 779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Allocate(int object_size, 780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result, 781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1, 782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2, 783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* gc_required, 784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationFlags flags); 785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 786014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void Allocate(Register object_size, Register result, Register result_end, 787014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register scratch, Label* gc_required, AllocationFlags flags); 7883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 789bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // FastAllocate is right now only used for folded allocations. It just 790bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // increments the top pointer without checking against limit. This can only 791bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // be done if it was proved earlier that the allocation will succeed. 792bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch void FastAllocate(int object_size, Register result, Register scratch1, 793bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register scratch2, AllocationFlags flags); 794bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 795bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch void FastAllocate(Register object_size, Register result, Register result_end, 796bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register scratch, AllocationFlags flags); 797bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 79825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // Allocates a heap number or jumps to the gc_required label if the young 79925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // space is full and a scavenge is needed. All registers are clobbered also 80025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // when control continues at the gc_required label. 8016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void AllocateHeapNumber(Register result, 8026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch1, 8036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch2, 8049dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Register heap_number_map, 805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* gc_required, 806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MutableMode mode = IMMUTABLE); 8078defd9ff6930b4e24729971a61cf7469daf119beSteve Block void AllocateHeapNumberWithValue(Register result, 8088defd9ff6930b4e24729971a61cf7469daf119beSteve Block DwVfpRegister value, 8098defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register scratch1, 8108defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register scratch2, 8118defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register heap_number_map, 8128defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label* gc_required); 8138defd9ff6930b4e24729971a61cf7469daf119beSteve Block 814014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Allocate and initialize a JSValue wrapper with the specified {constructor} 815014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // and {value}. 816014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void AllocateJSValue(Register result, Register constructor, Register value, 817014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register scratch1, Register scratch2, 818014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label* gc_required); 8193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 820014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Initialize fields with filler values. Fields starting at |current_address| 821014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // not including |end_address| are overwritten with the value in |filler|. At 822014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // the end the loop, |current_address| takes the value of |end_address|. 823014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void InitializeFieldsWithFiller(Register current_address, 824014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register end_address, Register filler); 8253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Support functions. 828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 829014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Machine code version of Map::GetConstructor(). 830014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // |temp| holds |result|'s map when done, and |temp2| its instance type. 831014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void GetMapConstructor(Register result, Register map, Register temp, 832014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register temp2); 833014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compare object type for heap object. heap_object contains a non-Smi 835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // whose object type should be compared with the given type. This both 836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sets the flags and leaves the object type in the type_reg register. 837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // It leaves the map in the map register (unless the type_reg and map register 838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // are the same register). It leaves the heap object in the heap_object 839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // register unless the heap_object register is the same register as one of the 840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // other registers. 841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Type_reg can be no_reg. In that case ip is used. 842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void CompareObjectType(Register heap_object, 843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register map, 844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register type_reg, 845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstanceType type); 846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compare instance type in a map. map contains a valid map object whose 848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // object type should be compared with the given type. This both 849589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // sets the flags and leaves the object type in the type_reg register. 850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void CompareInstanceType(Register map, 851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register type_reg, 852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstanceType type); 853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Compare an object's map with the specified map and its transitioned 8553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // elements maps if mode is ALLOW_ELEMENT_TRANSITION_MAPS. Condition flags are 8563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // set with result of map compare. If multiple map compares are required, the 8573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // compare sequences branches to early_success. 8583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CompareMap(Register obj, 8593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 8603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> map, 861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* early_success); 862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // As above, but the map of the object is already loaded into the register 864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // which is preserved by the code generated. 865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void CompareMap(Register obj_map, 866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> map, 867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* early_success); 8683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if the map of an object is equal to a specified map and branch to 8703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // label if not. Skip the smi check if not required (object is known to be a 8713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match 8723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // against maps that are ElementsKind transition maps of the specified map. 8733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void CheckMap(Register obj, 8743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register scratch, 8753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Handle<Map> map, 8763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Label* fail, 877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SmiCheckType smi_check_type); 878257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 8793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 8807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch void CheckMap(Register obj, 8817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch, 8827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Heap::RootListIndex index, 8837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label* fail, 884257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SmiCheckType smi_check_type); 885257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 886257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 887958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check if the map of an object is equal to a specified weak map and branch 888958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // to a specified target if equal. Skip the smi check if not required 889958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // (object is known to be a heap object) 890958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier void DispatchWeakMap(Register obj, Register scratch1, Register scratch2, 891958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<WeakCell> cell, Handle<Code> success, 892958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier SmiCheckType smi_check_type); 893958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 894958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Compare the given value and the value of weak cell. 895958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier void CmpWeakValue(Register value, Handle<WeakCell> cell, Register scratch); 8967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 897014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void GetWeakValue(Register value, Handle<WeakCell> cell); 898014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 899958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load the value of the weak cell in the value register. Branch to the given 900958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // miss label if the weak cell was cleared. 901958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier void LoadWeakValue(Register value, Handle<WeakCell> cell, Label* miss); 9027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 903e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Compare the object in a register to a value from the root list. 904e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Uses the ip register as scratch. 905e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void CompareRoot(Register obj, Heap::RootListIndex index); 906014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void PushRoot(Heap::RootListIndex index) { 907014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LoadRoot(ip, index); 908014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Push(ip); 909014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 910e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 911014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Compare the object in a register to a value and jump if they are equal. 912014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void JumpIfRoot(Register with, Heap::RootListIndex index, Label* if_equal) { 913014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CompareRoot(with, index); 914014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch b(eq, if_equal); 915014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 916014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 917014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Compare the object in a register to a value and jump if they are not equal. 918014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void JumpIfNotRoot(Register with, Heap::RootListIndex index, 919014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label* if_not_equal) { 920014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CompareRoot(with, index); 921014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch b(ne, if_not_equal); 922014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 923e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 9243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Load and check the instance type of an object for being a string. 9253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Loads the type into the second argument register. 926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Returns a condition that will be enabled if the object was a string 927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // and the passed-in condition passed. If the passed-in condition failed 928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // then flags remain unchanged. 9293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Condition IsObjectStringType(Register obj, 930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register type, 931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond = al) { 932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ldr(type, FieldMemOperand(obj, HeapObject::kMapOffset), cond); 933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ldrb(type, FieldMemOperand(type, Map::kInstanceTypeOffset), cond); 934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch tst(type, Operand(kIsNotStringMask), cond); 935014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_EQ(0u, kStringTag); 9363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return eq; 9373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 9383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Get the number of least significant bits from a register 9413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits); 9421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void GetLeastBitsFromInt32(Register dst, Register src, int mun_least_bits); 9433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the value of a smi object into a double register. 945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The register value must be between d0 and d15. 946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void SmiToDouble(LowDwVfpRegister value, Register smi); 947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if a double can be exactly represented as a signed 32-bit integer. 949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Z flag set to one if true. 950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void TestDoubleIsInt32(DwVfpRegister double_input, 951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LowDwVfpRegister double_scratch); 952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Try to convert a double to a signed 32-bit integer. 954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Z flag set to one and result assigned if the conversion is exact. 955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void TryDoubleToInt32Exact(Register result, 956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DwVfpRegister double_input, 957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LowDwVfpRegister double_scratch); 958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Floor a double and writes the value to the result register. 960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Go to exact if the conversion is exact (to be able to test -0), 961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // fall through calling code if an overflow occurred, else go to done. 962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // In return, input_high is loaded with high bits of input. 963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void TryInt32Floor(Register result, 964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DwVfpRegister double_input, 965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register input_high, 966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LowDwVfpRegister double_scratch, 967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* done, 968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* exact); 969d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Performs a truncating conversion of a floating point number as used by 971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the JS bitwise operations. See ECMA-262 9.5: ToInt32. Goes to 'done' if it 972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // succeeds, otherwise falls through if result is saturated. On return 973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 'result' either holds answer, or is clobbered on fall through. 974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Only public for the test code in test-code-stubs-arm.cc. 976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void TryInlineTruncateDoubleToI(Register result, 977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DwVfpRegister input, 978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* done); 97944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 98044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Performs a truncating conversion of a floating point number as used by 98144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // the JS bitwise operations. See ECMA-262 9.5: ToInt32. 982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Exits with 'result' holding the answer. 983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void TruncateDoubleToI(Register result, DwVfpRegister double_input); 984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Performs a truncating conversion of a heap number as used by 986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the JS bitwise operations. See ECMA-262 9.5: ToInt32. 'result' and 'input' 987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // must be different registers. Exits with 'result' holding the answer. 988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void TruncateHeapNumberToI(Register result, Register object); 989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Converts the smi or heap number in object to an int32 using the rules 991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // for ToInt32 as described in ECMAScript 9.5.: the value is truncated 992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // and brought into the range -2^31 .. +2^31 - 1. 'result' and 'input' must be 993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // different registers. 994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void TruncateNumberToI(Register object, 995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result, 996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register heap_number_map, 997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1, 998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* not_int32); 999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check whether d16-d31 are available on the CPU. The result is given by the 1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Z condition flag: Z==0 if d16-d31 available, Z==1 otherwise. 1002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void CheckFor32DRegs(Register scratch); 1003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Does a runtime check for 16/32 FP registers. Either way, pushes 32 double 1005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // values to location, saving [d0..(d15|d31)]. 1006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void SaveFPRegs(Register location, Register scratch); 1007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Does a runtime check for 16/32 FP registers. Either way, pops 32 double 1009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // values to location, restoring [d0..(d15|d31)]. 1010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void RestoreFPRegs(Register location, Register scratch); 1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1012f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Perform a floating-point min or max operation with the 1013f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // (IEEE-754-compatible) semantics of ARM64's fmin/fmax. Some cases, typically 1014f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // NaNs or +/-0.0, are expected to be rare and are handled in out-of-line 1015f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // code. The specific behaviour depends on supported instructions. 1016f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // 1017f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // These functions assume (and assert) that !left.is(right). It is permitted 1018f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // for the result to alias either input register. 1019f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void FloatMax(SwVfpRegister result, SwVfpRegister left, SwVfpRegister right, 1020f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label* out_of_line); 1021f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void FloatMin(SwVfpRegister result, SwVfpRegister left, SwVfpRegister right, 1022f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label* out_of_line); 1023f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void FloatMax(DwVfpRegister result, DwVfpRegister left, DwVfpRegister right, 1024f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label* out_of_line); 1025f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void FloatMin(DwVfpRegister result, DwVfpRegister left, DwVfpRegister right, 1026f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label* out_of_line); 1027f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1028f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Generate out-of-line cases for the macros above. 1029f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void FloatMaxOutOfLine(SwVfpRegister result, SwVfpRegister left, 1030f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch SwVfpRegister right); 1031f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void FloatMinOutOfLine(SwVfpRegister result, SwVfpRegister left, 1032f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch SwVfpRegister right); 1033f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void FloatMaxOutOfLine(DwVfpRegister result, DwVfpRegister left, 1034f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch DwVfpRegister right); 1035f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void FloatMinOutOfLine(DwVfpRegister result, DwVfpRegister left, 1036f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch DwVfpRegister right); 1037f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Runtime calls 1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call a code stub. 1042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void CallStub(CodeStub* stub, 1043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TypeFeedbackId ast_id = TypeFeedbackId::None(), 1044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond = al); 1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Call a code stub. 10473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void TailCallStub(CodeStub* stub, Condition cond = al); 10483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call a runtime routine. 1050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void CallRuntime(const Runtime::Function* f, 1051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int num_arguments, 1052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SaveFPRegsMode save_doubles = kDontSaveFPRegs); 1053014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void CallRuntimeSaveDoubles(Runtime::FunctionId fid) { 1054014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const Runtime::Function* function = Runtime::FunctionForId(fid); 1055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallRuntime(function, function->nargs, kSaveFPRegs); 1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Convenience function: Same as above, but takes the fid instead. 1059014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void CallRuntime(Runtime::FunctionId fid, 1060014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SaveFPRegsMode save_doubles = kDontSaveFPRegs) { 1061014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const Runtime::Function* function = Runtime::FunctionForId(fid); 1062014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CallRuntime(function, function->nargs, save_doubles); 1063014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1064014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1065014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Convenience function: Same as above, but takes the fid instead. 1066014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void CallRuntime(Runtime::FunctionId fid, int num_arguments, 1067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SaveFPRegsMode save_doubles = kDontSaveFPRegs) { 1068014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CallRuntime(Runtime::FunctionForId(fid), num_arguments, save_doubles); 1069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1071402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Convenience function: call an external reference. 1072402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu void CallExternalReference(const ExternalReference& ext, 1073402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu int num_arguments); 1074402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 10756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Convenience function: tail call a runtime routine (jump). 1076014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void TailCallRuntime(Runtime::FunctionId fid); 1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1078257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int CalculateStackPassedWords(int num_reg_arguments, 1079257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int num_double_arguments); 1080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 10816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Before calling a C-function from generated code, align arguments on stack. 10826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // After aligning the frame, non-register arguments must be stored in 10836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // sp[0], sp[4], etc., not pushed. The argument count assumes all arguments 1084257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // are word sized. If double arguments are used, this function assumes that 1085257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // all double arguments are stored before core registers; otherwise the 1086257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // correct alignment of the double values is not guaranteed. 10876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Some compilers/platforms require the stack to be aligned when calling 10886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // C++ code. 10896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Needs a scratch register to do some arithmetic. This register will be 10906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // trashed. 1091257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void PrepareCallCFunction(int num_reg_arguments, 1092257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int num_double_registers, 1093257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch); 1094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void PrepareCallCFunction(int num_reg_arguments, 1095257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch); 1096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // There are two ways of passing double arguments on ARM, depending on 1098257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // whether soft or hard floating point ABI is used. These functions 1099257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // abstract parameter passing for the three different ways we call 1100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // C functions from generated code. 1101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void MovToFloatParameter(DwVfpRegister src); 1102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void MovToFloatParameters(DwVfpRegister src1, DwVfpRegister src2); 1103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void MovToFloatResult(DwVfpRegister src); 11046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Calls a C function and cleans up the space for arguments allocated 11066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // by PrepareCallCFunction. The called function is not allowed to trigger a 11076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // garbage collection, since that might move the code and invalidate the 11086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // return address (unless this is somehow accounted for by the called 11096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // function). 11106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void CallCFunction(ExternalReference function, int num_arguments); 11113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CallCFunction(Register function, int num_arguments); 1112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void CallCFunction(ExternalReference function, 1113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int num_reg_arguments, 1114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int num_double_arguments); 11153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CallCFunction(Register function, 1116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int num_reg_arguments, 1117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int num_double_arguments); 11186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void MovFromFloatParameter(DwVfpRegister dst); 1120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void MovFromFloatResult(DwVfpRegister dst); 1121e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to a runtime routine. 1123f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch void JumpToExternalReference(const ExternalReference& builtin, 1124f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch bool builtin_exit_frame = false); 1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 11268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Handle<Object> CodeObject() { 1127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!code_object_.is_null()); 11288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return code_object_; 11298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emit code for a truncating division by a constant. The dividend register is 1133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // unchanged and ip gets clobbered. Dividend and result must be different. 1134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void TruncatingDiv(Register result, Register dividend, int32_t divisor); 1135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // StatsCounter support 1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SetCounter(StatsCounter* counter, int value, 1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, Register scratch2); 1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void IncrementCounter(StatsCounter* counter, int value, 1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, Register scratch2); 1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void DecrementCounter(StatsCounter* counter, int value, 1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, Register scratch2); 1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Debugging 1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 11501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Calls Abort(msg) if the condition cond is not satisfied. 1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Use --debug_code to enable. 1152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Assert(Condition cond, BailoutReason reason); 1153756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick void AssertFastElements(Register elements); 1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Like Assert(), but always enabled. 1156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Check(Condition cond, BailoutReason reason); 1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Print a message to stdout and abort execution. 1159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Abort(BailoutReason msg); 1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Verify restrictions about code generated in stubs. 1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void set_generating_stub(bool value) { generating_stub_ = value; } 1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool generating_stub() { return generating_stub_; } 11643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void set_has_frame(bool value) { has_frame_ = value; } 11653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool has_frame() { return has_frame_; } 11663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch inline bool AllowThisStubCall(CodeStub* stub); 1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1168257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // EABI variant for double arguments in use. 1169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool use_eabi_hardfloat() { 1170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef __arm__ 1171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return base::OS::ArmUsingHardFloat(); 1172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#elif USE_EABI_HARDFLOAT 1173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return true; 1174257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#else 1175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return false; 1176257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif 1177257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1178257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1179d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // --------------------------------------------------------------------------- 11801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Number utilities 11811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 11821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check whether the value of reg is a power of two and not zero. If not 11831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // control continues at the label not_power_of_two. If reg is a power of two 11841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // the register scratch contains the value of (reg - 1) when control falls 11851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // through. 11861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void JumpIfNotPowerOfTwoOrZero(Register reg, 11871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register scratch, 11881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label* not_power_of_two_or_zero); 118944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check whether the value of reg is a power of two and not zero. 119044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Control falls through if it is, with scratch containing the mask 119144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // value (reg - 1). 119244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Otherwise control jumps to the 'zero_and_neg' label if the value of reg is 119344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // zero or negative, or jumps to the 'not_power_of_two' label if the value is 119444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // strictly positive but not a power of two. 119544f0eee88ff00398ff7f715fab053374d808c90dSteve Block void JumpIfNotPowerOfTwoOrZeroAndNeg(Register reg, 119644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch, 119744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* zero_and_neg, 119844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* not_power_of_two); 11991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 12001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // --------------------------------------------------------------------------- 12013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Smi utilities 12023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void SmiTag(Register reg, SBit s = LeaveCC) { 1204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch add(reg, reg, Operand(reg), s); 1205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 12061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void SmiTag(Register dst, Register src, SBit s = LeaveCC) { 12071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block add(dst, src, Operand(src), s); 12081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 1209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1210b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Try to convert int32 to smi. If the value is to large, preserve 1211b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // the original value and jump to not_a_smi. Destroys scratch and 1212b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // sets flags. 1213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void TrySmiTag(Register reg, Label* not_a_smi) { 1214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TrySmiTag(reg, reg, not_a_smi); 1215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void TrySmiTag(Register reg, Register src, Label* not_a_smi) { 1217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SmiTag(ip, src, SetCC); 1218b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch b(vs, not_a_smi); 1219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(reg, ip); 1220b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 1221b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1223e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void SmiUntag(Register reg, SBit s = LeaveCC) { 1224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(reg, Operand::SmiUntag(reg), s); 1225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1226e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void SmiUntag(Register dst, Register src, SBit s = LeaveCC) { 1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(dst, Operand::SmiUntag(src), s); 12281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 1229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 12303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Untag the source value into destination and jump if source is a smi. 12313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Souce and destination can be the same register. 12323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void UntagAndJumpIfSmi(Register dst, Register src, Label* smi_case); 12333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Test if the register contains a smi (Z == 0 (eq) if true). 1235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline void SmiTst(Register value) { 1236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch tst(value, Operand(kSmiTagMask)); 1237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline void NonNegativeSmiTst(Register value) { 1239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch tst(value, Operand(kSmiTagMask | kSmiSignMask)); 1240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Jump if the register contains a smi. 12421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block inline void JumpIfSmi(Register value, Label* smi_label) { 12431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block tst(value, Operand(kSmiTagMask)); 12441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block b(eq, smi_label); 12451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 12461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Jump if either of the registers contain a non-smi. 12471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block inline void JumpIfNotSmi(Register value, Label* not_smi_label) { 12481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block tst(value, Operand(kSmiTagMask)); 12491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block b(ne, not_smi_label); 12501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 12513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Jump if either of the registers contain a non-smi. 12523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void JumpIfNotBothSmi(Register reg1, Register reg2, Label* on_not_both_smi); 12533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Jump if either of the registers contain a smi. 12543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi); 12553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Abort execution if argument is a number, enabled via --debug-code. 12573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch void AssertNotNumber(Register object); 12583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 1259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Abort execution if argument is a smi, enabled via --debug-code. 1260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void AssertNotSmi(Register object); 1261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void AssertSmi(Register object); 1262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Abort execution if argument is not a string, enabled via --debug-code. 1264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void AssertString(Register object); 12651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Abort execution if argument is not a name, enabled via --debug-code. 1267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void AssertName(Register object); 1268e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Abort execution if argument is not a JSFunction, enabled via --debug-code. 1270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void AssertFunction(Register object); 1271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Abort execution if argument is not a JSBoundFunction, 1273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // enabled via --debug-code. 1274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void AssertBoundFunction(Register object); 1275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1276bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Abort execution if argument is not a JSGeneratorObject, 1277bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // enabled via --debug-code. 1278bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch void AssertGeneratorObject(Register object); 1279bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1280109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Abort execution if argument is not a JSReceiver, enabled via --debug-code. 1281109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch void AssertReceiver(Register object); 1282109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Abort execution if argument is not undefined or an AllocationSite, enabled 1284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // via --debug-code. 1285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void AssertUndefinedOrAllocationSite(Register object, Register scratch); 1286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Abort execution if reg is not the root value with the given index, 1288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // enabled via --debug-code. 1289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void AssertIsRoot(Register reg, Heap::RootListIndex index); 12901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 12911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // --------------------------------------------------------------------------- 12921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // HeapNumber utilities 12931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 12941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void JumpIfNotHeapNumber(Register object, 12951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register heap_number_map, 12961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register scratch, 12971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label* on_not_heap_number); 1298756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 12993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // --------------------------------------------------------------------------- 1300d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // String utilities 1301d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Checks if both objects are sequential one-byte strings and jumps to label 1303d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // if either is not. Assumes that neither object is a smi. 1304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void JumpIfNonSmisNotBothSequentialOneByteStrings(Register object1, 1305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object2, 1306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1, 1307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2, 1308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* failure); 1309d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Checks if both objects are sequential one-byte strings and jumps to label 1311d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // if either is not. 1312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void JumpIfNotBothSequentialOneByteStrings(Register first, Register second, 1313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1, 1314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2, 1315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* not_flat_one_byte_strings); 1316d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Checks if both instance types are sequential one-byte strings and jumps to 13186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // label if either is not. 1319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void JumpIfBothInstanceTypesAreNotSequentialOneByte( 1320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register first_object_instance_type, Register second_object_instance_type, 1321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1, Register scratch2, Label* failure); 1322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void JumpIfNotUniqueNameInstanceType(Register reg, Label* not_unique_name); 13246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EmitSeqStringSetCharCheck(Register string, 1326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register index, 1327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value, 1328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t encoding_mask); 13296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1331257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void ClampUint8(Register output_reg, Register input_reg); 1332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void ClampDoubleToUint8(Register result_reg, 1334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DwVfpRegister input_reg, 1335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LowDwVfpRegister double_scratch); 1336257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1337257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1338257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void LoadInstanceDescriptors(Register map, Register descriptors); 1339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EnumLength(Register dst, Register map); 1340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void NumberOfOwnDescriptors(Register dst, Register map); 1341014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void LoadAccessor(Register dst, Register holder, int accessor_index, 1342014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch AccessorComponent accessor); 1343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template<typename Field> 1345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DecodeField(Register dst, Register src) { 1346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Ubfx(dst, src, Field::kShift, Field::kSize); 1347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template<typename Field> 1350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DecodeField(Register reg) { 1351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DecodeField<Field>(reg, reg); 1352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template<typename Field> 1355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DecodeFieldToSmi(Register dst, Register src) { 1356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int shift = Field::kShift; 1357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int mask = Field::kMask >> shift << kSmiTagSize; 1358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT((mask & (0x80000000u >> (kSmiTagSize - 1))) == 0); 1359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 1360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (shift < kSmiTagSize) { 1361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(dst, Operand(src, LSL, kSmiTagSize - shift)); 1362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch and_(dst, dst, Operand(mask)); 1363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (shift > kSmiTagSize) { 1364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(dst, Operand(src, LSR, shift - kSmiTagSize)); 1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch and_(dst, dst, Operand(mask)); 1366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch and_(dst, src, Operand(mask)); 1368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template<typename Field> 1372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DecodeFieldToSmi(Register reg) { 1373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DecodeField<Field>(reg, reg); 1374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1375257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1376014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Load the type feedback vector from a JavaScript frame. 137762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch void EmitLoadFeedbackVector(Register vector); 1378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 13793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Activation support. 1380958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier void EnterFrame(StackFrame::Type type, 1381958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool load_constant_pool_pointer_reg = false); 1382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Returns the pc offset at which the frame ends. 1383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int LeaveFrame(StackFrame::Type type); 13843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1385f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch void EnterBuiltinFrame(Register context, Register target, Register argc); 1386f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch void LeaveBuiltinFrame(Register context, Register target, Register argc); 1387f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 13883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Expects object in r0 and returns map with validated enum cache 13893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // in r0. Assumes that any other register can be used as a scratch. 1390109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch void CheckEnumCache(Label* call_runtime); 13913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // AllocationMemento support. Arrays may have an associated 1393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // AllocationMemento object that can be checked for in order to pretransition 1394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to another type. 1395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // On entry, receiver_reg should point to the array object. 1396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // scratch_reg gets clobbered. 1397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If allocation info is present, condition flags are set to eq. 1398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void TestJSArrayForAllocationMemento(Register receiver_reg, 1399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch_reg, 1400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* no_memento_found); 1401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1402014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Loads the constant pool pointer (pp) register. 1403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void LoadConstantPoolPointerRegisterFromCodeTargetAddress( 1404014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register code_target_address); 1405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void LoadConstantPoolPointerRegister(); 1406014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 140844f0eee88ff00398ff7f715fab053374d808c90dSteve Block void CallCFunctionHelper(Register function, 1409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int num_reg_arguments, 1410257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int num_double_arguments); 141144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 14123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = al); 1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Helper functions for generating invokes. 1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void InvokePrologue(const ParameterCount& expected, 1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 1417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* done, 14183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool* definitely_mismatches, 1419b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch InvokeFlag flag, 1420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CallWrapper& call_wrapper); 1421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 14223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Helper for implementing JumpIfNotInNewSpace and JumpIfInNewSpace. 14233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void InNewSpace(Register object, 14243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 14253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition cond, // eq for new space, ne otherwise. 14263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* branch); 14273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 14283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Helper for finding the mark bits for an address. Afterwards, the 14293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // bitmap register points at the word with the mark bits and the mask 14303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the position of the first bit. Leaves addr_reg unchanged. 14313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch inline void GetMarkBits(Register addr_reg, 14323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register bitmap_reg, 14333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register mask_reg); 14343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1435e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Compute memory operands for safepoint stack slots. 1436e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch static int SafepointRegisterStackIndex(int reg_code); 1437e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch MemOperand SafepointRegisterSlot(Register reg); 1438e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch MemOperand SafepointRegistersAndDoublesSlot(Register reg); 1439e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1440f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Implementation helpers for FloatMin and FloatMax. 1441f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch template <typename T> 1442f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void FloatMaxHelper(T result, T left, T right, Label* out_of_line); 1443f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch template <typename T> 1444f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void FloatMinHelper(T result, T left, T right, Label* out_of_line); 1445f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch template <typename T> 1446f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void FloatMaxOutOfLineHelper(T result, T left, T right); 1447f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch template <typename T> 1448f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void FloatMinOutOfLineHelper(T result, T left, T right); 1449f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 14503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu bool generating_stub_; 14513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool has_frame_; 14523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // This handle will be patched with the code object on installation. 14533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Handle<Object> code_object_; 1454e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Needs access to SafepointRegisterStackIndex for compiled frame 1456e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // traversal. 1457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch friend class StandardFrame; 1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The code patcher is used to patch (typically) small parts of code e.g. for 1462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// debugging and other types of instrumentation. When using the code patcher 1463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the exact number of bytes specified must be emitted. It is not legal to emit 1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// relocation information. If any of these constraints are violated it causes 1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// an assertion to fail. 1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass CodePatcher { 1467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 1468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch enum FlushICache { 1469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FLUSH, 1470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DONT_FLUSH 1471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 1472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1473014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CodePatcher(Isolate* isolate, byte* address, int instructions, 1474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FlushICache flush_cache = FLUSH); 1475014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ~CodePatcher(); 1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Macro assembler to emit code. 1478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MacroAssembler* masm() { return &masm_; } 1479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Emit an instruction directly. 14811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void Emit(Instr instr); 1482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Emit an address directly. 1484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Emit(Address addr); 1485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 14861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Emit the condition part of an instruction leaving the rest of the current 14871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // instruction unchanged. 14881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void EmitCondition(Condition cond); 14891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 1491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* address_; // The address of the code being patched. 1492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int size_; // Number of bytes of the expected patch size. 1493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MacroAssembler masm_; // Macro assembler used to generate the code. 1494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FlushICache flush_cache_; // Whether to flush the I cache after patching. 1495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 1496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------- 1499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Static helper functions. 1500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1501014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochinline MemOperand ContextMemOperand(Register context, int index = 0) { 15028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang return MemOperand(context, Context::SlotOffset(index)); 15038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang} 15048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 15058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 1506014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochinline MemOperand NativeContextMemOperand() { 1507014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return ContextMemOperand(cp, Context::NATIVE_CONTEXT_INDEX); 15088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang} 15098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 1510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define ACCESS_MASM(masm) masm-> 1511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1512014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 1513014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 1514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // V8_ARM_MACRO_ASSEMBLER_ARM_H_ 1516