macro-assembler-ia32.h revision 3ef787dbeca8a5fb1086949cda830dccee07bfbd
13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef V8_IA32_MACRO_ASSEMBLER_IA32_H_ 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define V8_IA32_MACRO_ASSEMBLER_IA32_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 50e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Convenience for platform-independent signatures. We do not normally 51e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// distinguish memory operands from other operands on ia32. 52e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarketypedef Operand MemOperand; 53e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochenum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET }; 553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochenum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK }; 563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool AreAliased(Register r1, Register r2, Register r3, Register r4); 593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// MacroAssembler implements a collection of frequently used macros. 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass MacroAssembler: public Assembler { 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // The isolate parameter can be NULL if the macro assembler should 658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // not use isolate-dependent functionality. In this case, it's the 668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // responsibility of the caller to never invoke such function on the 678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // macro assembler. 688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch MacroAssembler(Isolate* isolate, void* buffer, int size); 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // GC Support 723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch enum RememberedSetFinalAction { 733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kReturnAtEnd, 743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kFallThroughAtEnd 753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch }; 763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Record in the remembered set the fact that we have a pointer to new space 783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // at the address pointed to by the addr register. Only works if addr is not 793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // in new space. 803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void RememberedSetHelper(Register object, // Used for debug code. 813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register addr, 823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SaveFPRegsMode save_fp, 843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RememberedSetFinalAction and_then); 853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CheckPageFlag(Register object, 873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int mask, 893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition cc, 903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* condition_met, 913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance condition_met_distance = Label::kFar); 923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if object is in new space. Jumps if the object is not in new space. 943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The register scratch can be object itself, but scratch will be clobbered. 953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void JumpIfNotInNewSpace(Register object, 963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* branch, 983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance distance = Label::kFar) { 993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch InNewSpace(object, scratch, zero, branch, distance); 1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if object is in new space. Jumps if the object is in new space. 1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The register scratch can be object itself, but it will be clobbered. 1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void JumpIfInNewSpace(Register object, 1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* branch, 1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance distance = Label::kFar) { 1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch InNewSpace(object, scratch, not_zero, branch, distance); 1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if an object has a given incremental marking color. Also uses ecx! 1123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void HasColor(Register object, 1133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch0, 1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1, 1153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* has_color, 1163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance has_color_distance, 1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int first_bit, 1183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int second_bit); 1193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void JumpIfBlack(Register object, 1213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch0, 1223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1, 1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* on_black, 1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance on_black_distance = Label::kFar); 1253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Checks the color of an object. If the object is already grey or black 1273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // then we just fall through, since it is already live. If it is white and 1283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // we can determine that it doesn't need to be scanned, then we just mark it 1293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // black and fall through. For the rest we jump to the label so the 1303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // incremental marker can fix its assumptions. 1313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void EnsureNotWhite(Register object, 1323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1, 1333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch2, 1343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* object_is_white_and_not_data, 1353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance distance); 1363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Notify the garbage collector that we wrote a pointer into an object. 1383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // |object| is the object being stored into, |value| is the object being 1393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // stored. value and scratch registers are clobbered by the operation. 1403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The offset is the offset from the start of the object, not the offset from 1413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the tagged HeapObject pointer. For use with FieldOperand(reg, off). 1423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void RecordWriteField( 1433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object, 1443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int offset, 1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register value, 1463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 1473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SaveFPRegsMode save_fp, 1483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, 1493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiCheck smi_check = INLINE_SMI_CHECK); 1503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // As above, but the offset has the tag presubtracted. For use with 1523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Operand(reg, off). 1533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void RecordWriteContextSlot( 1543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register context, 1553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int offset, 1563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register value, 1573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 1583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SaveFPRegsMode save_fp, 1593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, 1603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiCheck smi_check = INLINE_SMI_CHECK) { 1613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RecordWriteField(context, 1623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch offset + kHeapObjectTag, 1633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value, 1643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 1653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch save_fp, 1663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch remembered_set_action, 1673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch smi_check); 1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Notify the garbage collector that we wrote a pointer into a fixed array. 1713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // |array| is the array being stored into, |value| is the 1723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // object being stored. |index| is the array index represented as a 1733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Smi. All registers are clobbered by the operation RecordWriteArray 1748defd9ff6930b4e24729971a61cf7469daf119beSteve Block // filters out smis so it does not update the write barrier if the 1758defd9ff6930b4e24729971a61cf7469daf119beSteve Block // value is a smi. 1763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void RecordWriteArray( 1773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register array, 1783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register value, 1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register index, 1803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SaveFPRegsMode save_fp, 1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, 1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiCheck smi_check = INLINE_SMI_CHECK); 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1848defd9ff6930b4e24729971a61cf7469daf119beSteve Block // For page containing |object| mark region covering |address| 1858defd9ff6930b4e24729971a61cf7469daf119beSteve Block // dirty. |object| is the object being stored into, |value| is the 1863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // object being stored. The address and value registers are clobbered by the 1878defd9ff6930b4e24729971a61cf7469daf119beSteve Block // operation. RecordWrite filters out smis so it does not update the 1888defd9ff6930b4e24729971a61cf7469daf119beSteve Block // write barrier if the value is a smi. 1893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void RecordWrite( 1903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object, 1913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register address, 1923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register value, 1933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SaveFPRegsMode save_fp, 1943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, 1953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiCheck smi_check = INLINE_SMI_CHECK); 1968defd9ff6930b4e24729971a61cf7469daf119beSteve Block 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Debugger Support 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 201402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu void DebugBreak(); 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Enter specific kind of exit frame. Expects the number of 205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // arguments in register eax and sets up the number of arguments in 206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // register edi and the pointer to the first argument in register 207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // esi. 208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void EnterExitFrame(bool save_doubles); 209d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang void EnterApiExitFrame(int argc); 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Leave the current exit frame. Expects the return value in 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // register eax:edx (untouched) and the pointer to the first 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // argument in register esi. 215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void LeaveExitFrame(bool save_doubles); 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Leave the current exit frame. Expects the return value in 2188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // register eax (untouched). 2198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang void LeaveApiExitFrame(); 2208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 221d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Find the function context up the context chain. 222d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void LoadContext(Register dst, int context_chain_length); 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Conditionally load the cached Array transitioned map of type 2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // transitioned_kind from the global context if the map in register 2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // map_in_out is the cached Array map in the global context of 2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // expected_kind. 2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void LoadTransitionedArrayMapConditional( 2293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind expected_kind, 2303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind transitioned_kind, 2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register map_in_out, 2323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 2333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* no_map_match); 2343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load the initial map for new Arrays from a JSFunction. 2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void LoadInitialArrayMap(Register function_in, 2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register map_out); 2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 24080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Load the global function with the given index. 24180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen void LoadGlobalFunction(int index, Register function); 24280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 24380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Load the initial map from the global function. The registers 24480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // function and map can be the same. 24580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen void LoadGlobalFunctionInitialMap(Register function, Register map); 24680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Push and pop the registers that can hold pointers. 248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void PushSafepointRegisters() { pushad(); } 249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void PopSafepointRegisters() { popad(); } 250e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Store the value in register/immediate src in the safepoint 251e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // register stack slot for register dst. 252e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void StoreToSafepointRegisterSlot(Register dst, Register src); 253e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void StoreToSafepointRegisterSlot(Register dst, Immediate src); 254e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void LoadFromSafepointRegisterSlot(Register dst, Register src); 255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void LoadHeapObject(Register result, Handle<HeapObject> object); 2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void PushHeapObject(Handle<HeapObject> object); 2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void LoadObject(Register result, Handle<Object> object) { 2603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (object->IsHeapObject()) { 2613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LoadHeapObject(result, Handle<HeapObject>::cast(object)); 2623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Set(result, Immediate(object)); 2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // JavaScript invokes 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up call kind marking in ecx. The method takes ecx as an 271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // explicit first parameter to make the code more readable at the 272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // call sites. 273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void SetCallKind(Register dst, CallKind kind); 274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the JavaScript function code by either calling or jumping. 2763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void InvokeCode(Register code, 2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const ParameterCount& expected, 2783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const ParameterCount& actual, 2793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch InvokeFlag flag, 2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const CallWrapper& call_wrapper, 2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallKind call_kind) { 2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch InvokeCode(Operand(code), expected, actual, flag, call_wrapper, call_kind); 2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void InvokeCode(const Operand& code, 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& expected, 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InvokeFlag flag, 289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const CallWrapper& call_wrapper, 290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKind call_kind); 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void InvokeCode(Handle<Code> code, 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& expected, 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::Mode rmode, 296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InvokeFlag flag, 297257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const CallWrapper& call_wrapper, 298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKind call_kind); 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the JavaScript function in the given register. Changes the 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // current context to the context in the function before invoking. 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void InvokeFunction(Register function, 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InvokeFlag flag, 305257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const CallWrapper& call_wrapper, 306257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKind call_kind); 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void InvokeFunction(Handle<JSFunction> function, 309402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu const ParameterCount& actual, 310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InvokeFlag flag, 311257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const CallWrapper& call_wrapper, 312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKind call_kind); 313402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke specified builtin JavaScript function. Adds an entry to 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the unresolved list if the name does not resolve. 316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void InvokeBuiltin(Builtins::JavaScript id, 317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InvokeFlag flag, 318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const CallWrapper& call_wrapper = NullCallWrapper()); 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 320791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block // Store the function for the given builtin in the target register. 321791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block void GetBuiltinFunction(Register target, Builtins::JavaScript id); 322791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Store the code object for the given builtin in the target register. 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void GetBuiltinEntry(Register target, Builtins::JavaScript id); 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Expression support 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Set(Register dst, const Immediate& x); 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Set(const Operand& dst, const Immediate& x); 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 330053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block // Support for constant splitting. 331053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block bool IsUnsafeImmediate(const Immediate& x); 332053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block void SafeSet(Register dst, const Immediate& x); 333053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block void SafePush(const Immediate& x); 334053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block 3353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Compare against a known root, e.g. undefined, null, true, ... 33669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch void CompareRoot(Register with, Heap::RootListIndex index); 3373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CompareRoot(const Operand& with, Heap::RootListIndex index); 33869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compare object type for heap object. 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Incoming register is heap_object and outgoing register is map. 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void CmpObjectType(Register heap_object, InstanceType type, Register map); 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compare instance type for map. 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void CmpInstanceType(Register map, InstanceType type); 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check if a map for a JSObject indicates that the object has fast elements. 3473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Jump to the specified label if it does not. 3483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void CheckFastElements(Register map, 3493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label* fail, 3503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label::Distance distance = Label::kFar); 3513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 3523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if a map for a JSObject indicates that the object can have both smi 3533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // and HeapObject elements. Jump to the specified label if it does not. 3543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CheckFastObjectElements(Register map, 3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* fail, 3563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance distance = Label::kFar); 3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if a map for a JSObject indicates that the object has fast smi only 3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // elements. Jump to the specified label if it does not. 3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CheckFastSmiOnlyElements(Register map, 3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* fail, 3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance distance = Label::kFar); 3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check to see if maybe_number can be stored as a double in 3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // FastDoubleElements. If it can, store it at the index specified by key in 3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the FastDoubleElements array elements, otherwise jump to fail. 3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void StoreNumberToDoubleElements(Register maybe_number, 3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register elements, 3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register key, 3703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1, 3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch XMMRegister scratch2, 3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* fail, 3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool specialize_for_processor); 3743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Compare an object's map with the specified map and its transitioned 3763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // elements maps if mode is ALLOW_ELEMENT_TRANSITION_MAPS. FLAGS are set with 3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // result of map compare. If multiple map compares are required, the compare 3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sequences branches to early_success. 3793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CompareMap(Register obj, 3803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> map, 3813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* early_success, 3823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompareMapMode mode = REQUIRE_EXACT_MAP); 3833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 384257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if the map of an object is equal to a specified map and branch to 385257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // label if not. Skip the smi check if not required (object is known to be a 3863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match 3873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // against maps that are ElementsKind transition maps of the specified map. 3883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void CheckMap(Register obj, 3893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Handle<Map> map, 3903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Label* fail, 3913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiCheckType smi_check_type, 3923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompareMapMode mode = REQUIRE_EXACT_MAP); 393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if the map of an object is equal to a specified map and branch to a 395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // specified target if equal. Skip the smi check if not required (object is 396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // known to be a heap object) 397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void DispatchMap(Register obj, 398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Map> map, 399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> success, 400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SmiCheckType smi_check_type); 4013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 402e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check if the object in register heap_object is a string. Afterwards the 403e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // register map contains the object map and the register instance_type 404e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // contains the instance_type. The registers map and instance_type can be the 405e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // same in which case it contains the instance type afterwards. Either of the 406e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // registers map and instance_type can be the same as heap_object. 407e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Condition IsObjectStringType(Register heap_object, 408e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register map, 409e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register instance_type); 410e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check if a heap object's type is in the JSObject range, not including 4127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // JSFunction. The object's map will be loaded in the map register. 4137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Any or all of the three registers may be the same. 4147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // The contents of the scratch register will always be overwritten. 4157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch void IsObjectJSObjectType(Register heap_object, 4167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register map, 4177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch, 4187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label* fail); 4197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 4207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // The contents of the scratch register will be overwritten. 4217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch void IsInstanceJSObjectType(Register map, Register scratch, Label* fail); 4227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // FCmp is similar to integer cmp, but requires unsigned 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // jcc instructions (je, ja, jae, jb, jbe, je, and jz). 425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void FCmp(); 426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 427257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void ClampUint8(Register reg); 428257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 429257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void ClampDoubleToUint8(XMMRegister input_reg, 430257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch XMMRegister scratch_reg, 431257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register result_reg); 432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 433257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 434e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Smi tagging support. 435e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void SmiTag(Register reg) { 43669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 43769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTagSize == 1); 4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(reg, reg); 439e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 440e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void SmiUntag(Register reg) { 441e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke sar(reg, kSmiTagSize); 442e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 443e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 444756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Modifies the register even if it does not contain a Smi! 445756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick void SmiUntag(Register reg, Label* is_smi) { 44669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTagSize == 1); 447756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick sar(reg, kSmiTagSize); 44869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 449756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick j(not_carry, is_smi); 450756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 451756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 4521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Jump the register contains a smi. 4533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch inline void JumpIfSmi(Register value, 4543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label* smi_label, 4553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label::Distance distance = Label::kFar) { 4563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch test(value, Immediate(kSmiTagMask)); 4573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch j(zero, smi_label, distance); 4583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 4593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Jump if the operand is a smi. 4603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch inline void JumpIfSmi(Operand value, 4613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label* smi_label, 4623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label::Distance distance = Label::kFar) { 4631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block test(value, Immediate(kSmiTagMask)); 4643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch j(zero, smi_label, distance); 4651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 4661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Jump if register contain a non-smi. 4673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch inline void JumpIfNotSmi(Register value, 4683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label* not_smi_label, 4693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label::Distance distance = Label::kFar) { 4701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block test(value, Immediate(kSmiTagMask)); 4713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch j(not_zero, not_smi_label, distance); 4721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 4731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void LoadInstanceDescriptors(Register map, Register descriptors); 475756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 4760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen void LoadPowerOf2(XMMRegister dst, Register scratch, int power); 4770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 478402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Abort execution if argument is not a number. Used in debug code. 4796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void AbortIfNotNumber(Register object); 4806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 4816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Abort execution if argument is not a smi. Used in debug code. 4826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void AbortIfNotSmi(Register object); 483402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 484756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Abort execution if argument is a smi. Used in debug code. 485756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick void AbortIfSmi(Register object); 486756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 48780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Abort execution if argument is a string. Used in debug code. 48880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen void AbortIfNotString(Register object); 48980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exception handling 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Push a new try handler and link it into try handler chain. 4943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void PushTryHandler(StackHandler::Kind kind, int handler_index); 495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 496e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Unlink the stack handler on top of the stack from the try handler chain. 497e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void PopTryHandler(); 498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Throw to the top handler in the try hander chain. 500e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void Throw(Register value); 501e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Throw past all JS frames to the top JS entry frame. 5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void ThrowUncatchable(Register value); 504e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Inline caching support 507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Generate code for checking access rights - used for security checks 509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // on access to global objects across environments. The holder register 510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is left untouched, but the scratch register is clobbered. 511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void CheckAccessGlobalProxy(Register holder_reg, 512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss); 514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 515c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch void GetNumberHash(Register r0, Register scratch); 516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void LoadFromNumberDictionary(Label* miss, 5183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register elements, 5193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register key, 5203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register r0, 5213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register r1, 5223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register r2, 5233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register result); 5243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 5253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocation support 528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocate an object in new space. If the new space is exhausted control 530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // continues at the gc_required label. The allocated object is returned in 531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result and end of the new object is returned in result_end. The register 532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scratch can be passed as no_reg in which case an additional object 533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // reference will be added to the reloc info. The returned pointers in result 534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // and result_end have not yet been tagged as heap objects. If 535d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // result_contains_top_on_entry is true the content of result is known to be 536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the allocation top on entry (could be result_end from a previous call to 537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // AllocateInNewSpace). If result_contains_top_on_entry is true scratch 538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // should be no_reg as it is never used. 539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void AllocateInNewSpace(int object_size, 540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result_end, 542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required, 544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags); 545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void AllocateInNewSpace(int header_size, 547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ScaleFactor element_size, 548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register element_count, 549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result_end, 551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required, 553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags); 554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void AllocateInNewSpace(Register object_size, 556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result_end, 558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required, 560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags); 561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Undo allocation in new space. The object passed and objects allocated after 563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // it will no longer be allocated. Make sure that no pointers are left to the 564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // object(s) no longer allocated as they would be invalid when allocation is 565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // un-done. 566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void UndoAllocationInNewSpace(Register object); 567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Allocate a heap number in new space with undefined value. The 5693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // register scratch2 can be passed as no_reg; the others must be 5703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // valid registers. Returns tagged pointer in result register, or 5713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // jumps to gc_required if new space is full. 5723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void AllocateHeapNumber(Register result, 5733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register scratch1, 5743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register scratch2, 5753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label* gc_required); 5763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 577d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Allocate a sequential string. All the header fields of the string object 578d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // are initialized. 579d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void AllocateTwoByteString(Register result, 580d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register length, 581d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch1, 582d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch2, 583d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch3, 584d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label* gc_required); 585d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void AllocateAsciiString(Register result, 586d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register length, 587d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch1, 588d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch2, 589d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch3, 590d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label* gc_required); 5919ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick void AllocateAsciiString(Register result, 5929ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick int length, 5939ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick Register scratch1, 5949ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick Register scratch2, 5959ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick Label* gc_required); 596d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 597d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Allocate a raw cons string object. Only the map field of the result is 598d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // initialized. 599589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch void AllocateTwoByteConsString(Register result, 600d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch1, 601d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch2, 602d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label* gc_required); 603d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void AllocateAsciiConsString(Register result, 604d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch1, 605d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch2, 606d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label* gc_required); 607d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 60869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Allocate a raw sliced string object. Only the map field of the result is 60969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // initialized. 610589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch void AllocateTwoByteSlicedString(Register result, 61169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Register scratch1, 61269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Register scratch2, 61369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Label* gc_required); 61469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch void AllocateAsciiSlicedString(Register result, 61569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Register scratch1, 61669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Register scratch2, 61769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Label* gc_required); 61869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 619b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Copy memory, byte-by-byte, from source to destination. Not optimized for 620b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // long or aligned copies. 621b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // The contents of index and scratch are destroyed. 622b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch void CopyBytes(Register source, 623b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register destination, 624b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register length, 625b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register scratch); 6268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 6273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Initialize fields with filler values. Fields starting at |start_offset| 6283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // not including end_offset are overwritten with the value in |filler|. At 6293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the end the loop, |start_offset| takes the value of |end_offset|. 6303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void InitializeFieldsWithFiller(Register start_offset, 6313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register end_offset, 6323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register filler); 6333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Support functions. 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check a boolean-bit of a Smi field. 6383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void BooleanBitTest(Register object, int field_offset, int bit_index); 6393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if result is zero and op is negative. 641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void NegativeZeroTest(Register result, Register op, Label* then_label); 642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if result is zero and any of op1 and op2 are negative. 644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Register scratch is destroyed, and it must be different from op2. 645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void NegativeZeroTest(Register result, Register op1, Register op2, 646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, Label* then_label); 647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Try to get function prototype of a function and puts the value in 649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the result register. Checks that the function really is a 650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // function and jumps to the miss label if the fast checks fail. The 651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // function register will be untouched; the other registers may be 652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // clobbered. 653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void TryGetFunctionPrototype(Register function, 654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 6563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss, 6573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool miss_on_bound_function = false); 658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Generates code for reporting that an illegal operation has 660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // occurred. 661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void IllegalOperation(int num_arguments); 662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 66380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Picks out an array index from the hash field. 66480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Register use: 66580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // hash - holds the index's hash. Clobbered. 66680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // index - holds the overwritten index on exit. 66780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen void IndexFromHash(Register hash, Register index); 66880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Runtime calls 671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 672e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Call a code stub. Generate the code if necessary. 673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void CallStub(CodeStub* stub, unsigned ast_id = kNoASTId); 674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 675e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Tail call a code stub (jump). Generate the code if necessary. 676d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void TailCallStub(CodeStub* stub); 677d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return from a code stub after popping its arguments. 679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void StubReturn(int argc); 680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call a runtime routine. 68244f0eee88ff00398ff7f715fab053374d808c90dSteve Block void CallRuntime(const Runtime::Function* f, int num_arguments); 683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void CallRuntimeSaveDoubles(Runtime::FunctionId id); 684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Convenience function: Same as above, but takes the fid instead. 686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void CallRuntime(Runtime::FunctionId id, int num_arguments); 687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 688bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Convenience function: call an external reference. 689bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch void CallExternalReference(ExternalReference ref, int num_arguments); 690bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Tail call of a runtime routine (jump). 6926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Like JumpToExternalReference, but also takes care of passing the number 6936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // of parameters. 6946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void TailCallExternalReference(const ExternalReference& ext, 6956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int num_arguments, 6966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int result_size); 6976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 6986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Convenience function: tail call a runtime routine (jump). 6996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void TailCallRuntime(Runtime::FunctionId fid, 700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int num_arguments, 701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result_size); 702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Before calling a C-function from generated code, align arguments on stack. 7046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // After aligning the frame, arguments must be stored in esp[0], esp[4], 7056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // etc., not pushed. The argument count assumes all arguments are word sized. 7066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Some compilers/platforms require the stack to be aligned when calling 7076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // C++ code. 7086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Needs a scratch register to do some arithmetic. This register will be 7096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // trashed. 7106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void PrepareCallCFunction(int num_arguments, Register scratch); 7116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 7126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Calls a C function and cleans up the space for arguments allocated 7136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // by PrepareCallCFunction. The called function is not allowed to trigger a 7146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // garbage collection, since that might move the code and invalidate the 7156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // return address (unless this is somehow accounted for by the called 7166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // function). 7176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void CallCFunction(ExternalReference function, int num_arguments); 7186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void CallCFunction(Register function, int num_arguments); 7196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 7205913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // Prepares stack to put arguments (aligns and so on). Reserves 7215913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // space for return value if needed (assumes the return value is a handle). 7223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Arguments must be stored in ApiParameterOperand(0), ApiParameterOperand(1) 7233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // etc. Saves context (esi). If space was reserved for return value then 7243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // stores the pointer to the reserved slot into esi. 7253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void PrepareCallApiFunction(int argc); 726d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 7273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Calls an API function. Allocates HandleScope, extracts returned value 7283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // from handle and propagates exceptions. Clobbers ebx, edi and 7293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // caller-save registers. Restores context. On return removes 7303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // stack_space * kPointerSize (GCed). 7313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CallApiFunctionAndReturn(Address function_address, int stack_space); 732e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to a runtime routine. 7346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void JumpToExternalReference(const ExternalReference& ext); 735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Utilities 738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Ret(); 740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Return and drop arguments from stack, where the number of arguments 7421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // may be bigger than 2^16 - 1. Requires a scratch register. 7431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void Ret(int bytes_dropped, Register scratch); 7441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 745e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Emit code to discard a non-negative number of pointer-sized elements 746e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // from the stack, clobbering only the esp register. 747e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void Drop(int element_count); 748e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 749e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void Call(Label* target) { call(target); } 750e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Emit call to the code we are currently generating. 752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void CallSelf() { 753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Code> self(reinterpret_cast<Code**>(CodeObject().location())); 754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch call(self, RelocInfo::CODE_TARGET); 755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Move if the registers are not identical. 7580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen void Move(Register target, Register source); 7590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 7603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Push a handle value. 7613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void Push(Handle<Object> handle) { push(Immediate(handle)); } 7623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Handle<Object> CodeObject() { 7648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!code_object_.is_null()); 7658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return code_object_; 7668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // StatsCounter support 771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SetCounter(StatsCounter* counter, int value); 773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void IncrementCounter(StatsCounter* counter, int value); 774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void DecrementCounter(StatsCounter* counter, int value); 775d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke void IncrementCounter(Condition cc, StatsCounter* counter, int value); 776d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke void DecrementCounter(Condition cc, StatsCounter* counter, int value); 777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Debugging 781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calls Abort(msg) if the condition cc is not satisfied. 783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Use --debug_code to enable. 784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Assert(Condition cc, const char* msg); 785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 786756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick void AssertFastElements(Register elements); 787756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Like Assert(), but always enabled. 789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Check(Condition cc, const char* msg); 790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Print a message to stdout and abort execution. 792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Abort(const char* msg); 793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the stack is aligned. 7956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void CheckStackAlignment(); 7966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Verify restrictions about code generated in stubs. 798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void set_generating_stub(bool value) { generating_stub_ = value; } 799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool generating_stub() { return generating_stub_; } 800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; } 801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool allow_stub_calls() { return allow_stub_calls_; } 8023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void set_has_frame(bool value) { has_frame_ = value; } 8033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool has_frame() { return has_frame_; } 8043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch inline bool AllowThisStubCall(CodeStub* stub); 805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 806d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // --------------------------------------------------------------------------- 807d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // String utilities. 808d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 8093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check whether the instance type represents a flat ASCII string. Jump to the 810402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // label if not. If the instance type can be scratched specify same register 811402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // for both instance type and scratch. 812402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu void JumpIfInstanceTypeIsNotSequentialAscii(Register instance_type, 813402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register scratch, 8146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label* on_not_flat_ascii_string); 815402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 816d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Checks if both objects are sequential ASCII strings, and jumps to label 817d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // if either is not. 818d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke void JumpIfNotBothSequentialAsciiStrings(Register object1, 819d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Register object2, 820d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Register scratch1, 821d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Register scratch2, 8226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label* on_not_flat_ascii_strings); 823d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 8248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static int SafepointRegisterStackIndex(Register reg) { 8258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return SafepointRegisterStackIndex(reg.code()); 8268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 8278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 8283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Activation support. 8293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void EnterFrame(StackFrame::Type type); 8303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void LeaveFrame(StackFrame::Type type); 8313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Expects object in eax and returns map with validated enum cache 8333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // in eax. Assumes that any other register can be used as a scratch. 8343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CheckEnumCache(Label* call_runtime); 8353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool generating_stub_; 838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool allow_stub_calls_; 8393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool has_frame_; 8403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // This handle will be patched with the code object on installation. 8413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Handle<Object> code_object_; 842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Helper functions for generating invokes. 844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void InvokePrologue(const ParameterCount& expected, 845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> code_constant, 847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const Operand& code_operand, 848257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* done, 8493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool* definitely_mismatches, 850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InvokeFlag flag, 8513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance done_distance, 852257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const CallWrapper& call_wrapper = NullCallWrapper(), 853257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKind call_kind = CALL_AS_METHOD); 854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 85580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen void EnterExitFramePrologue(); 856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void EnterExitFrameEpilogue(int argc, bool save_doubles); 857d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 8588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang void LeaveExitFrameEpilogue(); 8598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocation support helpers. 861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void LoadAllocationTopHelper(Register result, 862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags); 864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void UpdateAllocationTopHelper(Register result_end, Register scratch); 865e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 866e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Helper for PopHandleScope. Allowed to perform a GC and returns 867e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // NULL if gc_allowed. Does not perform a GC if !gc_allowed, and 868e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // possibly returns a failure object indicating an allocation failure. 8695913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck MUST_USE_RESULT MaybeObject* PopHandleScopeHelper(Register saved, 8705913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Register scratch, 8715913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck bool gc_allowed); 872e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 8733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Helper for implementing JumpIfNotInNewSpace and JumpIfInNewSpace. 8743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void InNewSpace(Register object, 8753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 8763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition cc, 8773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* condition_met, 8783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance condition_met_distance = Label::kFar); 8793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Helper for finding the mark bits for an address. Afterwards, the 8813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // bitmap register points at the word with the mark bits and the mask 8823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the position of the first bit. Uses ecx as scratch and leaves addr_reg 8833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // unchanged. 8843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch inline void GetMarkBits(Register addr_reg, 8853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register bitmap_reg, 8863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register mask_reg); 8873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Helper for throwing exceptions. Compute a handler address and jump to 8893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // it. See the implementation for register usage. 8903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void JumpToHandlerEntry(); 891e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 892e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Compute memory operands for safepoint stack slots. 893e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Operand SafepointRegisterSlot(Register reg); 894e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch static int SafepointRegisterStackIndex(int reg_code); 895e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 896e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Needs access to SafepointRegisterStackIndex for optimized frame 897e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // traversal. 898e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch friend class OptimizedFrame; 899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The code patcher is used to patch (typically) small parts of code e.g. for 903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// debugging and other types of instrumentation. When using the code patcher 904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the exact number of bytes specified must be emitted. Is not legal to emit 905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// relocation information. If any of these constraints are violated it causes 906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// an assertion. 907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass CodePatcher { 908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CodePatcher(byte* address, int size); 910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual ~CodePatcher(); 911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Macro assembler to emit code. 913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MacroAssembler* masm() { return &masm_; } 914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* address_; // The address of the code being patched. 917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int size_; // Number of bytes of the expected patch size. 918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MacroAssembler masm_; // Macro assembler used to generate the code. 919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------- 923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Static helper functions. 924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Generate an Operand for loading a field from an object. 9263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochinline Operand FieldOperand(Register object, int offset) { 927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Operand(object, offset - kHeapObjectTag); 928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Generate an Operand for loading an indexed field from an object. 9323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochinline Operand FieldOperand(Register object, 9333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register index, 9343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ScaleFactor scale, 9353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int offset) { 936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Operand(object, index, scale, offset - kHeapObjectTag); 937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 9403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochinline Operand ContextOperand(Register context, int index) { 9418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang return Operand(context, Context::SlotOffset(index)); 9428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang} 9438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 9448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 9453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochinline Operand GlobalObjectOperand() { 9468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang return ContextOperand(esi, Context::GLOBAL_INDEX); 9478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang} 9488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 9498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 9505913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck// Generates an Operand for saving parameters after PrepareCallApiFunction. 9515913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckOperand ApiParameterOperand(int index); 9525913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck 953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef GENERATED_CODE_COVERAGE 955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockextern void LogGeneratedCodeCoverage(const char* file_line); 956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define CODE_COVERAGE_STRINGIFY(x) #x 957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x) 958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__) 959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define ACCESS_MASM(masm) { \ 960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* ia32_coverage_function = \ 961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<byte*>(FUNCTION_ADDR(LogGeneratedCodeCoverage)); \ 962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->pushfd(); \ 963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->pushad(); \ 964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->push(Immediate(reinterpret_cast<int>(&__FILE_LINE__))); \ 965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->call(ia32_coverage_function, RelocInfo::RUNTIME_ENTRY); \ 966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->pop(eax); \ 967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->popad(); \ 968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->popfd(); \ 969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } \ 970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm-> 971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else 972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define ACCESS_MASM(masm) masm-> 973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // V8_IA32_MACRO_ASSEMBLER_IA32_H_ 979