13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef V8_X64_MACRO_ASSEMBLER_X64_H_ 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define V8_X64_MACRO_ASSEMBLER_X64_H_ 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "assembler.h" 323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "frames.h" 33257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#include "v8globals.h" 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen// Flags used for the AllocateInNewSpace functions. 3925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsenenum AllocationFlags { 4025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // No special flags. 4125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen NO_ALLOCATION_FLAGS = 0, 4225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // Return the pointer to the allocated already tagged as a heap object. 4325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen TAG_OBJECT = 1 << 0, 4425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // The content of the result register already contains the allocation top in 4525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // new space. 4625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen RESULT_CONTAINS_TOP = 1 << 1 4725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen}; 4825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen 49257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Default scratch register used by MacroAssembler (and other code that needs 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// a spare register). The register isn't callee save, and not used by the 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// function calling convention. 533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register kScratchRegister = { 10 }; // r10. 543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register kSmiConstantRegister = { 12 }; // r12 (callee save). 553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register kRootRegister = { 13 }; // r13 (callee save). 568defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Value of smi in kSmiConstantRegister. 573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kSmiConstantRegisterValue = 1; 58e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Actual value of root register is offset from the root array's start 59e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// to take advantage of negitive 8-bit displacement values. 603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRootRegisterBias = 128; 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 62e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Convenience for platform-independent signatures. 63e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarketypedef Operand MemOperand; 64e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochenum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET }; 663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochenum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK }; 673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool AreAliased(Register r1, Register r2, Register r3, Register r4); 693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Forward declaration. 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass JumpTarget; 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct SmiIndex { 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SmiIndex(Register index_register, ScaleFactor scale) 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : reg(index_register), 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block scale(scale) {} 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register reg; 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ScaleFactor scale; 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// MacroAssembler implements a collection of frequently used macros. 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass MacroAssembler: public Assembler { 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // The isolate parameter can be NULL if the macro assembler should 868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // not use isolate-dependent functionality. In this case, it's the 878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // responsibility of the caller to never invoke such function on the 888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // macro assembler. 898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch MacroAssembler(Isolate* isolate, void* buffer, int size); 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Prevent the use of the RootArray during the lifetime of this 9244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // scope object. 9344f0eee88ff00398ff7f715fab053374d808c90dSteve Block class NoRootArrayScope BASE_EMBEDDED { 9444f0eee88ff00398ff7f715fab053374d808c90dSteve Block public: 9544f0eee88ff00398ff7f715fab053374d808c90dSteve Block explicit NoRootArrayScope(MacroAssembler* assembler) 9644f0eee88ff00398ff7f715fab053374d808c90dSteve Block : variable_(&assembler->root_array_available_), 9744f0eee88ff00398ff7f715fab053374d808c90dSteve Block old_value_(assembler->root_array_available_) { 9844f0eee88ff00398ff7f715fab053374d808c90dSteve Block assembler->root_array_available_ = false; 9944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 10044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ~NoRootArrayScope() { 10144f0eee88ff00398ff7f715fab053374d808c90dSteve Block *variable_ = old_value_; 10244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 10344f0eee88ff00398ff7f715fab053374d808c90dSteve Block private: 10444f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool* variable_; 10544f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool old_value_; 10644f0eee88ff00398ff7f715fab053374d808c90dSteve Block }; 10744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 10844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Operand pointing to an external reference. 10944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // May emit code to set up the scratch register. The operand is 11044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // only guaranteed to be correct as long as the scratch register 11144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // isn't changed. 11244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // If the operand is used more than once, use a scratch register 11344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // that is guaranteed not to be clobbered. 11444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Operand ExternalOperand(ExternalReference reference, 11544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch = kScratchRegister); 11644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Loads and stores the value of an external reference. 11744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Special case code for load and store to take advantage of 11844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // load_rax/store_rax if possible/necessary. 11944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // For other operations, just use: 12044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Operand operand = ExternalOperand(extref); 12144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // operation(operand, ..); 12244f0eee88ff00398ff7f715fab053374d808c90dSteve Block void Load(Register destination, ExternalReference source); 12344f0eee88ff00398ff7f715fab053374d808c90dSteve Block void Store(ExternalReference destination, Register source); 12444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Loads the address of the external reference into the destination 12544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // register. 12644f0eee88ff00398ff7f715fab053374d808c90dSteve Block void LoadAddress(Register destination, ExternalReference source); 12744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Returns the size of the code generated by LoadAddress. 12844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Used by CallSize(ExternalReference) to find the size of a call. 12944f0eee88ff00398ff7f715fab053374d808c90dSteve Block int LoadAddressSize(ExternalReference source); 13044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 13144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Operations on roots in the root-array. 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void LoadRoot(Register destination, Heap::RootListIndex index); 13344f0eee88ff00398ff7f715fab053374d808c90dSteve Block void StoreRoot(Register source, Heap::RootListIndex index); 134e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Load a root value where the index (or part of it) is variable. 135e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // The variable_offset register is added to the fixed_offset value 136e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // to get the index into the root-array. 137e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void LoadRootIndexed(Register destination, 138e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register variable_offset, 139e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int fixed_offset); 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void CompareRoot(Register with, Heap::RootListIndex index); 1411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void CompareRoot(const Operand& with, Heap::RootListIndex index); 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void PushRoot(Heap::RootListIndex index); 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // These functions do not arrange the registers in any particular order so 1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // they are not useful for calls that can cause a GC. The caller can 1463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // exclude up to 3 registers that do not need to be saved and restored. 1473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void PushCallerSaved(SaveFPRegsMode fp_mode, 1483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register exclusion1 = no_reg, 1493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register exclusion2 = no_reg, 1503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register exclusion3 = no_reg); 1513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void PopCallerSaved(SaveFPRegsMode fp_mode, 1523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register exclusion1 = no_reg, 1533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register exclusion2 = no_reg, 1543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register exclusion3 = no_reg); 1553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// --------------------------------------------------------------------------- 1573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// GC Support 1583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch enum RememberedSetFinalAction { 1613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kReturnAtEnd, 1623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kFallThroughAtEnd 1633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch }; 164592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 1653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Record in the remembered set the fact that we have a pointer to new space 1663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // at the address pointed to by the addr register. Only works if addr is not 1673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // in new space. 1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void RememberedSetHelper(Register object, // Used for debug code. 1693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register addr, 1703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 1713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SaveFPRegsMode save_fp, 1723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RememberedSetFinalAction and_then); 1733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CheckPageFlag(Register object, 1753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 1763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int mask, 1773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition cc, 1783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* condition_met, 1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance condition_met_distance = Label::kFar); 1803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if object is in new space. Jumps if the object is not in new space. 1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The register scratch can be object itself, but scratch will be clobbered. 1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void JumpIfNotInNewSpace(Register object, 1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 1853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* branch, 1863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance distance = Label::kFar) { 1873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch InNewSpace(object, scratch, not_equal, branch, distance); 1883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if object is in new space. Jumps if the object is in new space. 1913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The register scratch can be object itself, but it will be clobbered. 1923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void JumpIfInNewSpace(Register object, 1933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 1943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* branch, 1953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance distance = Label::kFar) { 1963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch InNewSpace(object, scratch, equal, branch, distance); 1973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if an object has the black incremental marking color. Also uses rcx! 2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void JumpIfBlack(Register object, 2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch0, 2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1, 2033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* on_black, 2043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance on_black_distance = Label::kFar); 2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Detects conservatively whether an object is data-only, i.e. it does need to 2073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // be scanned by the garbage collector. 2083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void JumpIfDataObject(Register value, 2093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 2103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* not_data_object, 2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance not_data_object_distance); 2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Checks the color of an object. If the object is already grey or black 2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // then we just fall through, since it is already live. If it is white and 2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // we can determine that it doesn't need to be scanned, then we just mark it 2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // black and fall through. For the rest we jump to the label so the 2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // incremental marker can fix its assumptions. 2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void EnsureNotWhite(Register object, 2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1, 2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch2, 2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* object_is_white_and_not_data, 2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance distance); 2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Notify the garbage collector that we wrote a pointer into an object. 2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // |object| is the object being stored into, |value| is the object being 2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // stored. value and scratch registers are clobbered by the operation. 2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The offset is the offset from the start of the object, not the offset from 2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the tagged HeapObject pointer. For use with FieldOperand(reg, off). 2293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void RecordWriteField( 2303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object, 2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int offset, 2323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register value, 2333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 2343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SaveFPRegsMode save_fp, 2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, 2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiCheck smi_check = INLINE_SMI_CHECK); 2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // As above, but the offset has the tag presubtracted. For use with 2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Operand(reg, off). 2403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void RecordWriteContextSlot( 2413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register context, 2423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int offset, 2433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register value, 2443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 2453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SaveFPRegsMode save_fp, 2463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, 2473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiCheck smi_check = INLINE_SMI_CHECK) { 2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RecordWriteField(context, 2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch offset + kHeapObjectTag, 2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value, 2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 2523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch save_fp, 2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch remembered_set_action, 2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch smi_check); 2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Notify the garbage collector that we wrote a pointer into a fixed array. 2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // |array| is the array being stored into, |value| is the 2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // object being stored. |index| is the array index represented as a non-smi. 2603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // All registers are clobbered by the operation RecordWriteArray 2613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // filters out smis so it does not update the write barrier if the 2623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // value is a smi. 2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void RecordWriteArray( 2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register array, 2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register value, 2663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register index, 2673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SaveFPRegsMode save_fp, 2683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, 2693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiCheck smi_check = INLINE_SMI_CHECK); 2703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // For page containing |object| mark region covering |address| 27285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // dirty. |object| is the object being stored into, |value| is the 2733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // object being stored. The address and value registers are clobbered by the 2748defd9ff6930b4e24729971a61cf7469daf119beSteve Block // operation. RecordWrite filters out smis so it does not update 2758defd9ff6930b4e24729971a61cf7469daf119beSteve Block // the write barrier if the value is a smi. 2763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void RecordWrite( 2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object, 2783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register address, 2793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register value, 2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SaveFPRegsMode save_fp, 2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, 2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiCheck smi_check = INLINE_SMI_CHECK); 2833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Debugger Support 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 288402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu void DebugBreak(); 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 291d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Enter specific kind of exit frame; either in normal or 292d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // debug mode. Expects the number of arguments in register rax and 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sets up the number of arguments in register rdi and the pointer 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to the first argument in register rsi. 2958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // 2968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Allocates arg_stack_space * kPointerSize memory (not GCed) on the stack 2978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // accessible via StackSpaceOperand. 2981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void EnterExitFrame(int arg_stack_space = 0, bool save_doubles = false); 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Enter specific kind of exit frame. Allocates arg_stack_space * kPointerSize 3018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // memory (not GCed) on the stack accessible via StackSpaceOperand. 3028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang void EnterApiExitFrame(int arg_stack_space); 303bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Leave the current exit frame. Expects/provides the return value in 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // register rax:rdx (untouched) and the pointer to the first 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // argument in register rsi. 3071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void LeaveExitFrame(bool save_doubles = false); 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Leave the current exit frame. Expects/provides the return value in 3108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // register rax (untouched). 3118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang void LeaveApiExitFrame(); 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Push and pop the registers that can hold pointers. 3141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void PushSafepointRegisters() { Pushad(); } 3151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void PopSafepointRegisters() { Popad(); } 316e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Store the value in register src in the safepoint register stack 317e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // slot for register dst. 318e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void StoreToSafepointRegisterSlot(Register dst, Register src); 319e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void LoadFromSafepointRegisterSlot(Register dst, Register src); 320e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 321e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void InitializeRootRegister() { 3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference roots_array_start = 3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference::roots_array_start(isolate()); 3243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(kRootRegister, roots_array_start); 325e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch addq(kRootRegister, Immediate(kRootRegisterBias)); 326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // JavaScript invokes 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up call kind marking in rcx. The method takes rcx as an 332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // explicit first parameter to make the code more readable at the 333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // call sites. 334257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void SetCallKind(Register dst, CallKind kind); 335257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the JavaScript function code by either calling or jumping. 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void InvokeCode(Register code, 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& expected, 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 340e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch InvokeFlag flag, 341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const CallWrapper& call_wrapper, 342257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKind call_kind); 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void InvokeCode(Handle<Code> code, 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& expected, 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::Mode rmode, 348e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch InvokeFlag flag, 349257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const CallWrapper& call_wrapper, 350257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKind call_kind); 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the JavaScript function in the given register. Changes the 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // current context to the context in the function before invoking. 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void InvokeFunction(Register function, 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 356e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch InvokeFlag flag, 357257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const CallWrapper& call_wrapper, 358257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKind call_kind); 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void InvokeFunction(Handle<JSFunction> function, 361402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu const ParameterCount& actual, 362e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch InvokeFlag flag, 363257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const CallWrapper& call_wrapper, 364257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKind call_kind); 365402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke specified builtin JavaScript function. Adds an entry to 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the unresolved list if the name does not resolve. 368e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void InvokeBuiltin(Builtins::JavaScript id, 369e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch InvokeFlag flag, 370257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const CallWrapper& call_wrapper = NullCallWrapper()); 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 372791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block // Store the function for the given builtin in the target register. 373791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block void GetBuiltinFunction(Register target, Builtins::JavaScript id); 374791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Store the code object for the given builtin in the target register. 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void GetBuiltinEntry(Register target, Builtins::JavaScript id); 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Smi tagging, untagging and operations on tagged smis. 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3828defd9ff6930b4e24729971a61cf7469daf119beSteve Block void InitializeSmiConstantRegister() { 3838defd9ff6930b4e24729971a61cf7469daf119beSteve Block movq(kSmiConstantRegister, 3848defd9ff6930b4e24729971a61cf7469daf119beSteve Block reinterpret_cast<uint64_t>(Smi::FromInt(kSmiConstantRegisterValue)), 3858defd9ff6930b4e24729971a61cf7469daf119beSteve Block RelocInfo::NONE); 3868defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 3878defd9ff6930b4e24729971a61cf7469daf119beSteve Block 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Conversions between tagged smi values and non-tagged integer values. 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Tag an integer value. The result must be known to be a valid smi value. 3914515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Only uses the low 32 bits of the src register. Sets the N and Z flags 3920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // based on the value of the resulting smi. 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Integer32ToSmi(Register dst, Register src); 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3959dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Stores an integer32 value into a memory field that already holds a smi. 3969dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen void Integer32ToSmiField(const Operand& dst, Register src); 3979dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Adds constant to src and tags the result as a smi. 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Result must be a valid smi. 4003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void Integer64PlusConstantToSmi(Register dst, Register src, int constant); 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Convert smi to 32-bit integer. I.e., not sign extended into 403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // high 32 bits of destination. 404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SmiToInteger32(Register dst, Register src); 4057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch void SmiToInteger32(Register dst, const Operand& src); 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Convert smi to 64-bit integer (sign extended if necessary). 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SmiToInteger64(Register dst, Register src); 4099dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen void SmiToInteger64(Register dst, const Operand& src); 410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Multiply a positive smi's integer value by a power of two. 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Provides result as 64-bit integer value. 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void PositiveSmiTimesPowerOfTwoToInteger64(Register dst, 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int power); 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Divide a positive smi's integer value by a power of two. 4187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Provides result as 32-bit integer value. 4197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch void PositiveSmiDivPowerOfTwoToInteger32(Register dst, 4207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register src, 4217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch int power); 4227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 4238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Perform the logical or of two smi values and return a smi value. 4248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // If either argument is not a smi, jump to on_not_smis and retain 4258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // the original values of source registers. The destination register 4268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // may be changed if it's not one of the source registers. 4278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch void SmiOrIfSmis(Register dst, 4288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Register src1, 4298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Register src2, 430257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_smis, 431257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump = Label::kFar); 4328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 4337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 43444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Simple comparison of smis. Both sides must be known smis to use these, 43544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // otherwise use Cmp. 43644f0eee88ff00398ff7f715fab053374d808c90dSteve Block void SmiCompare(Register smi1, Register smi2); 4373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void SmiCompare(Register dst, Smi* src); 4386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void SmiCompare(Register dst, const Operand& src); 4393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void SmiCompare(const Operand& dst, Register src); 4403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void SmiCompare(const Operand& dst, Smi* src); 4419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Compare the int32 in src register to the value of the smi stored at dst. 4429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen void SmiCompareInteger32(const Operand& dst, Register src); 4433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Sets sign and zero flags depending on value of smi in register. 4443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void SmiTest(Register src); 4453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Functions performing a check on a known or potential smi. Returns 447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // a condition that is satisfied if the check is successful. 448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Is the value a tagged smi. 450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Condition CheckSmi(Register src); 4511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Condition CheckSmi(const Operand& src); 452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 453f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Is the value a non-negative tagged smi. 454f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Condition CheckNonNegativeSmi(Register src); 455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 456e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Are both values tagged smis. 457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Condition CheckBothSmi(Register first, Register second); 458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 459f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Are both values non-negative tagged smis. 460f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Condition CheckBothNonNegativeSmi(Register first, Register second); 461d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 462e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Are either value a tagged smi. 463bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Condition CheckEitherSmi(Register first, 464bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Register second, 465bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Register scratch = kScratchRegister); 466e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Is the value the minimum smi value (since we are using 468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // two's complement numbers, negating the value is known to yield 469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // a non-smi value). 470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Condition CheckIsMinSmi(Register src); 471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Checks whether an 32-bit integer value is a valid for conversion 473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to a smi. 474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Condition CheckInteger32ValidSmiValue(Register src); 475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Checks whether an 32-bit unsigned integer value is a valid for 4773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // conversion to a smi. 4783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Condition CheckUInteger32ValidSmiValue(Register src); 4793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 4801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check whether src is a Smi, and set dst to zero if it is a smi, 4811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // and to one if it isn't. 4821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void CheckSmiToIndicator(Register dst, Register src); 4831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void CheckSmiToIndicator(Register dst, const Operand& src); 4841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Test-and-jump functions. Typically combines a check function 486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // above with a conditional jump. 487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump if the value cannot be represented by a smi. 489257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void JumpIfNotValidSmiValue(Register src, Label* on_invalid, 490257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump = Label::kFar); 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Jump if the unsigned integer value cannot be represented by a smi. 493257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void JumpIfUIntNotValidSmiValue(Register src, Label* on_invalid, 494257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump = Label::kFar); 4953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to label if the value is a tagged smi. 497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void JumpIfSmi(Register src, 498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_smi, 499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump = Label::kFar); 500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to label if the value is not a tagged smi. 502257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void JumpIfNotSmi(Register src, 503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_smi, 504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump = Label::kFar); 505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 506f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Jump to label if the value is not a non-negative tagged smi. 507257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void JumpUnlessNonNegativeSmi(Register src, 508257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_smi, 509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump = Label::kFar); 510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Jump to label if the value, which must be a tagged smi, has value equal 512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to the constant. 5130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen void JumpIfSmiEqualsConstant(Register src, 5140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Smi* constant, 515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_equals, 516257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump = Label::kFar); 517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump if either or both register are not smi values. 5190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen void JumpIfNotBothSmi(Register src1, 5200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register src2, 521257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_both_smi, 522257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump = Label::kFar); 523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 524f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Jump if either or both register are not non-negative smi values. 525f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch void JumpUnlessBothNonNegativeSmi(Register src1, Register src2, 526257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_both_smi, 527257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump = Label::kFar); 528d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Operations on tagged smi values. 530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Smis represent a subset of integers. The subset is always equivalent to 532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // a two's complement interpretation of a fixed number of bits. 533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Optimistically adds an integer constant to a supposed smi. 535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the src is not a smi, or the result is not a smi, jump to 536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the label. 537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SmiTryAddConstant(Register dst, 538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 5393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Smi* constant, 540257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_smi_result, 541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump = Label::kFar); 542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Add an integer constant to a tagged smi, giving a tagged smi as result. 5443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // No overflow testing on the result is done. 5453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void SmiAddConstant(Register dst, Register src, Smi* constant); 5463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 547f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Add an integer constant to a tagged smi, giving a tagged smi as result. 548f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // No overflow testing on the result is done. 549f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke void SmiAddConstant(const Operand& dst, Smi* constant); 550f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Add an integer constant to a tagged smi, giving a tagged smi as result, 552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // or jumping to a label if the result cannot be represented by a smi. 553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SmiAddConstant(Register dst, 554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 5553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Smi* constant, 556257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_smi_result, 557257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump = Label::kFar); 558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Subtract an integer constant from a tagged smi, giving a tagged smi as 5606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // result. No testing on the result is done. Sets the N and Z flags 5616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // based on the value of the resulting integer. 5623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void SmiSubConstant(Register dst, Register src, Smi* constant); 5633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 5643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Subtract an integer constant from a tagged smi, giving a tagged smi as 565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result, or jumping to a label if the result cannot be represented by a smi. 566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SmiSubConstant(Register dst, 567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 5683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Smi* constant, 569257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_smi_result, 570257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump = Label::kFar); 571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Negating a smi can give a negative zero or too large positive value. 5733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // NOTICE: This operation jumps on success, not failure! 574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SmiNeg(Register dst, 575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 576257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_smi_result, 577257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump = Label::kFar); 578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Adds smi values and return the result as a smi. 580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If dst is src1, then src1 will be destroyed, even if 581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the operation is unsuccessful. 582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SmiAdd(Register dst, 583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2, 585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_smi_result, 586257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump = Label::kFar); 58744f0eee88ff00398ff7f715fab053374d808c90dSteve Block void SmiAdd(Register dst, 58844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register src1, 58944f0eee88ff00398ff7f715fab053374d808c90dSteve Block const Operand& src2, 590257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_smi_result, 591257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump = Label::kFar); 5920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen void SmiAdd(Register dst, 5940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register src1, 5950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register src2); 596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Subtracts smi values and return the result as a smi. 598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If dst is src1, then src1 will be destroyed, even if 599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the operation is unsuccessful. 600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SmiSub(Register dst, 601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2, 603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_smi_result, 604257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump = Label::kFar); 6050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen void SmiSub(Register dst, 6070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register src1, 6080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register src2); 609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void SmiSub(Register dst, 6116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register src1, 612f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke const Operand& src2, 613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_smi_result, 614257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump = Label::kFar); 6150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen void SmiSub(Register dst, 6170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register src1, 6180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen const Operand& src2); 6196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Multiplies smi values and return the result as a smi, 621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // if possible. 622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If dst is src1, then src1 will be destroyed, even if 623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the operation is unsuccessful. 624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SmiMul(Register dst, 625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2, 627257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_smi_result, 628257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump = Label::kFar); 629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Divides one smi by another and returns the quotient. 631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Clobbers rax and rdx registers. 632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SmiDiv(Register dst, 633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2, 635257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_smi_result, 636257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump = Label::kFar); 637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Divides one smi by another and returns the remainder. 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Clobbers rax and rdx registers. 640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SmiMod(Register dst, 641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2, 643257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_smi_result, 644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump = Label::kFar); 645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Bitwise operations. 647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SmiNot(Register dst, Register src); 648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SmiAnd(Register dst, Register src1, Register src2); 649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SmiOr(Register dst, Register src1, Register src2); 650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SmiXor(Register dst, Register src1, Register src2); 6513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void SmiAndConstant(Register dst, Register src1, Smi* constant); 6523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void SmiOrConstant(Register dst, Register src1, Smi* constant); 6533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void SmiXorConstant(Register dst, Register src1, Smi* constant); 654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SmiShiftLeftConstant(Register dst, 656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 65725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen int shift_value); 658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SmiShiftLogicalRightConstant(Register dst, 659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int shift_value, 661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_smi_result, 662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump = Label::kFar); 663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SmiShiftArithmeticRightConstant(Register dst, 664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int shift_value); 666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Shifts a smi value to the left, and returns the result if that is a smi. 668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Uses and clobbers rcx, so dst may not be rcx. 669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SmiShiftLeft(Register dst, 670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 67125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Register src2); 672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Shifts a smi value to the right, shifting in zero bits at the top, and 673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // returns the unsigned intepretation of the result if that is a smi. 674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Uses and clobbers rcx, so dst may not be rcx. 675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SmiShiftLogicalRight(Register dst, 6760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register src1, 6770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register src2, 678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_smi_result, 679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump = Label::kFar); 680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Shifts a smi value to the right, sign extending the top, and 681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // returns the signed intepretation of the result. That will always 682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // be a valid smi value, since it's numerically smaller than the 683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // original. 684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Uses and clobbers rcx, so dst may not be rcx. 685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SmiShiftArithmeticRight(Register dst, 686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2); 688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Specialized operations 690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Select the non-smi register of two registers where exactly one is a 692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // smi. If neither are smis, jump to the failure label. 693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SelectNonSmi(Register dst, 694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2, 696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_smis, 697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump = Label::kFar); 698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Converts, if necessary, a smi to a combination of number and 700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // multiplier to be used as a scaled index. 701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The src register contains a *positive* smi value. The shift is the 702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // power of two to multiply the index value by (e.g. 703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to index by smi-value * kPointerSize, pass the smi and kPointerSizeLog2). 704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The returned index register may be either src or dst, depending 705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // on what is most efficient. If src and dst are different registers, 706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // src is always unchanged. 707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SmiIndex SmiToIndex(Register dst, Register src, int shift); 708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Converts a positive smi to a negative index. 710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SmiIndex SmiToNegativeIndex(Register dst, Register src, int shift); 711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 71244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Add the value of a smi in memory to an int32 register. 71344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Sets flags as a normal add. 71444f0eee88ff00398ff7f715fab053374d808c90dSteve Block void AddSmiField(Register dst, const Operand& src); 71544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 7163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Basic Smi operations. 7173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void Move(Register dst, Smi* source) { 7188defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(dst, source); 7193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 7203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void Move(const Operand& dst, Smi* source) { 7228defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register constant = GetSmiConstant(source); 7238defd9ff6930b4e24729971a61cf7469daf119beSteve Block movq(dst, constant); 7243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 7253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void Push(Smi* smi); 7273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void Test(const Operand& dst, Smi* source); 7283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 731e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // String macros. 7321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 7331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // If object is a string, its map is loaded into object_map. 7341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void JumpIfNotString(Register object, 7351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register object_map, 736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* not_string, 737257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump = Label::kFar); 7381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 7391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 740257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void JumpIfNotBothSequentialAsciiStrings( 741257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register first_object, 742257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register second_object, 743257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch1, 744257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch2, 745257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_both_flat_ascii, 746257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump = Label::kFar); 747e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 7483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check whether the instance type represents a flat ASCII string. Jump to the 7496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // label if not. If the instance type can be scratched specify same register 7506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // for both instance type and scratch. 7510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen void JumpIfInstanceTypeIsNotSequentialAscii( 7520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register instance_type, 7530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register scratch, 754257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label*on_not_flat_ascii_string, 755257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump = Label::kFar); 7566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 7576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void JumpIfBothInstanceTypesAreNotSequentialAscii( 7586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register first_object_instance_type, 7596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register second_object_instance_type, 7606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch1, 7616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch2, 762257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_fail, 763257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump = Label::kFar); 7646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 765e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // --------------------------------------------------------------------------- 766e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Macro instructions. 767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Load a register with a long value as efficiently as possible. 769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Set(Register dst, int64_t x); 770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Set(const Operand& dst, int64_t x); 771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Move if the registers are not identical. 7730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen void Move(Register target, Register source); 7740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 7753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Bit-field support. 7763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void TestBit(const Operand& dst, int bit_index); 7773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle support 779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Move(Register dst, Handle<Object> source); 780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Move(const Operand& dst, Handle<Object> source); 781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Cmp(Register dst, Handle<Object> source); 782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Cmp(const Operand& dst, Handle<Object> source); 78344f0eee88ff00398ff7f715fab053374d808c90dSteve Block void Cmp(Register dst, Smi* src); 78444f0eee88ff00398ff7f715fab053374d808c90dSteve Block void Cmp(const Operand& dst, Smi* src); 785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Push(Handle<Object> source); 786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load a heap object and handle the case of new-space objects by 7883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // indirecting via a global cell. 7893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void LoadHeapObject(Register result, Handle<HeapObject> object); 7903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void PushHeapObject(Handle<HeapObject> object); 7913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void LoadObject(Register result, Handle<Object> object) { 7933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (object->IsHeapObject()) { 7943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LoadHeapObject(result, Handle<HeapObject>::cast(object)); 7953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 7963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Move(result, object); 7973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 7983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 7993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load a global cell into a register. 8013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void LoadGlobalCell(Register dst, Handle<JSGlobalPropertyCell> cell); 8023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 803e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Emit code to discard a non-negative number of pointer-sized elements 804e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // from the stack, clobbering only the rsp register. 805e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void Drop(int stack_elements); 806e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 807e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void Call(Label* target) { call(target); } 808e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Control Flow 810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Jump(Address destination, RelocInfo::Mode rmode); 811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Jump(ExternalReference ext); 812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Jump(Handle<Code> code_object, RelocInfo::Mode rmode); 813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Call(Address destination, RelocInfo::Mode rmode); 815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Call(ExternalReference ext); 816257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void Call(Handle<Code> code_object, 817257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch RelocInfo::Mode rmode, 818257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch unsigned ast_id = kNoASTId); 819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 82044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // The size of the code generated for different call instructions. 82144f0eee88ff00398ff7f715fab053374d808c90dSteve Block int CallSize(Address destination, RelocInfo::Mode rmode) { 82244f0eee88ff00398ff7f715fab053374d808c90dSteve Block return kCallInstructionLength; 82344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 82444f0eee88ff00398ff7f715fab053374d808c90dSteve Block int CallSize(ExternalReference ext); 82544f0eee88ff00398ff7f715fab053374d808c90dSteve Block int CallSize(Handle<Code> code_object) { 82644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Code calls use 32-bit relative addressing. 82744f0eee88ff00398ff7f715fab053374d808c90dSteve Block return kShortCallInstructionLength; 82844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 82944f0eee88ff00398ff7f715fab053374d808c90dSteve Block int CallSize(Register target) { 83044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Opcode: REX_opt FF /2 m64 83144f0eee88ff00398ff7f715fab053374d808c90dSteve Block return (target.high_bit() != 0) ? 3 : 2; 83244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 83344f0eee88ff00398ff7f715fab053374d808c90dSteve Block int CallSize(const Operand& target) { 83444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Opcode: REX_opt FF /2 m64 83544f0eee88ff00398ff7f715fab053374d808c90dSteve Block return (target.requires_rex() ? 2 : 1) + target.operand_size(); 83644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 83744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 8381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Emit call to the code we are currently generating. 8391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void CallSelf() { 8401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Handle<Code> self(reinterpret_cast<Code**>(CodeObject().location())); 8411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Call(self, RelocInfo::CODE_TARGET); 8421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 8431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 8441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Non-x64 instructions. 8451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Push/pop all general purpose registers. 8461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Does not push rsp/rbp nor any of the assembler's special purpose registers 8471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // (kScratchRegister, kSmiConstantRegister, kRootRegister). 8481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void Pushad(); 8491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void Popad(); 8501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Sets the stack as after performing Popad, without actually loading the 8511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // registers. 8521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void Dropad(); 8531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compare object type for heap object. 855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Always use unsigned comparisons: above and below, not less and greater. 856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Incoming register is heap_object and outgoing register is map. 857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // They may be the same register, and may be kScratchRegister. 858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void CmpObjectType(Register heap_object, InstanceType type, Register map); 859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compare instance type for map. 861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Always use unsigned comparisons: above and below, not less and greater. 862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void CmpInstanceType(Register map, InstanceType type); 863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check if a map for a JSObject indicates that the object has fast elements. 8653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Jump to the specified label if it does not. 8663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void CheckFastElements(Register map, 8673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label* fail, 8683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label::Distance distance = Label::kFar); 8693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 8703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if a map for a JSObject indicates that the object can have both smi 8713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // and HeapObject elements. Jump to the specified label if it does not. 8723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CheckFastObjectElements(Register map, 8733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* fail, 8743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance distance = Label::kFar); 8753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if a map for a JSObject indicates that the object has fast smi only 8773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // elements. Jump to the specified label if it does not. 8783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CheckFastSmiOnlyElements(Register map, 8793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* fail, 8803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance distance = Label::kFar); 8813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check to see if maybe_number can be stored as a double in 8833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // FastDoubleElements. If it can, store it at the index specified by index in 8843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the FastDoubleElements array elements, otherwise jump to fail. Note that 8853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // index must not be smi-tagged. 8863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void StoreNumberToDoubleElements(Register maybe_number, 8873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register elements, 8883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register index, 8893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch XMMRegister xmm_scratch, 8903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* fail); 8913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Compare an object's map with the specified map and its transitioned 8933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // elements maps if mode is ALLOW_ELEMENT_TRANSITION_MAPS. FLAGS are set with 8943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // result of map compare. If multiple map compares are required, the compare 8953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sequences branches to early_success. 8963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CompareMap(Register obj, 8973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> map, 8983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* early_success, 8993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompareMapMode mode = REQUIRE_EXACT_MAP); 9003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if the map of an object is equal to a specified map and branch to 9023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // label if not. Skip the smi check if not required (object is known to be a 9033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match 9043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // against maps that are ElementsKind transition maps of the specified map. 9053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void CheckMap(Register obj, 9063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Handle<Map> map, 9073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Label* fail, 9083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiCheckType smi_check_type, 9093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompareMapMode mode = REQUIRE_EXACT_MAP); 910257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 911257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if the map of an object is equal to a specified map and branch to a 912257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // specified target if equal. Skip the smi check if not required (object is 913257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // known to be a heap object) 914257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void DispatchMap(Register obj, 915257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Map> map, 916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> success, 917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SmiCheckType smi_check_type); 9183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 919d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Check if the object in register heap_object is a string. Afterwards the 920d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // register map contains the object map and the register instance_type 921d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // contains the instance_type. The registers map and instance_type can be the 922d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // same in which case it contains the instance type afterwards. Either of the 923d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // registers map and instance_type can be the same as heap_object. 924d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Condition IsObjectStringType(Register heap_object, 925d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Register map, 926d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Register instance_type); 927d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 9288defd9ff6930b4e24729971a61cf7469daf119beSteve Block // FCmp compares and pops the two values on top of the FPU stack. 9298defd9ff6930b4e24729971a61cf7469daf119beSteve Block // The flag results are similar to integer cmp, but requires unsigned 930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // jcc instructions (je, ja, jae, jb, jbe, je, and jz). 931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void FCmp(); 932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 933257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void ClampUint8(Register reg); 934257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 935257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void ClampDoubleToUint8(XMMRegister input_reg, 936257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch XMMRegister temp_xmm_reg, 937257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register result_reg, 938257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register temp_reg); 939257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 940257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void LoadInstanceDescriptors(Register map, Register descriptors); 941257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 942402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Abort execution if argument is not a number. Used in debug code. 943f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke void AbortIfNotNumber(Register object); 944402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 945756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Abort execution if argument is a smi. Used in debug code. 946756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick void AbortIfSmi(Register object); 947756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 9486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Abort execution if argument is not a smi. Used in debug code. 949f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke void AbortIfNotSmi(Register object); 95044f0eee88ff00398ff7f715fab053374d808c90dSteve Block void AbortIfNotSmi(const Operand& object); 9516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 9523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Abort execution if a 64 bit register containing a 32 bit payload does not 9533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // have zeros in the top 32 bits. 9543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void AbortIfNotZeroExtended(Register reg); 9553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 956e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Abort execution if argument is a string. Used in debug code. 957e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void AbortIfNotString(Register object); 958e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 9599dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Abort execution if argument is not the root value with the given index. 9609dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen void AbortIfNotRootValue(Register src, 9619dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Heap::RootListIndex root_value_index, 9629dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const char* message); 9639dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exception handling 966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Push a new try handler and link it into try handler chain. 9683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void PushTryHandler(StackHandler::Kind kind, int handler_index); 969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 970e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Unlink the stack handler on top of the stack from the try handler chain. 971e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void PopTryHandler(); 972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 973e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Activate the top handler in the try hander chain and pass the 974e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // thrown value. 975e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void Throw(Register value); 976e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 977e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Propagate an uncatchable exception out of the current JS stack. 9783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void ThrowUncatchable(Register value); 979e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Inline caching support 982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Generate code for checking access rights - used for security checks 984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // on access to global objects across environments. The holder register 985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is left untouched, but the scratch register and kScratchRegister, 986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // which must be different, are clobbered. 987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void CheckAccessGlobalProxy(Register holder_reg, 988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss); 990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 991c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch void GetNumberHash(Register r0, Register scratch); 992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void LoadFromNumberDictionary(Label* miss, 9943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register elements, 9953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register key, 9963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register r0, 9973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register r1, 9983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register r2, 9993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register result); 10003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 10013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocation support 1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocate an object in new space. If the new space is exhausted control 1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // continues at the gc_required label. The allocated object is returned in 1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result and end of the new object is returned in result_end. The register 1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scratch can be passed as no_reg in which case an additional object 1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // reference will be added to the reloc info. The returned pointers in result 1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // and result_end have not yet been tagged as heap objects. If 1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result_contains_top_on_entry is true the content of result is known to be 1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the allocation top on entry (could be result_end from a previous call to 1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // AllocateInNewSpace). If result_contains_top_on_entry is true scratch 1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // should be no_reg as it is never used. 1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void AllocateInNewSpace(int object_size, 1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result_end, 1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required, 1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags); 1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void AllocateInNewSpace(int header_size, 1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ScaleFactor element_size, 1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register element_count, 1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result_end, 1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required, 1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags); 1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void AllocateInNewSpace(Register object_size, 1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result_end, 1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required, 1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags); 1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Undo allocation in new space. The object passed and objects allocated after 1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // it will no longer be allocated. Make sure that no pointers are left to the 1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // object(s) no longer allocated as they would be invalid when allocation is 1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // un-done. 1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void UndoAllocationInNewSpace(Register object); 1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Allocate a heap number in new space with undefined value. Returns 10453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // tagged pointer in result register, or jumps to gc_required if new 10463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // space is full. 10473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void AllocateHeapNumber(Register result, 10483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register scratch, 10493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label* gc_required); 10503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1051e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Allocate a sequential string. All the header fields of the string object 1052e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // are initialized. 1053e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void AllocateTwoByteString(Register result, 1054e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register length, 1055e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch1, 1056e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch2, 1057e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch3, 1058e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* gc_required); 1059e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void AllocateAsciiString(Register result, 1060e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register length, 1061e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch1, 1062e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch2, 1063e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch3, 1064e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* gc_required); 1065e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1066e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Allocate a raw cons string object. Only the map field of the result is 1067e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // initialized. 1068589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch void AllocateTwoByteConsString(Register result, 1069e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch1, 1070e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch2, 1071e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* gc_required); 1072e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void AllocateAsciiConsString(Register result, 1073e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch1, 1074e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch2, 1075e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* gc_required); 1076e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1077589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Allocate a raw sliced string object. Only the map field of the result is 1078589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // initialized. 1079589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch void AllocateTwoByteSlicedString(Register result, 1080589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register scratch1, 1081589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register scratch2, 1082589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label* gc_required); 1083589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch void AllocateAsciiSlicedString(Register result, 1084589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register scratch1, 1085589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register scratch2, 1086589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label* gc_required); 1087589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Support functions. 1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if result is zero and op is negative. 1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void NegativeZeroTest(Register result, Register op, Label* then_label); 1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if result is zero and op is negative in code using jump targets. 1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void NegativeZeroTest(CodeGenerator* cgen, 1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register op, 1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JumpTarget* then_target); 1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if result is zero and any of op1 and op2 are negative. 1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Register scratch is destroyed, and it must be different from op2. 1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void NegativeZeroTest(Register result, Register op1, Register op2, 1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, Label* then_label); 1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Try to get function prototype of a function and puts the value in 1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the result register. Checks that the function really is a 1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // function and jumps to the miss label if the fast checks fail. The 1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // function register will be untouched; the other register may be 1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // clobbered. 1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void TryGetFunctionPrototype(Register function, 1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 11123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss, 11133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool miss_on_bound_function = false); 1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Generates code for reporting that an illegal operation has 1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // occurred. 1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void IllegalOperation(int num_arguments); 1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 111980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Picks out an array index from the hash field. 112080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Register use: 112180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // hash - holds the index's hash. Clobbered. 112280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // index - holds the overwritten index on exit. 112380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen void IndexFromHash(Register hash, Register index); 112480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1125d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Find the function context up the context chain. 1126d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void LoadContext(Register dst, int context_chain_length); 1127d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 11283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Conditionally load the cached Array transitioned map of type 11293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // transitioned_kind from the global context if the map in register 11303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // map_in_out is the cached Array map in the global context of 11313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // expected_kind. 11323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void LoadTransitionedArrayMapConditional( 11333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind expected_kind, 11343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind transitioned_kind, 11353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register map_in_out, 11363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 11373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* no_map_match); 11383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 11393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load the initial map for new Arrays from a JSFunction. 11403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void LoadInitialArrayMap(Register function_in, 11413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 11423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register map_out); 11433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Load the global function with the given index. 1145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void LoadGlobalFunction(int index, Register function); 1146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Load the initial map from the global function. The registers 1148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // function and map can be the same. 1149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void LoadGlobalFunctionInitialMap(Register function, Register map); 1150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Runtime calls 1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call a code stub. 1155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void CallStub(CodeStub* stub, unsigned ast_id = kNoASTId); 1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1157e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Tail call a code stub (jump). 1158e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void TailCallStub(CodeStub* stub); 1159e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return from a code stub after popping its arguments. 1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void StubReturn(int argc); 1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call a runtime routine. 116444f0eee88ff00398ff7f715fab053374d808c90dSteve Block void CallRuntime(const Runtime::Function* f, int num_arguments); 1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 11661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Call a runtime function and save the value of XMM registers. 11671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void CallRuntimeSaveDoubles(Runtime::FunctionId id); 11681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Convenience function: Same as above, but takes the fid instead. 1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void CallRuntime(Runtime::FunctionId id, int num_arguments); 1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1172402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Convenience function: call an external reference. 1173402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu void CallExternalReference(const ExternalReference& ext, 1174402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu int num_arguments); 1175402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Tail call of a runtime routine (jump). 11776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Like JumpToExternalReference, but also takes care of passing the number 11786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // of parameters. 11796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void TailCallExternalReference(const ExternalReference& ext, 11806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int num_arguments, 11816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int result_size); 11826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Convenience function: tail call a runtime routine (jump). 11846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void TailCallRuntime(Runtime::FunctionId fid, 1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int num_arguments, 1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result_size); 1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to a runtime routine. 11896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void JumpToExternalReference(const ExternalReference& ext, int result_size); 1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 11913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Prepares stack to put arguments (aligns and so on). WIN64 calling 11923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // convention requires to put the pointer to the return value slot into 11933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rcx (rcx must be preserverd until CallApiFunctionAndReturn). Saves 11943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // context (rsi). Clobbers rax. Allocates arg_stack_space * kPointerSize 11958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // inside the exit frame (not GCed) accessible via StackSpaceOperand. 11968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang void PrepareCallApiFunction(int arg_stack_space); 11978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 11983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Calls an API function. Allocates HandleScope, extracts returned value 11993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // from handle and propagates exceptions. Clobbers r14, r15, rbx and 12003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // caller-save registers. Restores context. On return removes 12013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // stack_space * kPointerSize (GCed). 12023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CallApiFunctionAndReturn(Address function_address, int stack_space); 12035913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck 12044515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Before calling a C-function from generated code, align arguments on stack. 12054515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // After aligning the frame, arguments must be stored in esp[0], esp[4], 12064515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // etc., not pushed. The argument count assumes all arguments are word sized. 12074515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // The number of slots reserved for arguments depends on platform. On Windows 12084515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // stack slots are reserved for the arguments passed in registers. On other 12094515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // platforms stack slots are only reserved for the arguments actually passed 12104515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // on the stack. 12114515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke void PrepareCallCFunction(int num_arguments); 12124515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 12134515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Calls a C function and cleans up the space for arguments allocated 12144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // by PrepareCallCFunction. The called function is not allowed to trigger a 12154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // garbage collection, since that might move the code and invalidate the 12164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // return address (unless this is somehow accounted for by the called 12174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // function). 12184515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke void CallCFunction(ExternalReference function, int num_arguments); 12194515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke void CallCFunction(Register function, int num_arguments); 12204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 12214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Calculate the number of stack slots to reserve for arguments when calling a 12224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // C function. 12234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke int ArgumentStackSlotsForCFunctionCall(int num_arguments); 1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Utilities 1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Ret(); 1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Return and drop arguments from stack, where the number of arguments 12311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // may be bigger than 2^16 - 1. Requires a scratch register. 12321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void Ret(int bytes_dropped, Register scratch); 12331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 12348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Handle<Object> CodeObject() { 12358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!code_object_.is_null()); 12368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return code_object_; 12378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 123944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Copy length bytes from source to destination. 124044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Uses scratch register internally (if you have a low-eight register 124144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // free, do use it, otherwise kScratchRegister will be used). 124244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // The min_length is a minimum limit on the value that length will have. 124344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // The algorithm has some special cases that might be omitted if the string 124444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // is known to always be long. 124544f0eee88ff00398ff7f715fab053374d808c90dSteve Block void CopyBytes(Register destination, 124644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register source, 124744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register length, 124844f0eee88ff00398ff7f715fab053374d808c90dSteve Block int min_length = 0, 124944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch = kScratchRegister); 125044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 12513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Initialize fields with filler values. Fields starting at |start_offset| 12523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // not including end_offset are overwritten with the value in |filler|. At 12533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the end the loop, |start_offset| takes the value of |end_offset|. 12543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void InitializeFieldsWithFiller(Register start_offset, 12553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register end_offset, 12563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register filler); 12573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // StatsCounter support 1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SetCounter(StatsCounter* counter, int value); 1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void IncrementCounter(StatsCounter* counter, int value); 1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void DecrementCounter(StatsCounter* counter, int value); 1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 1268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Debugging 1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calls Abort(msg) if the condition cc is not satisfied. 1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Use --debug_code to enable. 1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Assert(Condition cc, const char* msg); 1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1274756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick void AssertFastElements(Register elements); 1275756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Like Assert(), but always enabled. 1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Check(Condition cc, const char* msg); 1278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Print a message to stdout and abort execution. 1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Abort(const char* msg); 1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the stack is aligned. 12836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void CheckStackAlignment(); 12846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Verify restrictions about code generated in stubs. 1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void set_generating_stub(bool value) { generating_stub_ = value; } 1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool generating_stub() { return generating_stub_; } 1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; } 1289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool allow_stub_calls() { return allow_stub_calls_; } 12903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void set_has_frame(bool value) { has_frame_ = value; } 12913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool has_frame() { return has_frame_; } 12923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch inline bool AllowThisStubCall(CodeStub* stub); 1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static int SafepointRegisterStackIndex(Register reg) { 12958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return SafepointRegisterStackIndex(reg.code()); 12968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 12978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 12983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Activation support. 12993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void EnterFrame(StackFrame::Type type); 13003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void LeaveFrame(StackFrame::Type type); 13013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 13023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Expects object in rax and returns map with validated enum cache 13033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // in rax. Assumes that any other register can be used as a scratch. 13043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CheckEnumCache(Register null_value, 13053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* call_runtime); 13063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 13081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Order general registers are pushed by Pushad. 130944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // rax, rcx, rdx, rbx, rsi, rdi, r8, r9, r11, r14, r15. 13103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const int kSafepointPushRegisterIndices[Register::kNumRegisters]; 1311e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch static const int kNumSafepointSavedRegisters = 11; 1312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static const int kSmiShift = kSmiTagSize + kSmiShiftSize; 1313e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool generating_stub_; 1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool allow_stub_calls_; 13163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool has_frame_; 131744f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool root_array_available_; 13188defd9ff6930b4e24729971a61cf7469daf119beSteve Block 13198defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Returns a register holding the smi value. The register MUST NOT be 13208defd9ff6930b4e24729971a61cf7469daf119beSteve Block // modified. It may be the "smi 1 constant" register. 13218defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register GetSmiConstant(Smi* value); 13228defd9ff6930b4e24729971a61cf7469daf119beSteve Block 13238defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Moves the smi value to the destination register. 13248defd9ff6930b4e24729971a61cf7469daf119beSteve Block void LoadSmiConstant(Register dst, Smi* value); 13258defd9ff6930b4e24729971a61cf7469daf119beSteve Block 13263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // This handle will be patched with the code object on installation. 13273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Handle<Object> code_object_; 1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Helper functions for generating invokes. 1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void InvokePrologue(const ParameterCount& expected, 1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> code_constant, 1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register code_register, 1334257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* done, 13353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool* definitely_mismatches, 1336e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch InvokeFlag flag, 1337257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump = Label::kFar, 1338257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const CallWrapper& call_wrapper = NullCallWrapper(), 1339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKind call_kind = CALL_AS_METHOD); 1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 134180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen void EnterExitFramePrologue(bool save_rax); 13428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 13438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Allocates arg_stack_space * kPointerSize memory (not GCed) on the stack 13448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // accessible via StackSpaceOperand. 13451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void EnterExitFrameEpilogue(int arg_stack_space, bool save_doubles); 13468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 13478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang void LeaveExitFrameEpilogue(); 1348bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocation support helpers. 13506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Loads the top of new-space into the result register. 13516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Otherwise the address of the new-space top is loaded into scratch (if 13526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // scratch is valid), and the new-space top is loaded into result. 1353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void LoadAllocationTopHelper(Register result, 1354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 1355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags); 13566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Update allocation top with value in result_end register. 13576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // If scratch is valid, it contains the address of the allocation top. 1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void UpdateAllocationTopHelper(Register result_end, Register scratch); 1359bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 1360bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Helper for PopHandleScope. Allowed to perform a GC and returns 1361bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // NULL if gc_allowed. Does not perform a GC if !gc_allowed, and 1362bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // possibly returns a failure object indicating an allocation failure. 1363bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Object* PopHandleScopeHelper(Register saved, 1364bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Register scratch, 1365bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch bool gc_allowed); 1366e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 13673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Helper for implementing JumpIfNotInNewSpace and JumpIfInNewSpace. 13683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void InNewSpace(Register object, 13693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 13703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition cc, 13713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* branch, 13723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance distance = Label::kFar); 13733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 13743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Helper for finding the mark bits for an address. Afterwards, the 13753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // bitmap register points at the word with the mark bits and the mask 13763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the position of the first bit. Uses rcx as scratch and leaves addr_reg 13773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // unchanged. 13783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch inline void GetMarkBits(Register addr_reg, 13793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register bitmap_reg, 13803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register mask_reg); 13813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 13823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Helper for throwing exceptions. Compute a handler address and jump to 13833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // it. See the implementation for register usage. 13843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void JumpToHandlerEntry(); 1385e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1386e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Compute memory operands for safepoint stack slots. 1387e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Operand SafepointRegisterSlot(Register reg); 1388e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch static int SafepointRegisterStackIndex(int reg_code) { 1389e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return kNumSafepointRegisters - kSafepointPushRegisterIndices[reg_code] - 1; 1390e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 1391e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1392e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Needs access to SafepointRegisterStackIndex for optimized frame 1393e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // traversal. 1394e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch friend class OptimizedFrame; 1395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The code patcher is used to patch (typically) small parts of code e.g. for 1399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// debugging and other types of instrumentation. When using the code patcher 1400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the exact number of bytes specified must be emitted. Is not legal to emit 1401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// relocation information. If any of these constraints are violated it causes 1402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// an assertion. 1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass CodePatcher { 1404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 1405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CodePatcher(byte* address, int size); 1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual ~CodePatcher(); 1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Macro assembler to emit code. 1409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MacroAssembler* masm() { return &masm_; } 1410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* address_; // The address of the code being patched. 1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int size_; // Number of bytes of the expected patch size. 1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MacroAssembler masm_; // Macro assembler used to generate the code. 1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------- 1419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Static helper functions. 1420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Generate an Operand for loading a field from an object. 14223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochinline Operand FieldOperand(Register object, int offset) { 1423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Operand(object, offset - kHeapObjectTag); 1424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Generate an Operand for loading an indexed field from an object. 14283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochinline Operand FieldOperand(Register object, 14293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register index, 14303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ScaleFactor scale, 14313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int offset) { 1432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Operand(object, index, scale, offset - kHeapObjectTag); 1433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 14363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochinline Operand ContextOperand(Register context, int index) { 14378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang return Operand(context, Context::SlotOffset(index)); 14388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang} 14398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 14408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 14413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochinline Operand GlobalObjectOperand() { 14428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang return ContextOperand(rsi, Context::GLOBAL_INDEX); 14438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang} 14448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 14458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 14468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang// Provides access to exit frame stack space (not GCed). 14473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochinline Operand StackSpaceOperand(int index) { 14488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang#ifdef _WIN64 14498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const int kShaddowSpace = 4; 14508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang return Operand(rsp, (index + kShaddowSpace) * kPointerSize); 14518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang#else 14528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang return Operand(rsp, index * kPointerSize); 14538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang#endif 14548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang} 14558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 14568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 14578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef GENERATED_CODE_COVERAGE 1459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockextern void LogGeneratedCodeCoverage(const char* file_line); 1460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define CODE_COVERAGE_STRINGIFY(x) #x 1461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x) 1462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__) 1463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define ACCESS_MASM(masm) { \ 1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* x64_coverage_function = \ 1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<byte*>(FUNCTION_ADDR(LogGeneratedCodeCoverage)); \ 1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->pushfd(); \ 1467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->pushad(); \ 1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->push(Immediate(reinterpret_cast<int>(&__FILE_LINE__))); \ 1469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->call(x64_coverage_function, RelocInfo::RUNTIME_ENTRY); \ 1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->pop(rax); \ 1471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->popad(); \ 1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->popfd(); \ 1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } \ 1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm-> 1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else 1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define ACCESS_MASM(masm) masm-> 1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // V8_X64_MACRO_ASSEMBLER_X64_H_ 1482