macro-assembler-ia32.h revision 589d6979ff2ef66fca2d8fa51404c369ca5e9250
18b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// Copyright 2011 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_IA32_MACRO_ASSEMBLER_IA32_H_ 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define V8_IA32_MACRO_ASSEMBLER_IA32_H_ 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "assembler.h" 32257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#include "v8globals.h" 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen// Flags used for the AllocateInNewSpace functions. 3825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsenenum AllocationFlags { 3925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // No special flags. 4025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen NO_ALLOCATION_FLAGS = 0, 4125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // Return the pointer to the allocated already tagged as a heap object. 4225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen TAG_OBJECT = 1 << 0, 4325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // The content of the result register already contains the allocation top in 4425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // new space. 4525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen RESULT_CONTAINS_TOP = 1 << 1 4625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen}; 4725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen 48257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 49e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Convenience for platform-independent signatures. We do not normally 50e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// distinguish memory operands from other operands on ia32. 51e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarketypedef Operand MemOperand; 52e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// MacroAssembler implements a collection of frequently used macros. 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass MacroAssembler: public Assembler { 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // The isolate parameter can be NULL if the macro assembler should 578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // not use isolate-dependent functionality. In this case, it's the 588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // responsibility of the caller to never invoke such function on the 598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // macro assembler. 608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch MacroAssembler(Isolate* isolate, void* buffer, int size); 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // GC Support 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // For page containing |object| mark region covering |addr| dirty. 667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // RecordWriteHelper only works if the object is not in new 676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // space. 686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void RecordWriteHelper(Register object, 696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register addr, 706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch); 716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check if object is in new space. 736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // scratch can be object itself, but it will be clobbered. 746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void InNewSpace(Register object, 756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch, 766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Condition cc, // equal for new space, not_equal otherwise. 77257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* branch, 78257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance branch_near = Label::kFar); 796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 808defd9ff6930b4e24729971a61cf7469daf119beSteve Block // For page containing |object| mark region covering [object+offset] 818defd9ff6930b4e24729971a61cf7469daf119beSteve Block // dirty. |object| is the object being stored into, |value| is the 828defd9ff6930b4e24729971a61cf7469daf119beSteve Block // object being stored. If offset is zero, then the scratch register 838defd9ff6930b4e24729971a61cf7469daf119beSteve Block // contains the array index into the elements array represented as a 848defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Smi. All registers are clobbered by the operation. RecordWrite 858defd9ff6930b4e24729971a61cf7469daf119beSteve Block // filters out smis so it does not update the write barrier if the 868defd9ff6930b4e24729971a61cf7469daf119beSteve Block // value is a smi. 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void RecordWrite(Register object, 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset, 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register value, 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch); 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 928defd9ff6930b4e24729971a61cf7469daf119beSteve Block // For page containing |object| mark region covering |address| 938defd9ff6930b4e24729971a61cf7469daf119beSteve Block // dirty. |object| is the object being stored into, |value| is the 948defd9ff6930b4e24729971a61cf7469daf119beSteve Block // object being stored. All registers are clobbered by the 958defd9ff6930b4e24729971a61cf7469daf119beSteve Block // operation. RecordWrite filters out smis so it does not update the 968defd9ff6930b4e24729971a61cf7469daf119beSteve Block // write barrier if the value is a smi. 978defd9ff6930b4e24729971a61cf7469daf119beSteve Block void RecordWrite(Register object, 988defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register address, 998defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register value); 1008defd9ff6930b4e24729971a61cf7469daf119beSteve Block 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Debugger Support 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 105402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu void DebugBreak(); 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Activation frames 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void EnterInternalFrame() { EnterFrame(StackFrame::INTERNAL); } 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void LeaveInternalFrame() { LeaveFrame(StackFrame::INTERNAL); } 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void EnterConstructFrame() { EnterFrame(StackFrame::CONSTRUCT); } 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); } 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Enter specific kind of exit frame. Expects the number of 118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // arguments in register eax and sets up the number of arguments in 119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // register edi and the pointer to the first argument in register 120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // esi. 121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void EnterExitFrame(bool save_doubles); 122d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang void EnterApiExitFrame(int argc); 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Leave the current exit frame. Expects the return value in 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // register eax:edx (untouched) and the pointer to the first 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // argument in register esi. 128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void LeaveExitFrame(bool save_doubles); 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Leave the current exit frame. Expects the return value in 1318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // register eax (untouched). 1328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang void LeaveApiExitFrame(); 1338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 134d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Find the function context up the context chain. 135d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void LoadContext(Register dst, int context_chain_length); 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Load the global function with the given index. 13880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen void LoadGlobalFunction(int index, Register function); 13980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 14080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Load the initial map from the global function. The registers 14180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // function and map can be the same. 14280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen void LoadGlobalFunctionInitialMap(Register function, Register map); 14380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Push and pop the registers that can hold pointers. 145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void PushSafepointRegisters() { pushad(); } 146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void PopSafepointRegisters() { popad(); } 147e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Store the value in register/immediate src in the safepoint 148e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // register stack slot for register dst. 149e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void StoreToSafepointRegisterSlot(Register dst, Register src); 150e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void StoreToSafepointRegisterSlot(Register dst, Immediate src); 151e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void LoadFromSafepointRegisterSlot(Register dst, Register src); 152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // JavaScript invokes 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Setup call kind marking in ecx. The method takes ecx as an 157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // explicit first parameter to make the code more readable at the 158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // call sites. 159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void SetCallKind(Register dst, CallKind kind); 160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the JavaScript function code by either calling or jumping. 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void InvokeCode(const Operand& code, 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& expected, 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InvokeFlag flag, 166257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const CallWrapper& call_wrapper, 167257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKind call_kind); 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void InvokeCode(Handle<Code> code, 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& expected, 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::Mode rmode, 173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InvokeFlag flag, 174257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const CallWrapper& call_wrapper, 175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKind call_kind); 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the JavaScript function in the given register. Changes the 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // current context to the context in the function before invoking. 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void InvokeFunction(Register function, 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 181b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InvokeFlag flag, 182257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const CallWrapper& call_wrapper, 183257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKind call_kind); 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 185402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu void InvokeFunction(JSFunction* function, 186402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu const ParameterCount& actual, 187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InvokeFlag flag, 188257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const CallWrapper& call_wrapper, 189257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKind call_kind); 190402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke specified builtin JavaScript function. Adds an entry to 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the unresolved list if the name does not resolve. 193b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void InvokeBuiltin(Builtins::JavaScript id, 194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InvokeFlag flag, 195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const CallWrapper& call_wrapper = NullCallWrapper()); 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 197791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block // Store the function for the given builtin in the target register. 198791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block void GetBuiltinFunction(Register target, Builtins::JavaScript id); 199791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Store the code object for the given builtin in the target register. 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void GetBuiltinEntry(Register target, Builtins::JavaScript id); 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Expression support 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Set(Register dst, const Immediate& x); 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Set(const Operand& dst, const Immediate& x); 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 207053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block // Support for constant splitting. 208053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block bool IsUnsafeImmediate(const Immediate& x); 209053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block void SafeSet(Register dst, const Immediate& x); 210053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block void SafePush(const Immediate& x); 211053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block 21269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Compare a register against a known root, e.g. undefined, null, true, ... 21369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch void CompareRoot(Register with, Heap::RootListIndex index); 21469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compare object type for heap object. 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Incoming register is heap_object and outgoing register is map. 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void CmpObjectType(Register heap_object, InstanceType type, Register map); 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compare instance type for map. 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void CmpInstanceType(Register map, InstanceType type); 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check if a map for a JSObject indicates that the object has fast elements. 2233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Jump to the specified label if it does not. 2243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void CheckFastElements(Register map, 2253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label* fail, 2263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label::Distance distance = Label::kFar); 2273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if the map of an object is equal to a specified map and branch to 229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // label if not. Skip the smi check if not required (object is known to be a 230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // heap object) 2313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void CheckMap(Register obj, 2323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Handle<Map> map, 2333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Label* fail, 234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SmiCheckType smi_check_type); 235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if the map of an object is equal to a specified map and branch to a 237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // specified target if equal. Skip the smi check if not required (object is 238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // known to be a heap object) 239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void DispatchMap(Register obj, 240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Map> map, 241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> success, 242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SmiCheckType smi_check_type); 2433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 244e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check if the object in register heap_object is a string. Afterwards the 245e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // register map contains the object map and the register instance_type 246e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // contains the instance_type. The registers map and instance_type can be the 247e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // same in which case it contains the instance type afterwards. Either of the 248e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // registers map and instance_type can be the same as heap_object. 249e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Condition IsObjectStringType(Register heap_object, 250e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register map, 251e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register instance_type); 252e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check if a heap object's type is in the JSObject range, not including 2547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // JSFunction. The object's map will be loaded in the map register. 2557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Any or all of the three registers may be the same. 2567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // The contents of the scratch register will always be overwritten. 2577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch void IsObjectJSObjectType(Register heap_object, 2587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register map, 2597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch, 2607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label* fail); 2617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 2627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // The contents of the scratch register will be overwritten. 2637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch void IsInstanceJSObjectType(Register map, Register scratch, Label* fail); 2647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // FCmp is similar to integer cmp, but requires unsigned 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // jcc instructions (je, ja, jae, jb, jbe, je, and jz). 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void FCmp(); 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void ClampUint8(Register reg); 270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void ClampDoubleToUint8(XMMRegister input_reg, 272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch XMMRegister scratch_reg, 273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register result_reg); 274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 276e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Smi tagging support. 277e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void SmiTag(Register reg) { 27869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 27969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTagSize == 1); 2806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block add(reg, Operand(reg)); 281e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 282e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void SmiUntag(Register reg) { 283e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke sar(reg, kSmiTagSize); 284e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 285e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 286756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Modifies the register even if it does not contain a Smi! 287756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick void SmiUntag(Register reg, Label* is_smi) { 28869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTagSize == 1); 289756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick sar(reg, kSmiTagSize); 29069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 291756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick j(not_carry, is_smi); 292756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 293756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 2941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Jump the register contains a smi. 2953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch inline void JumpIfSmi(Register value, 2963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label* smi_label, 2973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label::Distance distance = Label::kFar) { 2983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch test(value, Immediate(kSmiTagMask)); 2993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch j(zero, smi_label, distance); 3003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 3013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Jump if the operand is a smi. 3023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch inline void JumpIfSmi(Operand value, 3033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label* smi_label, 3043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label::Distance distance = Label::kFar) { 3051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block test(value, Immediate(kSmiTagMask)); 3063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch j(zero, smi_label, distance); 3071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 3081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Jump if register contain a non-smi. 3093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch inline void JumpIfNotSmi(Register value, 3103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label* not_smi_label, 3113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label::Distance distance = Label::kFar) { 3121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block test(value, Immediate(kSmiTagMask)); 3133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch j(not_zero, not_smi_label, distance); 3141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 3151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void LoadInstanceDescriptors(Register map, Register descriptors); 317756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 3180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen void LoadPowerOf2(XMMRegister dst, Register scratch, int power); 3190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 320402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Abort execution if argument is not a number. Used in debug code. 3216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void AbortIfNotNumber(Register object); 3226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Abort execution if argument is not a smi. Used in debug code. 3246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void AbortIfNotSmi(Register object); 325402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 326756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Abort execution if argument is a smi. Used in debug code. 327756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick void AbortIfSmi(Register object); 328756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 32980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Abort execution if argument is a string. Used in debug code. 33080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen void AbortIfNotString(Register object); 33180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exception handling 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Push a new try handler and link into try handler chain. The return 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // address must be pushed before calling this helper. 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void PushTryHandler(CodeLocation try_location, HandlerType type); 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 339e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Unlink the stack handler on top of the stack from the try handler chain. 340e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void PopTryHandler(); 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 342e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Activate the top handler in the try hander chain. 343e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void Throw(Register value); 344e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 345e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void ThrowUncatchable(UncatchableExceptionType type, Register value); 346e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Inline caching support 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Generate code for checking access rights - used for security checks 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // on access to global objects across environments. The holder register 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is left untouched, but the scratch register is clobbered. 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void CheckAccessGlobalProxy(Register holder_reg, 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss); 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void LoadFromNumberDictionary(Label* miss, 3593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register elements, 3603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register key, 3613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register r0, 3623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register r1, 3633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register r2, 3643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register result); 3653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 3663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocation support 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocate an object in new space. If the new space is exhausted control 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // continues at the gc_required label. The allocated object is returned in 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result and end of the new object is returned in result_end. The register 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scratch can be passed as no_reg in which case an additional object 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // reference will be added to the reloc info. The returned pointers in result 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // and result_end have not yet been tagged as heap objects. If 376d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // result_contains_top_on_entry is true the content of result is known to be 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the allocation top on entry (could be result_end from a previous call to 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // AllocateInNewSpace). If result_contains_top_on_entry is true scratch 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // should be no_reg as it is never used. 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void AllocateInNewSpace(int object_size, 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result_end, 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required, 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags); 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void AllocateInNewSpace(int header_size, 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ScaleFactor element_size, 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register element_count, 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result_end, 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required, 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags); 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void AllocateInNewSpace(Register object_size, 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result_end, 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required, 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags); 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Undo allocation in new space. The object passed and objects allocated after 404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // it will no longer be allocated. Make sure that no pointers are left to the 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // object(s) no longer allocated as they would be invalid when allocation is 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // un-done. 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void UndoAllocationInNewSpace(Register object); 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Allocate a heap number in new space with undefined value. The 4103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // register scratch2 can be passed as no_reg; the others must be 4113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // valid registers. Returns tagged pointer in result register, or 4123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // jumps to gc_required if new space is full. 4133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void AllocateHeapNumber(Register result, 4143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register scratch1, 4153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register scratch2, 4163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label* gc_required); 4173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 418d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Allocate a sequential string. All the header fields of the string object 419d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // are initialized. 420d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void AllocateTwoByteString(Register result, 421d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register length, 422d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch1, 423d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch2, 424d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch3, 425d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label* gc_required); 426d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void AllocateAsciiString(Register result, 427d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register length, 428d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch1, 429d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch2, 430d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch3, 431d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label* gc_required); 4329ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick void AllocateAsciiString(Register result, 4339ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick int length, 4349ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick Register scratch1, 4359ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick Register scratch2, 4369ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick Label* gc_required); 437d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 438d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Allocate a raw cons string object. Only the map field of the result is 439d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // initialized. 440589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch void AllocateTwoByteConsString(Register result, 441d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch1, 442d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch2, 443d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label* gc_required); 444d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void AllocateAsciiConsString(Register result, 445d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch1, 446d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch2, 447d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label* gc_required); 448d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 44969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Allocate a raw sliced string object. Only the map field of the result is 45069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // initialized. 451589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch void AllocateTwoByteSlicedString(Register result, 45269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Register scratch1, 45369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Register scratch2, 45469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Label* gc_required); 45569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch void AllocateAsciiSlicedString(Register result, 45669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Register scratch1, 45769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Register scratch2, 45869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Label* gc_required); 45969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 460b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Copy memory, byte-by-byte, from source to destination. Not optimized for 461b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // long or aligned copies. 462b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // The contents of index and scratch are destroyed. 463b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch void CopyBytes(Register source, 464b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register destination, 465b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register length, 466b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register scratch); 4678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Support functions. 470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if result is zero and op is negative. 472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void NegativeZeroTest(Register result, Register op, Label* then_label); 473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if result is zero and any of op1 and op2 are negative. 475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Register scratch is destroyed, and it must be different from op2. 476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void NegativeZeroTest(Register result, Register op1, Register op2, 477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, Label* then_label); 478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Try to get function prototype of a function and puts the value in 480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the result register. Checks that the function really is a 481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // function and jumps to the miss label if the fast checks fail. The 482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // function register will be untouched; the other registers may be 483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // clobbered. 484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void TryGetFunctionPrototype(Register function, 485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss); 488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Generates code for reporting that an illegal operation has 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // occurred. 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void IllegalOperation(int num_arguments); 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 49380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Picks out an array index from the hash field. 49480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Register use: 49580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // hash - holds the index's hash. Clobbered. 49680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // index - holds the overwritten index on exit. 49780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen void IndexFromHash(Register hash, Register index); 49880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Runtime calls 501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 502e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Call a code stub. Generate the code if necessary. 503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void CallStub(CodeStub* stub, unsigned ast_id = kNoASTId); 504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 505e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Call a code stub and return the code object called. Try to generate 506e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // the code if necessary. Do not perform a GC but instead return a retry 507e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // after GC failure. 5085913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck MUST_USE_RESULT MaybeObject* TryCallStub(CodeStub* stub); 509e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 510e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Tail call a code stub (jump). Generate the code if necessary. 511d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void TailCallStub(CodeStub* stub); 512d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 513e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Tail call a code stub (jump) and return the code object called. Try to 514e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // generate the code if necessary. Do not perform a GC but instead return 515e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // a retry after GC failure. 5165913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck MUST_USE_RESULT MaybeObject* TryTailCallStub(CodeStub* stub); 517e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return from a code stub after popping its arguments. 519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void StubReturn(int argc); 520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call a runtime routine. 52244f0eee88ff00398ff7f715fab053374d808c90dSteve Block void CallRuntime(const Runtime::Function* f, int num_arguments); 523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void CallRuntimeSaveDoubles(Runtime::FunctionId id); 524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Call a runtime function, returning the CodeStub object called. 526e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Try to generate the stub code if necessary. Do not perform a GC 527e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // but instead return a retry after GC failure. 52844f0eee88ff00398ff7f715fab053374d808c90dSteve Block MUST_USE_RESULT MaybeObject* TryCallRuntime(const Runtime::Function* f, 5295913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int num_arguments); 530e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Convenience function: Same as above, but takes the fid instead. 532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void CallRuntime(Runtime::FunctionId id, int num_arguments); 533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 534e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Convenience function: Same as above, but takes the fid instead. 5355913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck MUST_USE_RESULT MaybeObject* TryCallRuntime(Runtime::FunctionId id, 5365913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int num_arguments); 537e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 538bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Convenience function: call an external reference. 539bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch void CallExternalReference(ExternalReference ref, int num_arguments); 540bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Tail call of a runtime routine (jump). 5426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Like JumpToExternalReference, but also takes care of passing the number 5436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // of parameters. 5446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void TailCallExternalReference(const ExternalReference& ext, 5456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int num_arguments, 5466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int result_size); 5476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 5488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Tail call of a runtime routine (jump). Try to generate the code if 5498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // necessary. Do not perform a GC but instead return a retry after GC failure. 5508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang MUST_USE_RESULT MaybeObject* TryTailCallExternalReference( 5518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const ExternalReference& ext, int num_arguments, int result_size); 5528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 5536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Convenience function: tail call a runtime routine (jump). 5546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void TailCallRuntime(Runtime::FunctionId fid, 555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int num_arguments, 556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result_size); 557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Convenience function: tail call a runtime routine (jump). Try to generate 5598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // the code if necessary. Do not perform a GC but instead return a retry after 5608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // GC failure. 5618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang MUST_USE_RESULT MaybeObject* TryTailCallRuntime(Runtime::FunctionId fid, 5628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang int num_arguments, 5638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang int result_size); 5648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 5656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Before calling a C-function from generated code, align arguments on stack. 5666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // After aligning the frame, arguments must be stored in esp[0], esp[4], 5676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // etc., not pushed. The argument count assumes all arguments are word sized. 5686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Some compilers/platforms require the stack to be aligned when calling 5696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // C++ code. 5706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Needs a scratch register to do some arithmetic. This register will be 5716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // trashed. 5726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void PrepareCallCFunction(int num_arguments, Register scratch); 5736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 5746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Calls a C function and cleans up the space for arguments allocated 5756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // by PrepareCallCFunction. The called function is not allowed to trigger a 5766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // garbage collection, since that might move the code and invalidate the 5776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // return address (unless this is somehow accounted for by the called 5786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // function). 5796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void CallCFunction(ExternalReference function, int num_arguments); 5806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void CallCFunction(Register function, int num_arguments); 5816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 5825913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // Prepares stack to put arguments (aligns and so on). Reserves 5835913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // space for return value if needed (assumes the return value is a handle). 5843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Arguments must be stored in ApiParameterOperand(0), ApiParameterOperand(1) 5853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // etc. Saves context (esi). If space was reserved for return value then 5863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // stores the pointer to the reserved slot into esi. 5873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void PrepareCallApiFunction(int argc); 588d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 58990bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner // Calls an API function. Allocates HandleScope, extracts 5905913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // returned value from handle and propagates exceptions. 5918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Clobbers ebx, edi and caller-save registers. Restores context. 5928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // On return removes stack_space * kPointerSize (GCed). 5938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang MaybeObject* TryCallApiFunctionAndReturn(ApiFunction* function, 5948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang int stack_space); 595e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to a runtime routine. 5976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void JumpToExternalReference(const ExternalReference& ext); 598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang MaybeObject* TryJumpToExternalReference(const ExternalReference& ext); 6008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Utilities 604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Ret(); 606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Return and drop arguments from stack, where the number of arguments 6081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // may be bigger than 2^16 - 1. Requires a scratch register. 6091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void Ret(int bytes_dropped, Register scratch); 6101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 611e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Emit code to discard a non-negative number of pointer-sized elements 612e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // from the stack, clobbering only the esp register. 613e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void Drop(int element_count); 614e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 615e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void Call(Label* target) { call(target); } 616e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Emit call to the code we are currently generating. 618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void CallSelf() { 619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Code> self(reinterpret_cast<Code**>(CodeObject().location())); 620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch call(self, RelocInfo::CODE_TARGET); 621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Move if the registers are not identical. 6240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen void Move(Register target, Register source); 6250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 626e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void Move(Register target, Handle<Object> value); 627e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 6283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Push a handle value. 6293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void Push(Handle<Object> handle) { push(handle); } 6303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 6318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Handle<Object> CodeObject() { 6328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!code_object_.is_null()); 6338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return code_object_; 6348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // StatsCounter support 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SetCounter(StatsCounter* counter, int value); 641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void IncrementCounter(StatsCounter* counter, int value); 642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void DecrementCounter(StatsCounter* counter, int value); 643d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke void IncrementCounter(Condition cc, StatsCounter* counter, int value); 644d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke void DecrementCounter(Condition cc, StatsCounter* counter, int value); 645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Debugging 649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calls Abort(msg) if the condition cc is not satisfied. 651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Use --debug_code to enable. 652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Assert(Condition cc, const char* msg); 653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 654756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick void AssertFastElements(Register elements); 655756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Like Assert(), but always enabled. 657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Check(Condition cc, const char* msg); 658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Print a message to stdout and abort execution. 660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Abort(const char* msg); 661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the stack is aligned. 6636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void CheckStackAlignment(); 6646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Verify restrictions about code generated in stubs. 666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void set_generating_stub(bool value) { generating_stub_ = value; } 667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool generating_stub() { return generating_stub_; } 668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; } 669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool allow_stub_calls() { return allow_stub_calls_; } 670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 671d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // --------------------------------------------------------------------------- 672d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // String utilities. 673d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 674402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Check whether the instance type represents a flat ascii string. Jump to the 675402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // label if not. If the instance type can be scratched specify same register 676402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // for both instance type and scratch. 677402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu void JumpIfInstanceTypeIsNotSequentialAscii(Register instance_type, 678402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register scratch, 6796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label* on_not_flat_ascii_string); 680402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 681d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Checks if both objects are sequential ASCII strings, and jumps to label 682d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // if either is not. 683d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke void JumpIfNotBothSequentialAsciiStrings(Register object1, 684d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Register object2, 685d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Register scratch1, 686d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Register scratch2, 6876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label* on_not_flat_ascii_strings); 688d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 6898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static int SafepointRegisterStackIndex(Register reg) { 6908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return SafepointRegisterStackIndex(reg.code()); 6918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 6928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool generating_stub_; 695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool allow_stub_calls_; 6963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // This handle will be patched with the code object on installation. 6973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Handle<Object> code_object_; 698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Helper functions for generating invokes. 700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void InvokePrologue(const ParameterCount& expected, 701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> code_constant, 703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const Operand& code_operand, 704257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* done, 705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InvokeFlag flag, 706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance done_near = Label::kFar, 707257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const CallWrapper& call_wrapper = NullCallWrapper(), 708257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKind call_kind = CALL_AS_METHOD); 709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Activation support. 711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void EnterFrame(StackFrame::Type type); 712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void LeaveFrame(StackFrame::Type type); 713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 71480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen void EnterExitFramePrologue(); 715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void EnterExitFrameEpilogue(int argc, bool save_doubles); 716d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 7178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang void LeaveExitFrameEpilogue(); 7188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocation support helpers. 720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void LoadAllocationTopHelper(Register result, 721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags); 723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void UpdateAllocationTopHelper(Register result_end, Register scratch); 724e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 725e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Helper for PopHandleScope. Allowed to perform a GC and returns 726e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // NULL if gc_allowed. Does not perform a GC if !gc_allowed, and 727e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // possibly returns a failure object indicating an allocation failure. 7285913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck MUST_USE_RESULT MaybeObject* PopHandleScopeHelper(Register saved, 7295913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Register scratch, 7305913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck bool gc_allowed); 731e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 732e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 733e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Compute memory operands for safepoint stack slots. 734e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Operand SafepointRegisterSlot(Register reg); 735e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch static int SafepointRegisterStackIndex(int reg_code); 736e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 737e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Needs access to SafepointRegisterStackIndex for optimized frame 738e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // traversal. 739e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch friend class OptimizedFrame; 740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The code patcher is used to patch (typically) small parts of code e.g. for 744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// debugging and other types of instrumentation. When using the code patcher 745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the exact number of bytes specified must be emitted. Is not legal to emit 746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// relocation information. If any of these constraints are violated it causes 747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// an assertion. 748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass CodePatcher { 749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CodePatcher(byte* address, int size); 751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual ~CodePatcher(); 752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Macro assembler to emit code. 754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MacroAssembler* masm() { return &masm_; } 755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* address_; // The address of the code being patched. 758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int size_; // Number of bytes of the expected patch size. 759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MacroAssembler masm_; // Macro assembler used to generate the code. 760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------- 764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Static helper functions. 765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Generate an Operand for loading a field from an object. 767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic inline Operand FieldOperand(Register object, int offset) { 768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Operand(object, offset - kHeapObjectTag); 769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Generate an Operand for loading an indexed field from an object. 773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic inline Operand FieldOperand(Register object, 774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register index, 775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ScaleFactor scale, 776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset) { 777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Operand(object, index, scale, offset - kHeapObjectTag); 778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 7818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangstatic inline Operand ContextOperand(Register context, int index) { 7828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang return Operand(context, Context::SlotOffset(index)); 7838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang} 7848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 7858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 7868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangstatic inline Operand GlobalObjectOperand() { 7878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang return ContextOperand(esi, Context::GLOBAL_INDEX); 7888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang} 7898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 7908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 7915913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck// Generates an Operand for saving parameters after PrepareCallApiFunction. 7925913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckOperand ApiParameterOperand(int index); 7935913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck 794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef GENERATED_CODE_COVERAGE 796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockextern void LogGeneratedCodeCoverage(const char* file_line); 797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define CODE_COVERAGE_STRINGIFY(x) #x 798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x) 799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__) 800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define ACCESS_MASM(masm) { \ 801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* ia32_coverage_function = \ 802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<byte*>(FUNCTION_ADDR(LogGeneratedCodeCoverage)); \ 803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->pushfd(); \ 804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->pushad(); \ 805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->push(Immediate(reinterpret_cast<int>(&__FILE_LINE__))); \ 806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->call(ia32_coverage_function, RelocInfo::RUNTIME_ENTRY); \ 807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->pop(eax); \ 808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->popad(); \ 809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->popfd(); \ 810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } \ 811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm-> 812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else 813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define ACCESS_MASM(masm) masm-> 814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // V8_IA32_MACRO_ASSEMBLER_IA32_H_ 820