macro-assembler-x64.cc revision e46be819fca9468a0cd4e74859ce0f778eb8ca60
1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2009 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#include "v8.h" 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "bootstrapper.h" 31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "codegen-inl.h" 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "assembler-x64.h" 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "macro-assembler-x64.h" 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "serialize.h" 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "debug.h" 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockMacroAssembler::MacroAssembler(void* buffer, int size) 413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block : Assembler(buffer, size), 423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block unresolved_(0), 433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block generating_stub_(false), 443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block allow_stub_calls_(true), 453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block code_object_(Heap::undefined_value()) { 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index) { 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(destination, Operand(r13, index << kPointerSizeLog2)); 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::PushRoot(Heap::RootListIndex index) { 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Operand(r13, index << kPointerSizeLog2)); 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) { 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(with, Operand(r13, index << kPointerSizeLog2)); 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::CompareRoot(Operand with, Heap::RootListIndex index) { 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadRoot(kScratchRegister, index); 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(with, kScratchRegister); 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 70d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::StackLimitCheck(Label* on_stack_overflow) { 71d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block CompareRoot(rsp, Heap::kStackLimitRootIndex); 72d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block j(below, on_stack_overflow); 73d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 74d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 75d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void RecordWriteHelper(MacroAssembler* masm, 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register object, 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register addr, 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch) { 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label fast; 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute the page start address from the heap object pointer, and reuse 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the 'object' register for it. 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_int32(~Page::kPageAlignmentMask)); 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->and_(object, 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(static_cast<int32_t>(~Page::kPageAlignmentMask))); 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register page_start = object; 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute the bit addr in the remembered set/index of the pointer in the 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // page. Reuse 'addr' as pointer_offset. 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->subq(addr, page_start); 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->shr(addr, Immediate(kPointerSizeLog2)); 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register pointer_offset = addr; 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the bit offset lies beyond the normal remembered set range, it is in 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the extra remembered set area of a large object. 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->cmpq(pointer_offset, Immediate(Page::kPageSize / kPointerSize)); 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->j(less, &fast); 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Adjust 'page_start' so that addressing using 'pointer_offset' hits the 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // extra remembered set after the large object. 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the array length into 'scratch'. 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->movl(scratch, 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand(page_start, 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Page::kObjectStartOffset + FixedArray::kLengthOffset)); 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register array_length = scratch; 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Extra remembered set starts right after the large object (a FixedArray), at 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // page_start + kObjectStartOffset + objectSize 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // where objectSize is FixedArray::kHeaderSize + kPointerSize * array_length. 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Add the delta between the end of the normal RSet and the start of the 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // extra RSet to 'page_start', so that addressing the bit using 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 'pointer_offset' hits the extra RSet words. 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->lea(page_start, 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand(page_start, array_length, times_pointer_size, 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Page::kObjectStartOffset + FixedArray::kHeaderSize 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block - Page::kRSetEndOffset)); 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // NOTE: For now, we use the bit-test-and-set (bts) x86 instruction 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to limit code size. We should probably evaluate this decision by 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // measuring the performance of an equivalent implementation using 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // "simpler" instructions 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->bind(&fast); 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->bts(Operand(page_start, Page::kRSetOffset), pointer_offset); 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass RecordWriteStub : public CodeStub { 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RecordWriteStub(Register object, Register addr, Register scratch) 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : object_(object), addr_(addr), scratch_(scratch) { } 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Generate(MacroAssembler* masm); 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register object_; 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register addr_; 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch_; 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Print() { 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF("RecordWriteStub (object reg %d), (addr reg %d), (scratch reg %d)\n", 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block object_.code(), addr_.code(), scratch_.code()); 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Minor key encoding in 12 bits of three registers (object, address and 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scratch) OOOOAAAASSSS. 1503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block class ScratchBits : public BitField<uint32_t, 0, 4> {}; 1513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block class AddressBits : public BitField<uint32_t, 4, 4> {}; 1523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block class ObjectBits : public BitField<uint32_t, 8, 4> {}; 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Major MajorKey() { return RecordWrite; } 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int MinorKey() { 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Encode the registers. 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return ObjectBits::encode(object_.code()) | 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddressBits::encode(addr_.code()) | 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ScratchBits::encode(scratch_.code()); 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RecordWriteStub::Generate(MacroAssembler* masm) { 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RecordWriteHelper(masm, object_, addr_, scratch_); 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->ret(0); 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Set the remembered set bit for [object+offset]. 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// object is the object being stored into, value is the object being stored. 1733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// If offset is zero, then the smi_index register contains the array index into 1743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// the elements array represented as a smi. Otherwise it can be used as a 1753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// scratch register. 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// All registers are clobbered by the operation. 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::RecordWrite(Register object, 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset, 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register value, 1803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register smi_index) { 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // First, check if a remembered set write is even needed. The tests below 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // catch stores of Smis and stores into young gen (which does not have space 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // for the remembered set bits. 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label done; 1853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block JumpIfSmi(value, &done); 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block RecordWriteNonSmi(object, offset, value, smi_index); 1883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bind(&done); 1893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 1903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::RecordWriteNonSmi(Register object, 1933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int offset, 1943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register scratch, 1953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register smi_index) { 1963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label done; 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Test that the object address is not in the new space. We cannot 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // set remembered set bits in the new space. 1993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(scratch, object); 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_int32(static_cast<int64_t>(Heap::NewSpaceMask()))); 2013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block and_(scratch, Immediate(static_cast<int32_t>(Heap::NewSpaceMask()))); 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, ExternalReference::new_space_start()); 2033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block cmpq(scratch, kScratchRegister); 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(equal, &done); 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((offset > 0) && (offset < Page::kMaxHeapObjectSize)) { 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute the bit offset in the remembered set, leave it in 'value'. 2083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block lea(scratch, Operand(object, offset)); 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_int32(Page::kPageAlignmentMask)); 2103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block and_(scratch, Immediate(static_cast<int32_t>(Page::kPageAlignmentMask))); 2113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shr(scratch, Immediate(kObjectAlignmentBits)); 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute the page address from the heap object pointer, leave it in 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 'object' (immediate value is sign extended). 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block and_(object, Immediate(~Page::kPageAlignmentMask)); 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // NOTE: For now, we use the bit-test-and-set (bts) x86 instruction 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to limit code size. We should probably evaluate this decision by 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // measuring the performance of an equivalent implementation using 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // "simpler" instructions 2213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bts(Operand(object, Page::kRSetOffset), scratch); 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 2233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register dst = smi_index; 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (offset != 0) { 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lea(dst, Operand(object, offset)); 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // array access: calculate the destination address in the same manner as 2283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // KeyedStoreIC::GenerateGeneric. 2293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiIndex index = SmiToIndex(smi_index, smi_index, kPointerSizeLog2); 2303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block lea(dst, Operand(object, 2313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block index.reg, 2323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block index.scale, 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FixedArray::kHeaderSize - kHeapObjectTag)); 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If we are already generating a shared stub, not inlining the 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // record write code isn't going to save us any memory. 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (generating_stub()) { 2383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block RecordWriteHelper(this, object, dst, scratch); 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 2403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block RecordWriteStub stub(object, dst, scratch); 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CallStub(&stub); 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&done); 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Assert(Condition cc, const char* msg) { 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_debug_code) Check(cc, msg); 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Check(Condition cc, const char* msg) { 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label L; 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(cc, &L); 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Abort(msg); 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // will not return here 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&L); 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::NegativeZeroTest(Register result, 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register op, 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* then_label) { 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label ok; 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block testl(result, result); 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(not_zero, &ok); 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block testl(op, op); 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(sign, then_label); 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&ok); 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Abort(const char* msg) { 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We want to pass the msg string like a smi to avoid GC 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // problems, however msg is not guaranteed to be aligned 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // properly. Instead, we pass an aligned pointer that is 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // a proper v8 smi, but also pass the alignment difference 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // from the real pointer as a smi. 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block intptr_t p1 = reinterpret_cast<intptr_t>(msg); 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block intptr_t p0 = (p1 & ~kSmiTagMask) + kSmiTag; 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Note: p0 might not be a valid Smi *value*, but it has a valid Smi tag. 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(reinterpret_cast<Object*>(p0)->IsSmi()); 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (msg != NULL) { 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RecordComment("Abort message: "); 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RecordComment(msg); 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 291d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Disable stub call restrictions to always allow calls to abort. 292d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block set_allow_stub_calls(true); 293d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(rax); 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, p0, RelocInfo::NONE); 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(kScratchRegister); 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, 298d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(p1 - p0))), 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::NONE); 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(kScratchRegister); 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CallRuntime(Runtime::kAbort, 2); 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // will not return here 303d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int3(); 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CallStub(CodeStub* stub) { 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(allow_stub_calls()); // calls are not allowed in some stubs 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Call(stub->GetCode(), RelocInfo::CODE_TARGET); 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 313e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::TailCallStub(CodeStub* stub) { 314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(allow_stub_calls()); // calls are not allowed in some stubs 315e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Jump(stub->GetCode(), RelocInfo::CODE_TARGET); 316e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 317e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 318e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::StubReturn(int argc) { 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(argc >= 1 && generating_stub()); 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ret((argc - 1) * kPointerSize); 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::IllegalOperation(int num_arguments) { 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (num_arguments > 0) { 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addq(rsp, Immediate(num_arguments * kPointerSize)); 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadRoot(rax, Heap::kUndefinedValueRootIndex); 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CallRuntime(Runtime::FunctionId id, int num_arguments) { 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CallRuntime(Runtime::FunctionForId(id), num_arguments); 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) { 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the expected number of arguments of the runtime function is 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // constant, we check that the actual number of arguments match the 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // expectation. 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (f->nargs >= 0 && f->nargs != num_arguments) { 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block IllegalOperation(num_arguments); 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Runtime::FunctionId function_id = 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static_cast<Runtime::FunctionId>(f->stub_id); 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RuntimeStub stub(function_id, num_arguments); 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CallStub(&stub); 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::TailCallRuntime(ExternalReference const& ext, 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int num_arguments, 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result_size) { 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rsp[0] : return address 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rsp[8] : argument num_arguments - 1 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ... 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rsp[8 * num_arguments] : argument 0 (receiver) 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // TODO(1236192): Most runtime routines don't need the number of 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // arguments passed in because it is constant. At some point we 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // should remove this need and make the runtime routine entry code 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // smarter. 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rax, Immediate(num_arguments)); 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JumpToRuntime(ext, result_size); 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::JumpToRuntime(const ExternalReference& ext, 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result_size) { 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the entry point and jump to the C entry runtime stub. 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rbx, ext); 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CEntryStub ces(result_size); 3783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block jmp(ces.GetCode(), RelocInfo::CODE_TARGET); 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) { 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool resolved; 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> code = ResolveBuiltin(id, &resolved); 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* name = Builtins::GetName(id); 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int argc = Builtins::GetArgumentsCount(id); 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(target, code, RelocInfo::EMBEDDED_OBJECT); 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!resolved) { 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint32_t flags = 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Bootstrapper::FixupFlagsArgumentsCount::encode(argc) | 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Bootstrapper::FixupFlagsUseCodeObject::encode(true); 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Unresolved entry = { pc_offset() - sizeof(intptr_t), flags, name }; 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block unresolved_.Add(entry); 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addq(target, Immediate(Code::kHeaderSize - kHeapObjectTag)); 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockHandle<Code> MacroAssembler::ResolveBuiltin(Builtins::JavaScript id, 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool* resolved) { 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Move the builtin function into the temporary function slot by 403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // reading it from the builtins object. NOTE: We should be able to 404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // reduce this to two instructions by putting the function table in 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the global object instead of the "builtins" object and by using a 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // real register for the function. 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rdx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rdx, FieldOperand(rdx, GlobalObject::kBuiltinsOffset)); 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int builtins_offset = 410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSBuiltinsObject::kJSBuiltinsOffset + (id * kPointerSize); 411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rdi, FieldOperand(rdx, builtins_offset)); 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Builtins::GetCode(id, resolved); 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Set(Register dst, int64_t x) { 418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (x == 0) { 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block xor_(dst, dst); 420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (is_int32(x)) { 421d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block movq(dst, Immediate(static_cast<int32_t>(x))); 422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (is_uint32(x)) { 423d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block movl(dst, Immediate(static_cast<uint32_t>(x))); 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(dst, x, RelocInfo::NONE); 426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Set(const Operand& dst, int64_t x) { 431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (x == 0) { 432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block xor_(kScratchRegister, kScratchRegister); 433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(dst, kScratchRegister); 434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (is_int32(x)) { 435d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block movq(dst, Immediate(static_cast<int32_t>(x))); 436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (is_uint32(x)) { 437d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block movl(dst, Immediate(static_cast<uint32_t>(x))); 438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, x, RelocInfo::NONE); 440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(dst, kScratchRegister); 441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ---------------------------------------------------------------------------- 445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Smi tagging, untagging and tag detection. 446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockstatic int kSmiShift = kSmiTagSize + kSmiShiftSize; 448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Integer32ToSmi(Register dst, Register src) { 450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, kSmiTag); 4513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src)) { 4523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movl(dst, src); 453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 4543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(kSmiShift)); 455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Integer32ToSmi(Register dst, 459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_overflow) { 461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, kSmiTag); 4623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // 32-bit integer always fits in a long smi. 463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!dst.is(src)) { 464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movl(dst, src); 465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 4663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(kSmiShift)); 467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::Integer64PlusConstantToSmi(Register dst, 4713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register src, 4723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int constant) { 4733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (dst.is(src)) { 4743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block addq(dst, Immediate(constant)); 4753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 4763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block lea(dst, Operand(src, constant)); 4773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 4783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(kSmiShift)); 479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiToInteger32(Register dst, Register src) { 483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, kSmiTag); 484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!dst.is(src)) { 4853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 4873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shr(dst, Immediate(kSmiShift)); 488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiToInteger64(Register dst, Register src) { 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, kSmiTag); 4933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src)) { 4943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 4963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block sar(dst, Immediate(kSmiShift)); 497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiTest(Register src) { 5013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testq(src, src); 502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(Register dst, Register src) { 5063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block cmpq(dst, src); 507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(Register dst, Smi* src) { 5113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 5123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (src->value() == 0) { 5133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testq(dst, dst); 5143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 5153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(kScratchRegister, src); 5163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block cmpq(dst, kScratchRegister); 517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(const Operand& dst, Register src) { 5223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block cmpq(dst, src); 523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(const Operand& dst, Smi* src) { 5273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (src->value() == 0) { 5283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Only tagged long smi to have 32-bit representation. 5293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block cmpq(dst, Immediate(0)); 5303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 5313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(kScratchRegister, src); 5323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block cmpq(dst, kScratchRegister); 5333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::PositiveSmiTimesPowerOfTwoToInteger64(Register dst, 5383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register src, 5393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int power) { 5403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(power >= 0); 5413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(power < 64); 5423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (power == 0) { 5433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiToInteger64(dst, src); 5443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block return; 5453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 5463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src)) { 5473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 5483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 5493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (power < kSmiShift) { 5503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block sar(dst, Immediate(kSmiShift - power)); 5513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (power > kSmiShift) { 5523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(power - kSmiShift)); 5533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockCondition MacroAssembler::CheckSmi(Register src) { 558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, kSmiTag); 559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block testb(src, Immediate(kSmiTagMask)); 5603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block return zero; 561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCondition MacroAssembler::CheckPositiveSmi(Register src) { 565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, kSmiTag); 5663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(kScratchRegister, src); 5673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block rol(kScratchRegister, Immediate(1)); 5683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testl(kScratchRegister, Immediate(0x03)); 569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return zero; 570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCondition MacroAssembler::CheckBothSmi(Register first, Register second) { 574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (first.is(second)) { 575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return CheckSmi(first); 576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movl(kScratchRegister, first); 578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block orl(kScratchRegister, second); 5793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testb(kScratchRegister, Immediate(kSmiTagMask)); 5803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block return zero; 581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 584e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeCondition MacroAssembler::CheckEitherSmi(Register first, Register second) { 585e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (first.is(second)) { 586e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return CheckSmi(first); 587e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 588e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movl(kScratchRegister, first); 589e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke andl(kScratchRegister, second); 590e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke testb(kScratchRegister, Immediate(kSmiTagMask)); 591e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return zero; 592e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 593e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 594e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCondition MacroAssembler::CheckIsMinSmi(Register src) { 596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 5973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(kScratchRegister, src); 5983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block rol(kScratchRegister, Immediate(1)); 5993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block cmpq(kScratchRegister, Immediate(1)); 600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return equal; 601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockCondition MacroAssembler::CheckInteger32ValidSmiValue(Register src) { 6053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // A 32-bit integer value can always be converted to a smi. 6063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block return always; 607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockCondition MacroAssembler::CheckUInteger32ValidSmiValue(Register src) { 6113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // An unsigned 32-bit integer value is valid as long as the high bit 6123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // is not set. 6133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testq(src, Immediate(0x80000000)); 6143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block return zero; 615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiNeg(Register dst, Register src, Label* on_smi_result) { 6193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (dst.is(src)) { 6203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 6213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(kScratchRegister, src); 6223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block neg(dst); // Low 32 bits are retained as zero by negation. 6233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Test if result is zero or Smi::kMinValue. 6243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block cmpq(dst, kScratchRegister); 6253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(not_equal, on_smi_result); 6263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src, kScratchRegister); 6273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 6283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 6293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block neg(dst); 6303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block cmpq(dst, src); 6313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // If the result is zero or Smi::kMinValue, negation failed to create a smi. 6323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(not_equal, on_smi_result); 633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiAdd(Register dst, 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2, 640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smi_result) { 641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(src2)); 6423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (dst.is(src1)) { 6433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block addq(dst, src2); 644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label smi_result; 645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(no_overflow, &smi_result); 646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore src1. 6473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block subq(src1, src2); 648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block jmp(on_not_smi_result); 649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&smi_result); 6503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 6513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src1); 6523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block addq(dst, src2); 6533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(overflow, on_not_smi_result); 654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiSub(Register dst, 659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2, 661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smi_result) { 662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(src2)); 6633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (dst.is(src1)) { 6643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block subq(dst, src2); 665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label smi_result; 666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(no_overflow, &smi_result); 667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore src1. 6683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block addq(src1, src2); 669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block jmp(on_not_smi_result); 670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&smi_result); 6713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 6723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src1); 6733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block subq(dst, src2); 6743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(overflow, on_not_smi_result); 675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiMul(Register dst, 680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2, 682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smi_result) { 683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(src2)); 6843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 6853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src1.is(kScratchRegister)); 6863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src2.is(kScratchRegister)); 687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (dst.is(src1)) { 6893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label failure, zero_correct_result; 6903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(kScratchRegister, src1); // Create backup for later testing. 6913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiToInteger64(dst, src1); 6923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block imul(dst, src2); 6933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(overflow, &failure); 6943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 6953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check for negative zero result. If product is zero, and one 6963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // argument is negative, go to slow case. 6973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label correct_result; 6983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testq(dst, dst); 6993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(not_zero, &correct_result); 700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, kScratchRegister); 7023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block xor_(dst, src2); 7033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(positive, &zero_correct_result); // Result was positive zero. 704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bind(&failure); // Reused failure exit, restores src1. 7063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src1, kScratchRegister); 7073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block jmp(on_not_smi_result); 708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bind(&zero_correct_result); 7103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block xor_(dst, dst); 7113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bind(&correct_result); 7133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 7143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiToInteger64(dst, src1); 7153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block imul(dst, src2); 7163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(overflow, on_not_smi_result); 7173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check for negative zero result. If product is zero, and one 7183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // argument is negative, go to slow case. 7193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label correct_result; 7203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testq(dst, dst); 7213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(not_zero, &correct_result); 7223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // One of src1 and src2 is zero, the check whether the other is 7233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // negative. 7243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(kScratchRegister, src1); 7253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block xor_(kScratchRegister, src2); 7263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(negative, on_not_smi_result); 7273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bind(&correct_result); 7283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiTryAddConstant(Register dst, 733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 7343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Smi* constant, 735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smi_result) { 736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Does not assume that src is a smi. 7373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT_EQ(static_cast<int>(1), static_cast<int>(kSmiTagMask)); 738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, kSmiTag); 7393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 7403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src.is(kScratchRegister)); 741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block JumpIfNotSmi(src, on_not_smi_result); 7433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register tmp = (dst.is(src) ? kScratchRegister : dst); 7443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(tmp, constant); 7453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block addq(tmp, src); 7463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(overflow, on_not_smi_result); 7473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (dst.is(src)) { 7483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, tmp); 7493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 7503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 7513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiAddConstant(Register dst, Register src, Smi* constant) { 7543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (constant->value() == 0) { 7553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src)) { 7563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 7573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 7583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (dst.is(src)) { 7593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 7603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(kScratchRegister, constant); 7623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block addq(dst, kScratchRegister); 763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 7643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(dst, constant); 7653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block addq(dst, src); 766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiAddConstant(Register dst, 771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 7723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Smi* constant, 773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smi_result) { 7743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (constant->value() == 0) { 7753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src)) { 7763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 7783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (dst.is(src)) { 7793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 7803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(kScratchRegister, constant); 7823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block addq(dst, kScratchRegister); 7833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label result_ok; 7843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(no_overflow, &result_ok); 7853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block subq(dst, kScratchRegister); 7863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block jmp(on_not_smi_result); 7873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bind(&result_ok); 788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 7893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(dst, constant); 7903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block addq(dst, src); 7913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(overflow, on_not_smi_result); 7923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 7933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 7943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiSubConstant(Register dst, Register src, Smi* constant) { 7973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (constant->value() == 0) { 798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!dst.is(src)) { 7993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 8013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (dst.is(src)) { 8023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 8033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 8043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(kScratchRegister, constant); 8053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block subq(dst, kScratchRegister); 8063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 8073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Subtract by adding the negative, to do it in two operations. 8083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (constant->value() == Smi::kMinValue) { 8093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(kScratchRegister, constant); 8103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 8113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block subq(dst, kScratchRegister); 812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 8133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(dst, Smi::FromInt(-constant->value())); 8143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block addq(dst, src); 815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiSubConstant(Register dst, 821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 8223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Smi* constant, 823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smi_result) { 8243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (constant->value() == 0) { 8253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src)) { 8263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 8283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (dst.is(src)) { 8293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 8303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 8313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(kScratchRegister, constant); 8323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block subq(dst, kScratchRegister); 8333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label sub_success; 8343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(no_overflow, &sub_success); 8353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block addq(src, kScratchRegister); 8363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block jmp(on_not_smi_result); 8373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bind(&sub_success); 838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 8393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (constant->value() == Smi::kMinValue) { 8403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(kScratchRegister, constant); 8413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 8423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block subq(dst, kScratchRegister); 8433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(overflow, on_not_smi_result); 8443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 8453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(dst, Smi::FromInt(-(constant->value()))); 8463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block addq(dst, src); 8473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(overflow, on_not_smi_result); 8483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiDiv(Register dst, 854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2, 856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smi_result) { 8573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src1.is(kScratchRegister)); 8583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src2.is(kScratchRegister)); 8593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!src2.is(rax)); 861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!src2.is(rdx)); 862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!src1.is(rdx)); 863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for 0 divisor (result is +/-Infinity). 865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label positive_divisor; 8663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testq(src2, src2); 867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(zero, on_not_smi_result); 868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (src1.is(rax)) { 8703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(kScratchRegister, src1); 871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 8723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiToInteger32(rax, src1); 8733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // We need to rule out dividing Smi::kMinValue by -1, since that would 8743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // overflow in idiv and raise an exception. 8753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // We combine this with negative zero test (negative zero only happens 8763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // when dividing zero by a negative number). 8773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 8783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // We overshoot a little and go to slow case if we divide min-value 8793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // by any negative value, not just -1. 8803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label safe_div; 8813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testl(rax, Immediate(0x7fffffff)); 8823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(not_zero, &safe_div); 8833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testq(src2, src2); 8843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (src1.is(rax)) { 8853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(positive, &safe_div); 8863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src1, kScratchRegister); 8873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block jmp(on_not_smi_result); 8883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 8893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(negative, on_not_smi_result); 8903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 8913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bind(&safe_div); 892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiToInteger32(src2, src2); 8943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Sign extend src1 into edx:eax. 8953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block cdq(); 896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block idivl(src2); 8973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Integer32ToSmi(src2, src2); 898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the remainder is zero. 899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block testl(rdx, rdx); 9003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (src1.is(rax)) { 9013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label smi_result; 9023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(zero, &smi_result); 9033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src1, kScratchRegister); 9043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block jmp(on_not_smi_result); 9053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bind(&smi_result); 9063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 9073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(not_zero, on_not_smi_result); 9083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 9093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src1) && src1.is(rax)) { 9103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src1, kScratchRegister); 9113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Integer32ToSmi(dst, rax); 913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiMod(Register dst, 917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2, 919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smi_result) { 920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(kScratchRegister)); 921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!src1.is(kScratchRegister)); 922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!src2.is(kScratchRegister)); 923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!src2.is(rax)); 924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!src2.is(rdx)); 925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!src1.is(rdx)); 9263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src1.is(src2)); 927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testq(src2, src2); 929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(zero, on_not_smi_result); 930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (src1.is(rax)) { 9323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(kScratchRegister, src1); 9333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 9343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiToInteger32(rax, src1); 9353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiToInteger32(src2, src2); 9363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 9373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Test for the edge case of dividing Smi::kMinValue by -1 (will overflow). 9383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label safe_div; 9393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block cmpl(rax, Immediate(Smi::kMinValue)); 9403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(not_equal, &safe_div); 9413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block cmpl(src2, Immediate(-1)); 9423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(not_equal, &safe_div); 9433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Retag inputs and go slow case. 9443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Integer32ToSmi(src2, src2); 9453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (src1.is(rax)) { 9463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src1, kScratchRegister); 947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 9483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block jmp(on_not_smi_result); 9493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bind(&safe_div); 9503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Sign extend eax into edx:eax. 952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cdq(); 953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block idivl(src2); 9543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Restore smi tags on inputs. 9553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Integer32ToSmi(src2, src2); 956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (src1.is(rax)) { 9573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src1, kScratchRegister); 958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 9593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check for a negative zero result. If the result is zero, and the 9603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // dividend is negative, go slow to return a floating point negative zero. 9613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label smi_result; 9623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testl(rdx, rdx); 9633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(not_zero, &smi_result); 9643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testq(src1, src1); 965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(negative, on_not_smi_result); 9663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bind(&smi_result); 9673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Integer32ToSmi(dst, rdx); 968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiNot(Register dst, Register src) { 9723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 9733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src.is(kScratchRegister)); 9743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Set tag and padding bits before negating, so that they are zero afterwards. 9753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movl(kScratchRegister, Immediate(~0)); 976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (dst.is(src)) { 9773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block xor_(dst, kScratchRegister); 978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 9793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block lea(dst, Operand(src, kScratchRegister, times_1, 0)); 980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 9813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block not_(dst); 982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiAnd(Register dst, Register src1, Register src2) { 9863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(src2)); 987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!dst.is(src1)) { 9883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src1); 989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block and_(dst, src2); 991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiAndConstant(Register dst, Register src, Smi* constant) { 9953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (constant->value() == 0) { 9963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block xor_(dst, dst); 9973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (dst.is(src)) { 9983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 9993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(kScratchRegister, constant); 10003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block and_(dst, kScratchRegister); 10013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 10023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(dst, constant); 10033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block and_(dst, src); 1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiOr(Register dst, Register src1, Register src2) { 1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!dst.is(src1)) { 10103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src1); 1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block or_(dst, src2); 1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiOrConstant(Register dst, Register src, Smi* constant) { 10173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (dst.is(src)) { 10183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 10193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(kScratchRegister, constant); 10203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block or_(dst, kScratchRegister); 10213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 10223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(dst, constant); 10233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block or_(dst, src); 1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiXor(Register dst, Register src1, Register src2) { 1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!dst.is(src1)) { 10303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src1); 1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block xor_(dst, src2); 1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiXorConstant(Register dst, Register src, Smi* constant) { 10373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (dst.is(src)) { 10383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 10393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(kScratchRegister, constant); 10403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block xor_(dst, kScratchRegister); 10413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 10423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(dst, constant); 10433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block xor_(dst, src); 1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftArithmeticRightConstant(Register dst, 1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int shift_value) { 10513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(is_uint5(shift_value)); 1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (shift_value > 0) { 1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (dst.is(src)) { 10543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block sar(dst, Immediate(shift_value + kSmiShift)); 10553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(kSmiShift)); 1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNIMPLEMENTED(); // Not used. 1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftLogicalRightConstant(Register dst, 1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int shift_value, 1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smi_result) { 1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Logic right shift interprets its result as an *unsigned* number. 1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (dst.is(src)) { 1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNIMPLEMENTED(); // Not used. 1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 10713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 10723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (shift_value == 0) { 10733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testq(dst, dst); 1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(negative, on_not_smi_result); 1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 10763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shr(dst, Immediate(shift_value + kSmiShift)); 10773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(kSmiShift)); 1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftLeftConstant(Register dst, 1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int shift_value, 1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smi_result) { 10863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src)) { 10873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 10883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 10893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (shift_value > 0) { 10903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(shift_value)); 1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftLeft(Register dst, 1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2, 1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smi_result) { 1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(rcx)); 1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label result_ok; 11013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Untag shift amount. 11023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src1)) { 11033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src1); 1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 11053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiToInteger32(rcx, src2); 11063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Shift amount specified by lower 5 bits, not six as the shl opcode. 11073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block and_(rcx, Immediate(0x1f)); 1108d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block shl_cl(dst); 1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftLogicalRight(Register dst, 1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2, 1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smi_result) { 11163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 11173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src1.is(kScratchRegister)); 11183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src2.is(kScratchRegister)); 1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(rcx)); 1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label result_ok; 11213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (src1.is(rcx) || src2.is(rcx)) { 11223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(kScratchRegister, rcx); 11233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 11243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src1)) { 11253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src1); 11263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SmiToInteger32(rcx, src2); 11283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block orl(rcx, Immediate(kSmiShift)); 1129d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block shr_cl(dst); // Shift is rcx modulo 0x1f + 32. 11303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(kSmiShift)); 11313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testq(dst, dst); 11323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (src1.is(rcx) || src2.is(rcx)) { 11333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label positive_result; 11343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(positive, &positive_result); 11353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (src1.is(rcx)) { 11363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src1, kScratchRegister); 11373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 11383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src2, kScratchRegister); 11393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 11403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block jmp(on_not_smi_result); 11413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bind(&positive_result); 11423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 11433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(negative, on_not_smi_result); // src2 was zero and src1 negative. 1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftArithmeticRight(Register dst, 1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2) { 11513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 11523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src1.is(kScratchRegister)); 11533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src2.is(kScratchRegister)); 1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(rcx)); 11553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (src1.is(rcx)) { 11563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(kScratchRegister, src1); 11573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (src2.is(rcx)) { 11583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(kScratchRegister, src2); 11593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 11603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src1)) { 11613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src1); 11623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SmiToInteger32(rcx, src2); 11643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block orl(rcx, Immediate(kSmiShift)); 1165d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block sar_cl(dst); // Shift 32 + original rcx & 0x1f. 11663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(kSmiShift)); 11673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (src1.is(rcx)) { 11683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src1, kScratchRegister); 11693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (src2.is(rcx)) { 11703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src2, kScratchRegister); 11713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SelectNonSmi(Register dst, 1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2, 1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smis) { 11793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 11803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src1.is(kScratchRegister)); 11813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src2.is(kScratchRegister)); 1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(src1)); 1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(src2)); 1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Both operands must not be smis. 1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 11863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (allow_stub_calls()) { // Check contains a stub call. 11873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Condition not_both_smis = NegateCondition(CheckBothSmi(src1, src2)); 11883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Check(not_both_smis, "Both registers were smis in SelectNonSmi."); 11893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, kSmiTag); 1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, Smi::FromInt(0)); 11933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movl(kScratchRegister, Immediate(kSmiTagMask)); 1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block and_(kScratchRegister, src1); 1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block testl(kScratchRegister, src2); 11963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // If non-zero then both are smis. 1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(not_zero, on_not_smis); 1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 11993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Exactly one operand is a smi. 1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(1, static_cast<int>(kSmiTagMask)); 1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // kScratchRegister still holds src1 & kSmiTag, which is either zero or one. 1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block subq(kScratchRegister, Immediate(1)); 1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If src1 is a smi, then scratch register all 1s, else it is all 0s. 1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(dst, src1); 1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block xor_(dst, src2); 1206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block and_(dst, kScratchRegister); 1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If src1 is a smi, dst holds src1 ^ src2, else it is zero. 1208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block xor_(dst, src1); 12093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // If src1 is a smi, dst is src2, else it is src1, i.e., the non-smi. 1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockSmiIndex MacroAssembler::SmiToIndex(Register dst, 12133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register src, 12143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int shift) { 1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_uint6(shift)); 12163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // There is a possible optimization if shift is in the range 60-63, but that 12173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // will (and must) never happen. 12183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src)) { 12193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 12203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 12213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (shift < kSmiShift) { 12223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block sar(dst, Immediate(kSmiShift - shift)); 12233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 12243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(shift - kSmiShift)); 12253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return SmiIndex(dst, times_1); 1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockSmiIndex MacroAssembler::SmiToNegativeIndex(Register dst, 1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int shift) { 1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Register src holds a positive smi. 1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_uint6(shift)); 12343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src)) { 12353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block neg(dst); 12383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (shift < kSmiShift) { 12393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block sar(dst, Immediate(kSmiShift - shift)); 12403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 12413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(shift - kSmiShift)); 12423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return SmiIndex(dst, times_1); 1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfSmi(Register src, Label* on_smi) { 12483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT_EQ(0, kSmiTag); 12493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Condition smi = CheckSmi(src); 12503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(smi, on_smi); 12513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 12523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfNotSmi(Register src, Label* on_not_smi) { 12553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Condition smi = CheckSmi(src); 12563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(NegateCondition(smi), on_not_smi); 1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfNotPositiveSmi(Register src, 12613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label* on_not_positive_smi) { 12623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Condition positive_smi = CheckPositiveSmi(src); 12633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(NegateCondition(positive_smi), on_not_positive_smi); 12643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 12653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfSmiEqualsConstant(Register src, 12683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Smi* constant, 12693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label* on_equals) { 12703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiCompare(src, constant); 12713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(equal, on_equals); 12723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 12733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfNotValidSmiValue(Register src, Label* on_invalid) { 12763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Condition is_valid = CheckInteger32ValidSmiValue(src); 12773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(NegateCondition(is_valid), on_invalid); 12783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 12793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfUIntNotValidSmiValue(Register src, 12823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label* on_invalid) { 12833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Condition is_valid = CheckUInteger32ValidSmiValue(src); 12843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(NegateCondition(is_valid), on_invalid); 12853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 12863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfNotBothSmi(Register src1, Register src2, 12893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label* on_not_both_smi) { 12903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Condition both_smi = CheckBothSmi(src1, src2); 12913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(NegateCondition(both_smi), on_not_both_smi); 1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1295e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register first_object, 1296e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register second_object, 1297e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch1, 1298e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch2, 1299e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* on_fail) { 1300e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that both objects are not smis. 1301e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Condition either_smi = CheckEitherSmi(first_object, second_object); 1302e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke j(either_smi, on_fail); 1303e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1304e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Load instance type for both strings. 1305e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movq(scratch1, FieldOperand(first_object, HeapObject::kMapOffset)); 1306e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movq(scratch2, FieldOperand(second_object, HeapObject::kMapOffset)); 1307e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movzxbl(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset)); 1308e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movzxbl(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset)); 1309e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1310e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that both are flat ascii strings. 1311e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(kNotStringTag != 0); 1312e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const int kFlatAsciiStringMask = 1313e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; 1314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const int kFlatAsciiStringBits = 1315e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke kNotStringTag | kSeqStringTag | kAsciiStringTag; 1316e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1317e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke andl(scratch1, Immediate(kFlatAsciiStringMask)); 1318e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke andl(scratch2, Immediate(kFlatAsciiStringMask)); 1319e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Interleave the bits to check both scratch1 and scratch2 in one test. 1320e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3)); 1321e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke lea(scratch1, Operand(scratch1, scratch2, times_8, 0)); 1322e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke cmpl(scratch1, 1323e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Immediate(kFlatAsciiStringBits + (kFlatAsciiStringBits << 3))); 1324e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke j(not_equal, on_fail); 1325e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1326e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1327e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Move(Register dst, Handle<Object> source) { 1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!source->IsFailure()); 1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (source->IsSmi()) { 13313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(dst, Smi::cast(*source)); 1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(dst, source, RelocInfo::EMBEDDED_OBJECT); 1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Move(const Operand& dst, Handle<Object> source) { 13393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!source->IsFailure()); 1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (source->IsSmi()) { 13413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(dst, Smi::cast(*source)); 1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT); 1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(dst, kScratchRegister); 1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Cmp(Register dst, Handle<Object> source) { 13503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (source->IsSmi()) { 13513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiCompare(dst, Smi::cast(*source)); 13523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 13533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(kScratchRegister, source); 13543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block cmpq(dst, kScratchRegister); 13553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Cmp(const Operand& dst, Handle<Object> source) { 1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (source->IsSmi()) { 13613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiCompare(dst, Smi::cast(*source)); 1362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(source->IsHeapObject()); 1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT); 1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(dst, kScratchRegister); 1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Push(Handle<Object> source) { 1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (source->IsSmi()) { 13723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Push(Smi::cast(*source)); 1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(source->IsHeapObject()); 1375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT); 1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(kScratchRegister); 1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Push(Smi* source) { 13823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block intptr_t smi = reinterpret_cast<intptr_t>(source); 13833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (is_int32(smi)) { 13843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block push(Immediate(static_cast<int32_t>(smi))); 13853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 13863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Set(kScratchRegister, smi); 1387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(kScratchRegister); 13883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 13893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 13903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1392e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::Drop(int stack_elements) { 1393e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (stack_elements > 0) { 1394e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke addq(rsp, Immediate(stack_elements * kPointerSize)); 1395e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1396e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1397e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1398e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 13993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::Test(const Operand& src, Smi* source) { 14003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block intptr_t smi = reinterpret_cast<intptr_t>(source); 14013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (is_int32(smi)) { 14023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testl(src, Immediate(static_cast<int32_t>(smi))); 1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 14043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(kScratchRegister, source); 14053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testq(src, kScratchRegister); 1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Jump(ExternalReference ext) { 1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, ext); 1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block jmp(kScratchRegister); 1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Jump(Address destination, RelocInfo::Mode rmode) { 1417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, destination, rmode); 1418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block jmp(kScratchRegister); 1419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Jump(Handle<Code> code_object, RelocInfo::Mode rmode) { 14233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // TODO(X64): Inline this 14243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block jmp(code_object, rmode); 1425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Call(ExternalReference ext) { 1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, ext); 1430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block call(kScratchRegister); 1431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Call(Address destination, RelocInfo::Mode rmode) { 1435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, destination, rmode); 1436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block call(kScratchRegister); 1437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Call(Handle<Code> code_object, RelocInfo::Mode rmode) { 1441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(RelocInfo::IsCodeTarget(rmode)); 1442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block WriteRecordedPositions(); 14433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block call(code_object, rmode); 1444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::PushTryHandler(CodeLocation try_location, 1448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HandlerType type) { 1449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Adjust this code if not the case. 1450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); 1451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The pc (return address) is already on TOS. This code pushes state, 1453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // frame pointer and current handler. Check that they are expected 1454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // next on the stack, in that order. 1455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(StackHandlerConstants::kStateOffset, 1456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StackHandlerConstants::kPCOffset - kPointerSize); 1457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(StackHandlerConstants::kFPOffset, 1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StackHandlerConstants::kStateOffset - kPointerSize); 1459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(StackHandlerConstants::kNextOffset, 1460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StackHandlerConstants::kFPOffset - kPointerSize); 1461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (try_location == IN_JAVASCRIPT) { 1463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (type == TRY_CATCH_HANDLER) { 1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Immediate(StackHandler::TRY_CATCH)); 1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Immediate(StackHandler::TRY_FINALLY)); 1467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(rbp); 1469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(try_location == IN_JS_ENTRY); 1471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The frame pointer does not point to a JS frame so we save NULL 1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // for rbp. We expect the code throwing an exception to check rbp 1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // before dereferencing it to restore the context. 1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Immediate(StackHandler::ENTRY)); 1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Immediate(0)); // NULL frame pointer. 1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save the current handler. 1478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, ExternalReference(Top::k_handler_address)); 1479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Operand(kScratchRegister, 0)); 1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Link this handler. 1481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(Operand(kScratchRegister, 0), rsp); 1482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1485e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::PopTryHandler() { 1486e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(0, StackHandlerConstants::kNextOffset); 1487e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Unlink this handler. 1488e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movq(kScratchRegister, ExternalReference(Top::k_handler_address)); 1489e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke pop(Operand(kScratchRegister, 0)); 1490e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Remove the remaining fields. 1491e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke addq(rsp, Immediate(StackHandlerConstants::kSize - kPointerSize)); 1492e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1493e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1494e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Ret() { 1496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ret(0); 1497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::FCmp() { 15013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block fucomip(); 15023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ffree(0); 15033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block fincstp(); 1504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpObjectType(Register heap_object, 1508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstanceType type, 1509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register map) { 1510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(map, FieldOperand(heap_object, HeapObject::kMapOffset)); 1511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CmpInstanceType(map, type); 1512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpInstanceType(Register map, InstanceType type) { 1516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpb(FieldOperand(map, Map::kInstanceTypeOffset), 1517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(static_cast<int8_t>(type))); 1518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::TryGetFunctionPrototype(Register function, 1522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 1523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 1524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 1525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block testl(function, Immediate(kSmiTagMask)); 1526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(zero, miss); 1527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the function really is a function. 1529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CmpObjectType(function, JS_FUNCTION_TYPE, result); 1530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(not_equal, miss); 1531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure that the function has an instance prototype. 1533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label non_instance; 1534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block testb(FieldOperand(result, Map::kBitFieldOffset), 1535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(1 << Map::kHasNonInstancePrototype)); 1536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(not_zero, &non_instance); 1537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the prototype or initial map from the function. 1539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(result, 1540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 1541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the prototype or initial map is the hole, don't return it and 1543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // simply miss the cache instead. This will allow us to allocate a 1544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // prototype object on-demand in the runtime system. 1545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CompareRoot(result, Heap::kTheHoleValueRootIndex); 1546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(equal, miss); 1547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the function does not have an initial map, we're done. 1549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label done; 1550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CmpObjectType(result, MAP_TYPE, kScratchRegister); 1551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(not_equal, &done); 1552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the prototype from the initial map. 1554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(result, FieldOperand(result, Map::kPrototypeOffset)); 1555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block jmp(&done); 1556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Non-instance prototype: Fetch prototype from constructor field 1558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // in initial map. 1559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&non_instance); 1560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(result, FieldOperand(result, Map::kConstructorOffset)); 1561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // All done. 1563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&done); 1564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SetCounter(StatsCounter* counter, int value) { 1568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_native_code_counters && counter->Enabled()) { 1569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, ExternalReference(counter)); 1570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movl(Operand(kScratchRegister, 0), Immediate(value)); 1571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::IncrementCounter(StatsCounter* counter, int value) { 1576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(value > 0); 1577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_native_code_counters && counter->Enabled()) { 1578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, ExternalReference(counter)); 1579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand operand(kScratchRegister, 0); 1580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (value == 1) { 1581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block incl(operand); 1582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addl(operand, Immediate(value)); 1584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::DecrementCounter(StatsCounter* counter, int value) { 1590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(value > 0); 1591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_native_code_counters && counter->Enabled()) { 1592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, ExternalReference(counter)); 1593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand operand(kScratchRegister, 0); 1594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (value == 1) { 1595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block decl(operand); 1596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block subl(operand, Immediate(value)); 1598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT 1603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::PushRegistersFromMemory(RegList regs) { 1605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((regs & ~kJSCallerSaved) == 0); 1606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Push the content of the memory location to the stack. 1607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < kNumJSCallerSaved; i++) { 1608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int r = JSCallerSavedCode(i); 1609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((regs & (1 << r)) != 0) { 1610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference reg_addr = 1611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference(Debug_Address::Register(i)); 1612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, reg_addr); 1613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Operand(kScratchRegister, 0)); 1614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SaveRegistersToMemory(RegList regs) { 1620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((regs & ~kJSCallerSaved) == 0); 1621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Copy the content of registers to memory location. 1622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < kNumJSCallerSaved; i++) { 1623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int r = JSCallerSavedCode(i); 1624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((regs & (1 << r)) != 0) { 1625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register reg = { r }; 1626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference reg_addr = 1627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference(Debug_Address::Register(i)); 1628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, reg_addr); 1629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(Operand(kScratchRegister, 0), reg); 1630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::RestoreRegistersFromMemory(RegList regs) { 1636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((regs & ~kJSCallerSaved) == 0); 1637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Copy the content of memory location to registers. 1638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = kNumJSCallerSaved - 1; i >= 0; i--) { 1639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int r = JSCallerSavedCode(i); 1640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((regs & (1 << r)) != 0) { 1641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register reg = { r }; 1642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference reg_addr = 1643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference(Debug_Address::Register(i)); 1644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, reg_addr); 1645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(reg, Operand(kScratchRegister, 0)); 1646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::PopRegistersToMemory(RegList regs) { 1652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((regs & ~kJSCallerSaved) == 0); 1653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pop the content from the stack to the memory location. 1654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = kNumJSCallerSaved - 1; i >= 0; i--) { 1655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int r = JSCallerSavedCode(i); 1656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((regs & (1 << r)) != 0) { 1657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference reg_addr = 1658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference(Debug_Address::Register(i)); 1659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, reg_addr); 1660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pop(Operand(kScratchRegister, 0)); 1661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CopyRegistersFromStackToMemory(Register base, 1667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 1668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RegList regs) { 1669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!scratch.is(kScratchRegister)); 1670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!base.is(kScratchRegister)); 1671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!base.is(scratch)); 1672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((regs & ~kJSCallerSaved) == 0); 1673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Copy the content of the stack to the memory location and adjust base. 1674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = kNumJSCallerSaved - 1; i >= 0; i--) { 1675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int r = JSCallerSavedCode(i); 1676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((regs & (1 << r)) != 0) { 1677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(scratch, Operand(base, 0)); 1678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference reg_addr = 1679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference(Debug_Address::Register(i)); 1680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, reg_addr); 1681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(Operand(kScratchRegister, 0), scratch); 1682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lea(base, Operand(base, kPointerSize)); 1683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // ENABLE_DEBUGGER_SUPPORT 1688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag) { 1691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool resolved; 1692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> code = ResolveBuiltin(id, &resolved); 1693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calls are not allowed in some stubs. 1695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(flag == JUMP_FUNCTION || allow_stub_calls()); 1696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Rely on the assertion to check that the number of provided 1698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // arguments match the expected number of arguments. Fake a 1699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // parameter count to avoid emitting code to do the check. 1700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ParameterCount expected(0); 17013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block InvokeCode(Handle<Code>(code), 17023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block expected, 17033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block expected, 17043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block RelocInfo::CODE_TARGET, 17053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block flag); 1706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* name = Builtins::GetName(id); 1708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int argc = Builtins::GetArgumentsCount(id); 1709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The target address for the jump is stored as an immediate at offset 1710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // kInvokeCodeAddressOffset. 1711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!resolved) { 1712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint32_t flags = 1713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Bootstrapper::FixupFlagsArgumentsCount::encode(argc) | 1714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Bootstrapper::FixupFlagsUseCodeObject::encode(false); 1715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Unresolved entry = 1716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { pc_offset() - kCallTargetAddressOffset, flags, name }; 1717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block unresolved_.Add(entry); 1718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokePrologue(const ParameterCount& expected, 1723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 1724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> code_constant, 1725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register code_register, 1726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* done, 1727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InvokeFlag flag) { 1728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool definitely_matches = false; 1729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label invoke; 1730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (expected.is_immediate()) { 1731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(actual.is_immediate()); 1732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (expected.immediate() == actual.immediate()) { 1733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block definitely_matches = true; 1734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rax, Immediate(actual.immediate())); 1736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (expected.immediate() == 17373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SharedFunctionInfo::kDontAdaptArgumentsSentinel) { 1738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Don't worry about adapting arguments for built-ins that 1739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // don't want that done. Skip adaption code by making it look 1740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // like we have a match between expected and actual number of 1741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // arguments. 1742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block definitely_matches = true; 1743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rbx, Immediate(expected.immediate())); 1745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (actual.is_immediate()) { 1749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Expected is in register, actual is immediate. This is the 1750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // case when we invoke function values without going through the 1751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // IC mechanism. 1752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(expected.reg(), Immediate(actual.immediate())); 1753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(equal, &invoke); 1754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(expected.reg().is(rbx)); 1755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rax, Immediate(actual.immediate())); 1756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (!expected.reg().is(actual.reg())) { 1757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Both expected and actual are in (different) registers. This 1758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is the case when we invoke functions using call and apply. 1759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(expected.reg(), actual.reg()); 1760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(equal, &invoke); 1761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(actual.reg().is(rax)); 1762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(expected.reg().is(rbx)); 1763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!definitely_matches) { 1767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> adaptor = 1768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)); 1769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!code_constant.is_null()) { 1770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rdx, code_constant, RelocInfo::EMBEDDED_OBJECT); 1771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addq(rdx, Immediate(Code::kHeaderSize - kHeapObjectTag)); 1772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (!code_register.is(rdx)) { 1773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rdx, code_register); 1774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (flag == CALL_FUNCTION) { 1777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Call(adaptor, RelocInfo::CODE_TARGET); 1778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block jmp(done); 1779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Jump(adaptor, RelocInfo::CODE_TARGET); 1781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&invoke); 1783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeCode(Register code, 1788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& expected, 1789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 1790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InvokeFlag flag) { 1791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label done; 1792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InvokePrologue(expected, actual, Handle<Code>::null(), code, &done, flag); 1793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (flag == CALL_FUNCTION) { 1794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block call(code); 1795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(flag == JUMP_FUNCTION); 1797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block jmp(code); 1798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&done); 1800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeCode(Handle<Code> code, 1804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& expected, 1805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 1806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::Mode rmode, 1807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InvokeFlag flag) { 1808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label done; 1809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register dummy = rax; 1810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InvokePrologue(expected, actual, code, dummy, &done, flag); 1811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (flag == CALL_FUNCTION) { 1812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Call(code, rmode); 1813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(flag == JUMP_FUNCTION); 1815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Jump(code, rmode); 1816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&done); 1818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeFunction(Register function, 1822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 1823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InvokeFlag flag) { 1824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(function.is(rdi)); 1825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rdx, FieldOperand(function, JSFunction::kSharedFunctionInfoOffset)); 1826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rsi, FieldOperand(function, JSFunction::kContextOffset)); 1827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movsxlq(rbx, 1828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FieldOperand(rdx, SharedFunctionInfo::kFormalParameterCountOffset)); 1829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rdx, FieldOperand(rdx, SharedFunctionInfo::kCodeOffset)); 1830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Advances rdx to the end of the Code object header, to the start of 1831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the executable code. 1832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lea(rdx, FieldOperand(rdx, Code::kHeaderSize)); 1833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ParameterCount expected(rbx); 1835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InvokeCode(rdx, expected, actual, flag); 1836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::EnterFrame(StackFrame::Type type) { 1840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(rbp); 1841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rbp, rsp); 1842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(rsi); // Context. 18433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Push(Smi::FromInt(type)); 1844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT); 1845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(kScratchRegister); 1846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_debug_code) { 1847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, 1848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Factory::undefined_value(), 1849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::EMBEDDED_OBJECT); 1850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(Operand(rsp, 0), kScratchRegister); 1851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(not_equal, "code object not properly patched"); 1852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LeaveFrame(StackFrame::Type type) { 1857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_debug_code) { 18583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(kScratchRegister, Smi::FromInt(type)); 1859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(Operand(rbp, StandardFrameConstants::kMarkerOffset), kScratchRegister); 1860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(equal, "stack frame types must match"); 1861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rsp, rbp); 1863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pop(rbp); 1864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1867d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::EnterExitFrame(ExitFrame::Mode mode, int result_size) { 1868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Setup the frame structure on the stack. 1869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // All constants are relative to the frame pointer of the exit frame. 1870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize); 1871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize); 1872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize); 1873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(rbp); 1874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rbp, rsp); 1875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Reserve room for entry stack pointer and push the debug marker. 18773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize); 1878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Immediate(0)); // saved entry sp, patched before call 1879d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (mode == ExitFrame::MODE_DEBUG) { 1880d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block push(Immediate(0)); 1881d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 1882d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT); 1883d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block push(kScratchRegister); 1884d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save the frame pointer and the context in top. 1887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address); 1888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference context_address(Top::k_context_address); 1889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(r14, rax); // Backup rax before we use it. 1890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rax, rbp); 1892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block store_rax(c_entry_fp_address); 1893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rax, rsi); 1894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block store_rax(context_address); 1895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Setup argv in callee-saved register r15. It is reused in LeaveExitFrame, 1897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // so it must be retained across the C-call. 1898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; 1899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lea(r15, Operand(rbp, r14, times_pointer_size, offset)); 1900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT 1902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save the state of all registers to the stack from the memory 1903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // location. This is needed to allow nested break points. 1904d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (mode == ExitFrame::MODE_DEBUG) { 1905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // TODO(1243899): This should be symmetric to 1906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // CopyRegistersFromStackToMemory() but it isn't! esp is assumed 1907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // correct here, but computed for the other call. Very error 1908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // prone! FIX THIS. Actually there are deeper problems with 1909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // register saving than this asymmetry (see the bug report 1910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // associated with this issue). 1911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PushRegistersFromMemory(kJSCallerSaved); 1912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef _WIN64 1916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Reserve space on stack for result and argument structures, if necessary. 1917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result_stack_space = (result_size < 2) ? 0 : result_size * kPointerSize; 1918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Reserve space for the Arguments object. The Windows 64-bit ABI 1919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // requires us to pass this structure as a pointer to its location on 1920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the stack. The structure contains 2 values. 1921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int argument_stack_space = 2 * kPointerSize; 1922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We also need backing space for 4 parameters, even though 1923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // we only pass one or two parameter, and it is in a register. 1924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int argument_mirror_space = 4 * kPointerSize; 1925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int total_stack_space = 1926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block argument_mirror_space + argument_stack_space + result_stack_space; 1927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block subq(rsp, Immediate(total_stack_space)); 1928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the required frame alignment for the OS. 1931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kFrameAlignment = OS::ActivationFrameAlignment(); 1932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (kFrameAlignment > 0) { 1933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(IsPowerOf2(kFrameAlignment)); 1934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, Immediate(-kFrameAlignment)); 1935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block and_(rsp, kScratchRegister); 1936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the saved entry sp. 1939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(Operand(rbp, ExitFrameConstants::kSPOffset), rsp); 1940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1943d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::LeaveExitFrame(ExitFrame::Mode mode, int result_size) { 1944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Registers: 1945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r15 : argv 1946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT 1947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore the memory copy of the registers by digging them out from 1948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the stack. This is needed to allow nested break points. 1949d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (mode == ExitFrame::MODE_DEBUG) { 1950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // It's okay to clobber register rbx below because we don't need 1951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the function pointer after this. 1952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kCallerSavedSize = kNumJSCallerSaved * kPointerSize; 1953d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int kOffset = ExitFrameConstants::kCodeOffset - kCallerSavedSize; 1954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lea(rbx, Operand(rbp, kOffset)); 1955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CopyRegistersFromStackToMemory(rbx, rcx, kJSCallerSaved); 1956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the return address from the stack and restore the frame pointer. 1960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rcx, Operand(rbp, 1 * kPointerSize)); 1961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rbp, Operand(rbp, 0 * kPointerSize)); 1962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pop everything up to and including the arguments and the receiver 1964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // from the caller stack. 1965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lea(rsp, Operand(r15, 1 * kPointerSize)); 1966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore current context from top and clear it in debug mode. 1968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference context_address(Top::k_context_address); 1969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, context_address); 1970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rsi, Operand(kScratchRegister, 0)); 1971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 1972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(Operand(kScratchRegister, 0), Immediate(0)); 1973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Push the return address to get ready to return. 1976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(rcx); 1977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Clear the top frame. 1979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address); 1980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, c_entry_fp_address); 1981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(Operand(kScratchRegister, 0), Immediate(0)); 1982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 19853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockRegister MacroAssembler::CheckMaps(JSObject* object, 19863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register object_reg, 19873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block JSObject* holder, 19883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register holder_reg, 1989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 1990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 1991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure there's no overlap between scratch and the other 1992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // registers. 1993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!scratch.is(object_reg) && !scratch.is(holder_reg)); 1994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Keep track of the current object in register reg. On the first 1996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // iteration, reg is an alias for object_reg, on later iterations, 1997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // it is an alias for holder_reg. 1998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register reg = object_reg; 1999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int depth = 1; 2000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check the maps in the prototype chain. 2002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Traverse the prototype chain from the object and do map checks. 2003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (object != holder) { 2004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block depth++; 2005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Only global objects and objects that do not require access 2007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // checks are allowed in stubs. 2008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 2009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* prototype = JSObject::cast(object->GetPrototype()); 2011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (Heap::InNewSpace(prototype)) { 2012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the map of the current object. 2013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(scratch, FieldOperand(reg, HeapObject::kMapOffset)); 2014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Cmp(scratch, Handle<Map>(object->map())); 2015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Branch on the result of the map check. 2016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(not_equal, miss); 2017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check access rights to the global object. This has to happen 2018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // after the map check so that we know that the object is 2019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // actually a global object. 2020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsJSGlobalProxy()) { 2021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckAccessGlobalProxy(reg, scratch, miss); 2022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore scratch register to be the map of the object. 2024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We load the prototype from the map in the scratch register. 2025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(scratch, FieldOperand(reg, HeapObject::kMapOffset)); 2026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The prototype is in new space; we cannot store a reference 2028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to it in the code. Load it from the map. 2029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reg = holder_reg; // from now the object is in holder_reg 2030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(reg, FieldOperand(scratch, Map::kPrototypeOffset)); 2031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 2033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check the map of the current object. 2034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Cmp(FieldOperand(reg, HeapObject::kMapOffset), 2035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Map>(object->map())); 2036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Branch on the result of the map check. 2037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(not_equal, miss); 2038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check access rights to the global object. This has to happen 2039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // after the map check so that we know that the object is 2040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // actually a global object. 2041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsJSGlobalProxy()) { 2042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckAccessGlobalProxy(reg, scratch, miss); 2043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The prototype is in old space; load it directly. 2045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reg = holder_reg; // from now the object is in holder_reg 2046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Move(reg, Handle<JSObject>(prototype)); 2047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Go to the next object in the prototype chain. 2050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block object = prototype; 2051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check the holder map. 20543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Cmp(FieldOperand(reg, HeapObject::kMapOffset), Handle<Map>(holder->map())); 2055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(not_equal, miss); 2056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Log the check depth. 2058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LOG(IntEvent("check-maps-depth", depth)); 2059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform security check for access to the global object and return 2061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the holder register. 2062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(object == holder); 2063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 2064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsJSGlobalProxy()) { 2065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckAccessGlobalProxy(reg, scratch, miss); 2066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return reg; 2068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, 2072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 2073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 2074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label same_contexts; 2075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!holder_reg.is(scratch)); 2077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!scratch.is(kScratchRegister)); 2078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load current lexical context from the stack frame. 2079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(scratch, Operand(rbp, StandardFrameConstants::kContextOffset)); 2080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // When generating debug code, make sure the lexical context is set. 2082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_debug_code) { 2083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(scratch, Immediate(0)); 2084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(not_equal, "we should not have an empty lexical context"); 2085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the global context of the current context. 2087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; 2088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(scratch, FieldOperand(scratch, offset)); 2089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(scratch, FieldOperand(scratch, GlobalObject::kGlobalContextOffset)); 2090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check the context is a global context. 2092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_debug_code) { 2093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Cmp(FieldOperand(scratch, HeapObject::kMapOffset), 2094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Factory::global_context_map()); 2095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(equal, "JSGlobalObject::global_context should be a global context."); 2096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if both contexts are the same. 2099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(scratch, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); 2100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(equal, &same_contexts); 2101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compare security tokens. 2103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the security token in the calling global object is 2104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // compatible with the security token in the receiving global 2105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // object. 2106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check the context is a global context. 2108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_debug_code) { 2109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Preserve original value of holder_reg. 2110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(holder_reg); 2111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(holder_reg, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); 2112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CompareRoot(holder_reg, Heap::kNullValueRootIndex); 2113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(not_equal, "JSGlobalProxy::context() should not be null."); 2114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Read the first word and compare to global_context_map(), 2116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(holder_reg, FieldOperand(holder_reg, HeapObject::kMapOffset)); 2117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CompareRoot(holder_reg, Heap::kGlobalContextMapRootIndex); 2118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(equal, "JSGlobalObject::global_context should be a global context."); 2119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pop(holder_reg); 2120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, 2123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); 21243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int token_offset = 21253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Context::kHeaderSize + Context::SECURITY_TOKEN_INDEX * kPointerSize; 2126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(scratch, FieldOperand(scratch, token_offset)); 2127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(scratch, FieldOperand(kScratchRegister, token_offset)); 2128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(not_equal, miss); 2129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&same_contexts); 2131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LoadAllocationTopHelper(Register result, 2135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result_end, 2136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 2137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags) { 2138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_top = 2139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference::new_space_allocation_top_address(); 2140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Just return if allocation top is already known. 2142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((flags & RESULT_CONTAINS_TOP) != 0) { 2143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // No use of scratch if allocation top is provided. 2144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(scratch.is(no_reg)); 2145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 2146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Assert that result actually contains top on entry. 2147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, new_space_allocation_top); 2148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(result, Operand(kScratchRegister, 0)); 2149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(equal, "Unexpected allocation top"); 2150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 2151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 2152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Move address of new object to result. Use scratch register if available. 2155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (scratch.is(no_reg)) { 2156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, new_space_allocation_top); 2157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(result, Operand(kScratchRegister, 0)); 2158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 2159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!scratch.is(result_end)); 2160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(scratch, new_space_allocation_top); 2161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(result, Operand(scratch, 0)); 2162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::UpdateAllocationTopHelper(Register result_end, 2167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch) { 2168d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (FLAG_debug_code) { 2169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block testq(result_end, Immediate(kObjectAlignmentMask)); 2170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Check(zero, "Unaligned allocation in new space"); 2171d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2172d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_top = 2174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference::new_space_allocation_top_address(); 2175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update new top. 2177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result_end.is(rax)) { 2178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rax can be stored directly to a memory location. 2179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block store_rax(new_space_allocation_top); 2180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 2181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Register required - use scratch provided if available. 2182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (scratch.is(no_reg)) { 2183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, new_space_allocation_top); 2184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(Operand(kScratchRegister, 0), result_end); 2185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 2186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(Operand(scratch, 0), result_end); 2187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(int object_size, 2193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 2194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result_end, 2195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 2196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required, 2197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags) { 2198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!result.is(result_end)); 2199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load address of new object into result. 2201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadAllocationTopHelper(result, result_end, scratch, flags); 2202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate new top and bail out if new space is exhausted. 2204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_limit = 2205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference::new_space_allocation_limit_address(); 2206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lea(result_end, Operand(result, object_size)); 2207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, new_space_allocation_limit); 2208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(result_end, Operand(kScratchRegister, 0)); 2209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(above, gc_required); 2210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update allocation top. 2212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UpdateAllocationTopHelper(result_end, scratch); 2213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Tag the result if requested. 2215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((flags & TAG_OBJECT) != 0) { 2216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addq(result, Immediate(kHeapObjectTag)); 2217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(int header_size, 2222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ScaleFactor element_size, 2223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register element_count, 2224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 2225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result_end, 2226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 2227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required, 2228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags) { 2229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!result.is(result_end)); 2230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load address of new object into result. 2232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadAllocationTopHelper(result, result_end, scratch, flags); 2233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate new top and bail out if new space is exhausted. 2235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_limit = 2236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference::new_space_allocation_limit_address(); 2237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lea(result_end, Operand(result, element_count, element_size, header_size)); 2238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, new_space_allocation_limit); 2239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(result_end, Operand(kScratchRegister, 0)); 2240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(above, gc_required); 2241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update allocation top. 2243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UpdateAllocationTopHelper(result_end, scratch); 2244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Tag the result if requested. 2246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((flags & TAG_OBJECT) != 0) { 2247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addq(result, Immediate(kHeapObjectTag)); 2248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(Register object_size, 2253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 2254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result_end, 2255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 2256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required, 2257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags) { 2258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load address of new object into result. 2259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadAllocationTopHelper(result, result_end, scratch, flags); 2260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate new top and bail out if new space is exhausted. 2262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_limit = 2263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference::new_space_allocation_limit_address(); 2264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!object_size.is(result_end)) { 2265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(result_end, object_size); 2266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addq(result_end, result); 2268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, new_space_allocation_limit); 2269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(result_end, Operand(kScratchRegister, 0)); 2270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(above, gc_required); 2271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update allocation top. 2273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UpdateAllocationTopHelper(result_end, scratch); 2274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Tag the result if requested. 2276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((flags & TAG_OBJECT) != 0) { 2277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addq(result, Immediate(kHeapObjectTag)); 2278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::UndoAllocationInNewSpace(Register object) { 2283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_top = 2284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference::new_space_allocation_top_address(); 2285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure the object has no tag before resetting top. 2287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block and_(object, Immediate(~kHeapObjectTagMask)); 2288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, new_space_allocation_top); 2289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 2290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(object, Operand(kScratchRegister, 0)); 2291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(below, "Undo allocation of non allocated memory"); 2292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 2293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(Operand(kScratchRegister, 0), object); 2294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 22973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::AllocateHeapNumber(Register result, 22983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register scratch, 22993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label* gc_required) { 23003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Allocate heap number in new space. 23013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block AllocateInNewSpace(HeapNumber::kSize, 23023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block result, 23033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block scratch, 23043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block no_reg, 23053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block gc_required, 23063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block TAG_OBJECT); 23073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 23083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Set the map. 23093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block LoadRoot(kScratchRegister, Heap::kHeapNumberMapRootIndex); 23103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); 23113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 23123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 23133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::AllocateTwoByteString(Register result, 2315e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register length, 2316e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch1, 2317e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch2, 2318e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch3, 2319e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* gc_required) { 2320e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Calculate the number of bytes needed for the characters in the string while 2321e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // observing object alignment. 2322e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); 2323e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(kShortSize == 2); 2324e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // scratch1 = length * 2 + kObjectAlignmentMask. 2325e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke lea(scratch1, Operand(length, length, times_1, kObjectAlignmentMask)); 2326e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke and_(scratch1, Immediate(~kObjectAlignmentMask)); 2327e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2328e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Allocate two byte string in new space. 2329e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AllocateInNewSpace(SeqTwoByteString::kHeaderSize, 2330e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke times_1, 2331e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch1, 2332e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke result, 2333e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch2, 2334e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch3, 2335e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke gc_required, 2336e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke TAG_OBJECT); 2337e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2338e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Set the map, length and hash field. 2339e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke LoadRoot(kScratchRegister, Heap::kStringMapRootIndex); 2340e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); 2341e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movl(FieldOperand(result, String::kLengthOffset), length); 2342e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movl(FieldOperand(result, String::kHashFieldOffset), 2343e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Immediate(String::kEmptyHashField)); 2344e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 2345e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2346e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2347e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::AllocateAsciiString(Register result, 2348e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register length, 2349e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch1, 2350e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch2, 2351e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch3, 2352e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* gc_required) { 2353e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Calculate the number of bytes needed for the characters in the string while 2354e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // observing object alignment. 2355e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0); 2356e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movl(scratch1, length); 2357e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(kCharSize == 1); 2358e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke addq(scratch1, Immediate(kObjectAlignmentMask)); 2359e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke and_(scratch1, Immediate(~kObjectAlignmentMask)); 2360e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2361e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Allocate ascii string in new space. 2362e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AllocateInNewSpace(SeqAsciiString::kHeaderSize, 2363e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke times_1, 2364e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch1, 2365e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke result, 2366e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch2, 2367e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch3, 2368e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke gc_required, 2369e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke TAG_OBJECT); 2370e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2371e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Set the map, length and hash field. 2372e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke LoadRoot(kScratchRegister, Heap::kAsciiStringMapRootIndex); 2373e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); 2374e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movl(FieldOperand(result, String::kLengthOffset), length); 2375e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movl(FieldOperand(result, String::kHashFieldOffset), 2376e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Immediate(String::kEmptyHashField)); 2377e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 2378e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2379e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2380e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::AllocateConsString(Register result, 2381e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch1, 2382e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch2, 2383e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* gc_required) { 2384e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Allocate heap number in new space. 2385e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AllocateInNewSpace(ConsString::kSize, 2386e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke result, 2387e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch1, 2388e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch2, 2389e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke gc_required, 2390e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke TAG_OBJECT); 2391e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2392e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Set the map. The other fields are left uninitialized. 2393e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke LoadRoot(kScratchRegister, Heap::kConsStringMapRootIndex); 2394e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); 2395e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 2396e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2397e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2398e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::AllocateAsciiConsString(Register result, 2399e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch1, 2400e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch2, 2401e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* gc_required) { 2402e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Allocate heap number in new space. 2403e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AllocateInNewSpace(ConsString::kSize, 2404e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke result, 2405e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch1, 2406e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch2, 2407e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke gc_required, 2408e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke TAG_OBJECT); 2409e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2410e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Set the map. The other fields are left uninitialized. 2411e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke LoadRoot(kScratchRegister, Heap::kConsAsciiStringMapRootIndex); 2412e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); 2413e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 2414e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2415e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2416d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::LoadContext(Register dst, int context_chain_length) { 2417d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (context_chain_length > 0) { 2418d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Move up the chain of contexts to the context containing the slot. 2419d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block movq(dst, Operand(rsi, Context::SlotOffset(Context::CLOSURE_INDEX))); 2420d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load the function context (which is the incoming, outer context). 2421e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movq(dst, FieldOperand(dst, JSFunction::kContextOffset)); 2422d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 1; i < context_chain_length; i++) { 2423d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block movq(dst, Operand(dst, Context::SlotOffset(Context::CLOSURE_INDEX))); 2424d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block movq(dst, FieldOperand(dst, JSFunction::kContextOffset)); 2425d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2426d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // The context may be an intermediate context, not a function context. 2427d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block movq(dst, Operand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX))); 2428d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { // context is the current function context. 2429d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // The context may be an intermediate context, not a function context. 2430d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block movq(dst, Operand(rsi, Context::SlotOffset(Context::FCONTEXT_INDEX))); 2431d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2432d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2433d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2434d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCodePatcher::CodePatcher(byte* address, int size) 2436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : address_(address), size_(size), masm_(address, size + Assembler::kGap) { 2437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Create a new macro assembler pointing to the address of the code to patch. 2438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The size is adjusted with kGap on order for the assembler to generate size 2439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // bytes of instructions without failing with buffer size constraints. 2440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); 2441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCodePatcher::~CodePatcher() { 2445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Indicate that code has changed. 2446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CPU::FlushICache(address_, size_); 2447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the code was patched as expected. 2449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(masm_.pc_ == address_ + size_); 2450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); 2451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 2454