macro-assembler-ia32.cc revision 4515c472dc3e5ed2448a564600976759e569a0a8
1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2006-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 "debug.h" 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "runtime.h" 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "serialize.h" 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ------------------------------------------------------------------------- 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// MacroAssembler implementation. 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockMacroAssembler::MacroAssembler(void* buffer, int size) 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : Assembler(buffer, size), 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block unresolved_(0), 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block generating_stub_(false), 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block allow_stub_calls_(true), 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block code_object_(Heap::undefined_value()) { 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void RecordWriteHelper(MacroAssembler* masm, 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register object, 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register addr, 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch) { 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label fast; 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute the page start address from the heap object pointer, and reuse 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the 'object' register for it. 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->and_(object, ~Page::kPageAlignmentMask); 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register page_start = object; 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute the bit addr in the remembered set/index of the pointer in the 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // page. Reuse 'addr' as pointer_offset. 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->sub(addr, Operand(page_start)); 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->shr(addr, kObjectAlignmentBits); 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register pointer_offset = addr; 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the bit offset lies beyond the normal remembered set range, it is in 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the extra remembered set area of a large object. 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->cmp(pointer_offset, Page::kPageSize / kPointerSize); 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->j(less, &fast); 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Adjust 'page_start' so that addressing using 'pointer_offset' hits the 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // extra remembered set after the large object. 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Find the length of the large object (FixedArray). 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->mov(scratch, Operand(page_start, Page::kObjectStartOffset 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block + FixedArray::kLengthOffset)); 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register array_length = scratch; 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Extra remembered set starts right after the large object (a FixedArray), at 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // page_start + kObjectStartOffset + objectSize 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // where objectSize is FixedArray::kHeaderSize + kPointerSize * array_length. 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Add the delta between the end of the normal RSet and the start of the 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // extra RSet to 'page_start', so that addressing the bit using 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 'pointer_offset' hits the extra RSet words. 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->lea(page_start, 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand(page_start, array_length, times_pointer_size, 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Page::kObjectStartOffset + FixedArray::kHeaderSize 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block - Page::kRSetEndOffset)); 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // NOTE: For now, we use the bit-test-and-set (bts) x86 instruction 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to limit code size. We should probably evaluate this decision by 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // measuring the performance of an equivalent implementation using 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // "simpler" instructions 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->bind(&fast); 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->bts(Operand(page_start, Page::kRSetOffset), pointer_offset); 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass RecordWriteStub : public CodeStub { 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RecordWriteStub(Register object, Register addr, Register scratch) 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : object_(object), addr_(addr), scratch_(scratch) { } 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Generate(MacroAssembler* masm); 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register object_; 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register addr_; 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch_; 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Print() { 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF("RecordWriteStub (object reg %d), (addr reg %d), (scratch reg %d)\n", 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block object_.code(), addr_.code(), scratch_.code()); 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Minor key encoding in 12 bits of three registers (object, address and 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scratch) OOOOAAAASSSS. 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block class ScratchBits: public BitField<uint32_t, 0, 4> {}; 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block class AddressBits: public BitField<uint32_t, 4, 4> {}; 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block class ObjectBits: public BitField<uint32_t, 8, 4> {}; 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Major MajorKey() { return RecordWrite; } 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int MinorKey() { 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Encode the registers. 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return ObjectBits::encode(object_.code()) | 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddressBits::encode(addr_.code()) | 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ScratchBits::encode(scratch_.code()); 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RecordWriteStub::Generate(MacroAssembler* masm) { 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RecordWriteHelper(masm, object_, addr_, scratch_); 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm->ret(0); 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Set the remembered set bit for [object+offset]. 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// object is the object being stored into, value is the object being stored. 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// If offset is zero, then the scratch register contains the array index into 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the elements array represented as a Smi. 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// All registers are clobbered by the operation. 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::RecordWrite(Register object, int offset, 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register value, Register scratch) { 1504515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // The compiled code assumes that record write doesn't change the 1514515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // context register, so we check that none of the clobbered 1524515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // registers are esi. 1534515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke ASSERT(!object.is(esi) && !value.is(esi) && !scratch.is(esi)); 1544515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // First, check if a remembered set write is even needed. The tests below 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // catch stores of Smis and stores into young gen (which does not have space 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // for the remembered set bits. 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label done; 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Skip barrier if writing a smi. 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, kSmiTag); 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block test(value, Immediate(kSmiTagMask)); 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(zero, &done); 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (Serializer::enabled()) { 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Can't do arithmetic on external references if it might get serialized. 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(value, Operand(object)); 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block and_(value, Heap::NewSpaceMask()); 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmp(Operand(value), Immediate(ExternalReference::new_space_start())); 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(equal, &done); 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t new_space_start = reinterpret_cast<int32_t>( 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference::new_space_start().address()); 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lea(value, Operand(object, -new_space_start)); 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block and_(value, Heap::NewSpaceMask()); 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(equal, &done); 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((offset > 0) && (offset < Page::kMaxHeapObjectSize)) { 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute the bit offset in the remembered set, leave it in 'value'. 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lea(value, Operand(object, offset)); 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block and_(value, Page::kPageAlignmentMask); 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block shr(value, kPointerSizeLog2); 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute the page address from the heap object pointer, leave it in 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 'object'. 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block and_(object, ~Page::kPageAlignmentMask); 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // NOTE: For now, we use the bit-test-and-set (bts) x86 instruction 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to limit code size. We should probably evaluate this decision by 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // measuring the performance of an equivalent implementation using 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // "simpler" instructions 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bts(Operand(object, Page::kRSetOffset), value); 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register dst = scratch; 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (offset != 0) { 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lea(dst, Operand(object, offset)); 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // array access: calculate the destination address in the same manner as 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // KeyedStoreIC::GenerateGeneric. Multiply a smi by 2 to get an offset 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // into an array of words. 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(1, kSmiTagSize); 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, kSmiTag); 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lea(dst, Operand(object, dst, times_half_pointer_size, 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FixedArray::kHeaderSize - kHeapObjectTag)); 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If we are already generating a shared stub, not inlining the 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // record write code isn't going to save us any memory. 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (generating_stub()) { 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RecordWriteHelper(this, object, dst, value); 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RecordWriteStub stub(object, dst, value); 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CallStub(&stub); 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&done); 2184515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 2194515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Clobber all input registers when running with the debug-code flag 2204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // turned on to provoke errors. 2214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (FLAG_debug_code) { 2224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke mov(object, Immediate(bit_cast<int32_t>(kZapValue))); 2234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke mov(value, Immediate(bit_cast<int32_t>(kZapValue))); 2244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke mov(scratch, Immediate(bit_cast<int32_t>(kZapValue))); 2254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 229d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::StackLimitCheck(Label* on_stack_overflow) { 230d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cmp(esp, 231d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Operand::StaticVariable(ExternalReference::address_of_stack_limit())); 232d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block j(below, on_stack_overflow); 233d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 234d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 235d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SaveRegistersToMemory(RegList regs) { 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((regs & ~kJSCallerSaved) == 0); 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Copy the content of registers to memory location. 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < kNumJSCallerSaved; i++) { 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int r = JSCallerSavedCode(i); 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((regs & (1 << r)) != 0) { 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register reg = { r }; 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference reg_addr = 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference(Debug_Address::Register(i)); 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(Operand::StaticVariable(reg_addr), reg); 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::RestoreRegistersFromMemory(RegList regs) { 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((regs & ~kJSCallerSaved) == 0); 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Copy the content of memory location to registers. 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = kNumJSCallerSaved; --i >= 0;) { 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int r = JSCallerSavedCode(i); 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((regs & (1 << r)) != 0) { 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register reg = { r }; 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference reg_addr = 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference(Debug_Address::Register(i)); 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(reg, Operand::StaticVariable(reg_addr)); 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::PushRegistersFromMemory(RegList regs) { 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((regs & ~kJSCallerSaved) == 0); 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Push the content of the memory location to the stack. 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < kNumJSCallerSaved; i++) { 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int r = JSCallerSavedCode(i); 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((regs & (1 << r)) != 0) { 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference reg_addr = 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference(Debug_Address::Register(i)); 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Operand::StaticVariable(reg_addr)); 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::PopRegistersToMemory(RegList regs) { 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((regs & ~kJSCallerSaved) == 0); 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pop the content from the stack to the memory location. 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = kNumJSCallerSaved; --i >= 0;) { 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int r = JSCallerSavedCode(i); 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((regs & (1 << r)) != 0) { 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference reg_addr = 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference(Debug_Address::Register(i)); 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pop(Operand::StaticVariable(reg_addr)); 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CopyRegistersFromStackToMemory(Register base, 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RegList regs) { 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((regs & ~kJSCallerSaved) == 0); 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Copy the content of the stack to the memory location and adjust base. 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = kNumJSCallerSaved; --i >= 0;) { 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int r = JSCallerSavedCode(i); 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((regs & (1 << r)) != 0) { 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(scratch, Operand(base, 0)); 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference reg_addr = 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference(Debug_Address::Register(i)); 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(Operand::StaticVariable(reg_addr), scratch); 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lea(base, Operand(base, kPointerSize)); 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Set(Register dst, const Immediate& x) { 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (x.is_zero()) { 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block xor_(dst, Operand(dst)); // shorter than mov 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(dst, x); 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Set(const Operand& dst, const Immediate& x) { 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(dst, x); 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpObjectType(Register heap_object, 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstanceType type, 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register map) { 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(map, FieldOperand(heap_object, HeapObject::kMapOffset)); 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CmpInstanceType(map, type); 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpInstanceType(Register map, InstanceType type) { 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpb(FieldOperand(map, Map::kInstanceTypeOffset), 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static_cast<int8_t>(type)); 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 341e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeCondition MacroAssembler::IsObjectStringType(Register heap_object, 342e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register map, 343e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register instance_type) { 344e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke mov(map, FieldOperand(heap_object, HeapObject::kMapOffset)); 345e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset)); 346e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(kNotStringTag != 0); 347e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke test(instance_type, Immediate(kIsNotStringMask)); 348e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return zero; 349e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 350e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 351e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::FCmp() { 353d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (CpuFeatures::IsSupported(CMOV)) { 3543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block fucomip(); 3553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ffree(0); 3563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block fincstp(); 3573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 3583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block fucompp(); 3593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block push(eax); 3603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block fnstsw_ax(); 3613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block sahf(); 3623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block pop(eax); 3633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::EnterFrame(StackFrame::Type type) { 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(ebp); 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(ebp, Operand(esp)); 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(esi); 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Immediate(Smi::FromInt(type))); 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Immediate(CodeObject())); 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_debug_code) { 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmp(Operand(esp, 0), Immediate(Factory::undefined_value())); 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(not_equal, "code object not properly patched"); 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LeaveFrame(StackFrame::Type type) { 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_debug_code) { 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmp(Operand(ebp, StandardFrameConstants::kMarkerOffset), 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(Smi::FromInt(type))); 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(equal, "stack frame types must match"); 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block leave(); 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 389d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::EnterExitFramePrologue(ExitFrame::Mode mode) { 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Setup the frame structure on the stack. 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize); 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize); 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize); 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(ebp); 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(ebp, Operand(esp)); 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Reserve room for entry stack pointer and push the debug marker. 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize); 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Immediate(0)); // saved entry sp, patched before call 400d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (mode == ExitFrame::MODE_DEBUG) { 401d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block push(Immediate(0)); 402d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 403d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block push(Immediate(CodeObject())); 404d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save the frame pointer and the context in top. 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address); 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference context_address(Top::k_context_address); 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(Operand::StaticVariable(c_entry_fp_address), ebp); 410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(Operand::StaticVariable(context_address), esi); 411d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 413d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::EnterExitFrameEpilogue(ExitFrame::Mode mode, int argc) { 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT 415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save the state of all registers to the stack from the memory 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // location. This is needed to allow nested break points. 417d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (mode == ExitFrame::MODE_DEBUG) { 418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // TODO(1243899): This should be symmetric to 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // CopyRegistersFromStackToMemory() but it isn't! esp is assumed 420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // correct here, but computed for the other call. Very error 421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // prone! FIX THIS. Actually there are deeper problems with 422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // register saving than this asymmetry (see the bug report 423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // associated with this issue). 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PushRegistersFromMemory(kJSCallerSaved); 425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 428d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Reserve space for arguments. 429d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block sub(Operand(esp), Immediate(argc * kPointerSize)); 430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the required frame alignment for the OS. 432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kFrameAlignment = OS::ActivationFrameAlignment(); 433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (kFrameAlignment > 0) { 434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(IsPowerOf2(kFrameAlignment)); 435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block and_(esp, -kFrameAlignment); 436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the saved entry sp. 439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(Operand(ebp, ExitFrameConstants::kSPOffset), esp); 440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 443d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::EnterExitFrame(ExitFrame::Mode mode) { 444d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block EnterExitFramePrologue(mode); 445d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 446d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Setup argc and argv in callee-saved registers. 447d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; 448d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mov(edi, Operand(eax)); 449d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block lea(esi, Operand(ebp, eax, times_4, offset)); 450d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 451d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block EnterExitFrameEpilogue(mode, 2); 452d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 453d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 454d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 455d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::EnterApiExitFrame(ExitFrame::Mode mode, 456d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int stack_space, 457d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int argc) { 458d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block EnterExitFramePrologue(mode); 459d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 460d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; 461d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block lea(esi, Operand(ebp, (stack_space * kPointerSize) + offset)); 462d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 463d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block EnterExitFrameEpilogue(mode, argc); 464d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 465d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 466d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 467d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::LeaveExitFrame(ExitFrame::Mode mode) { 468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT 469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore the memory copy of the registers by digging them out from 470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the stack. This is needed to allow nested break points. 471d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (mode == ExitFrame::MODE_DEBUG) { 472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // It's okay to clobber register ebx below because we don't need 473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the function pointer after this. 474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kCallerSavedSize = kNumJSCallerSaved * kPointerSize; 475d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int kOffset = ExitFrameConstants::kCodeOffset - kCallerSavedSize; 476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lea(ebx, Operand(ebp, kOffset)); 477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CopyRegistersFromStackToMemory(ebx, ecx, kJSCallerSaved); 478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the return address from the stack and restore the frame pointer. 482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(ecx, Operand(ebp, 1 * kPointerSize)); 483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(ebp, Operand(ebp, 0 * kPointerSize)); 484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pop the arguments and the receiver from the caller stack. 486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lea(esp, Operand(esi, 1 * kPointerSize)); 487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore current context from top and clear it in debug mode. 489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference context_address(Top::k_context_address); 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(esi, Operand::StaticVariable(context_address)); 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(Operand::StaticVariable(context_address), Immediate(0)); 493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Push the return address to get ready to return. 496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(ecx); 497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Clear the top frame. 499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address); 500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(Operand::StaticVariable(c_entry_fp_address), Immediate(0)); 501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::PushTryHandler(CodeLocation try_location, 505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HandlerType type) { 506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Adjust this code if not the case. 507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); 508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The pc (return address) is already on TOS. 509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (try_location == IN_JAVASCRIPT) { 510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (type == TRY_CATCH_HANDLER) { 511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Immediate(StackHandler::TRY_CATCH)); 512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Immediate(StackHandler::TRY_FINALLY)); 514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(ebp); 516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(try_location == IN_JS_ENTRY); 518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The frame pointer does not point to a JS frame so we save NULL 519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // for ebp. We expect the code throwing an exception to check ebp 520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // before dereferencing it to restore the context. 521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Immediate(StackHandler::ENTRY)); 522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Immediate(0)); // NULL frame pointer. 523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save the current handler as the next handler. 525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Operand::StaticVariable(ExternalReference(Top::k_handler_address))); 526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Link this handler as the new current one. 527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(Operand::StaticVariable(ExternalReference(Top::k_handler_address)), esp); 528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 531e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::PopTryHandler() { 532e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(0, StackHandlerConstants::kNextOffset); 533e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke pop(Operand::StaticVariable(ExternalReference(Top::k_handler_address))); 534e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke add(Operand(esp), Immediate(StackHandlerConstants::kSize - kPointerSize)); 535e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 536e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 537e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister MacroAssembler::CheckMaps(JSObject* object, Register object_reg, 539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, Register holder_reg, 540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure there's no overlap between scratch and the other 543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // registers. 544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!scratch.is(object_reg) && !scratch.is(holder_reg)); 545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Keep track of the current object in register reg. 547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register reg = object_reg; 548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int depth = 1; 549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check the maps in the prototype chain. 551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Traverse the prototype chain from the object and do map checks. 552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (object != holder) { 553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block depth++; 554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Only global objects and objects that do not require access 556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // checks are allowed in stubs. 557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* prototype = JSObject::cast(object->GetPrototype()); 560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (Heap::InNewSpace(prototype)) { 561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the map of the current object. 562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); 563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmp(Operand(scratch), Immediate(Handle<Map>(object->map()))); 564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Branch on the result of the map check. 565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(not_equal, miss, not_taken); 566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check access rights to the global object. This has to happen 567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // after the map check so that we know that the object is 568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // actually a global object. 569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsJSGlobalProxy()) { 570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckAccessGlobalProxy(reg, scratch, miss); 571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore scratch register to be the map of the object. 573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We load the prototype from the map in the scratch register. 574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); 575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The prototype is in new space; we cannot store a reference 577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to it in the code. Load it from the map. 578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reg = holder_reg; // from now the object is in holder_reg 579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(reg, FieldOperand(scratch, Map::kPrototypeOffset)); 580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check the map of the current object. 583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmp(FieldOperand(reg, HeapObject::kMapOffset), 584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(Handle<Map>(object->map()))); 585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Branch on the result of the map check. 586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(not_equal, miss, not_taken); 587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check access rights to the global object. This has to happen 588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // after the map check so that we know that the object is 589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // actually a global object. 590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsJSGlobalProxy()) { 591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckAccessGlobalProxy(reg, scratch, miss); 592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The prototype is in old space; load it directly. 594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reg = holder_reg; // from now the object is in holder_reg 595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(reg, Handle<JSObject>(prototype)); 596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Go to the next object in the prototype chain. 599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block object = prototype; 600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check the holder map. 603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmp(FieldOperand(reg, HeapObject::kMapOffset), 604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(Handle<Map>(holder->map()))); 605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(not_equal, miss, not_taken); 606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Log the check depth. 608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LOG(IntEvent("check-maps-depth", depth)); 609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform security check for access to the global object and return 611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the holder register. 612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(object == holder); 613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsJSGlobalProxy()) { 615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckAccessGlobalProxy(reg, scratch, miss); 616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return reg; 618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, 622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label same_contexts; 625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!holder_reg.is(scratch)); 627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load current lexical context from the stack frame. 629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(scratch, Operand(ebp, StandardFrameConstants::kContextOffset)); 630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // When generating debug code, make sure the lexical context is set. 632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_debug_code) { 633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmp(Operand(scratch), Immediate(0)); 634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(not_equal, "we should not have an empty lexical context"); 635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the global context of the current context. 637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(scratch, FieldOperand(scratch, offset)); 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(scratch, FieldOperand(scratch, GlobalObject::kGlobalContextOffset)); 640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check the context is a global context. 642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_debug_code) { 643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(scratch); 644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Read the first word and compare to global_context_map. 645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); 646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmp(scratch, Factory::global_context_map()); 647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(equal, "JSGlobalObject::global_context should be a global context."); 648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pop(scratch); 649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if both contexts are the same. 652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmp(scratch, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); 653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(equal, &same_contexts, taken); 654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compare security tokens, save holder_reg on the stack so we can use it 656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // as a temporary register. 657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // TODO(119): avoid push(holder_reg)/pop(holder_reg) 659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(holder_reg); 660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the security token in the calling global object is 661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // compatible with the security token in the receiving global 662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // object. 663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(holder_reg, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); 664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check the context is a global context. 666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_debug_code) { 667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmp(holder_reg, Factory::null_value()); 668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(not_equal, "JSGlobalProxy::context() should not be null."); 669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(holder_reg); 671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Read the first word and compare to global_context_map(), 672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(holder_reg, FieldOperand(holder_reg, HeapObject::kMapOffset)); 673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmp(holder_reg, Factory::global_context_map()); 674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(equal, "JSGlobalObject::global_context should be a global context."); 675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pop(holder_reg); 676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int token_offset = Context::kHeaderSize + 679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Context::SECURITY_TOKEN_INDEX * kPointerSize; 680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(scratch, FieldOperand(scratch, token_offset)); 681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmp(scratch, FieldOperand(holder_reg, token_offset)); 682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pop(holder_reg); 683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(not_equal, miss, not_taken); 684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&same_contexts); 686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LoadAllocationTopHelper(Register result, 690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result_end, 691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags) { 693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_top = 694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference::new_space_allocation_top_address(); 695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Just return if allocation top is already known. 697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((flags & RESULT_CONTAINS_TOP) != 0) { 698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // No use of scratch if allocation top is provided. 699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(scratch.is(no_reg)); 700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Assert that result actually contains top on entry. 702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmp(result, Operand::StaticVariable(new_space_allocation_top)); 703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(equal, "Unexpected allocation top"); 704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Move address of new object to result. Use scratch register if available. 709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (scratch.is(no_reg)) { 710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(result, Operand::StaticVariable(new_space_allocation_top)); 711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!scratch.is(result_end)); 713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(Operand(scratch), Immediate(new_space_allocation_top)); 714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(result, Operand(scratch, 0)); 715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::UpdateAllocationTopHelper(Register result_end, 720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch) { 721d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (FLAG_debug_code) { 722d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block test(result_end, Immediate(kObjectAlignmentMask)); 723d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Check(zero, "Unaligned allocation in new space"); 724d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 725d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_top = 727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference::new_space_allocation_top_address(); 728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update new top. Use scratch if available. 730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (scratch.is(no_reg)) { 731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(Operand::StaticVariable(new_space_allocation_top), result_end); 732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(Operand(scratch, 0), result_end); 734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(int object_size, 739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result_end, 741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required, 743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags) { 744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!result.is(result_end)); 745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load address of new object into result. 747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadAllocationTopHelper(result, result_end, scratch, flags); 748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate new top and bail out if new space is exhausted. 750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_limit = 751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference::new_space_allocation_limit_address(); 752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lea(result_end, Operand(result, object_size)); 753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmp(result_end, Operand::StaticVariable(new_space_allocation_limit)); 754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(above, gc_required, not_taken); 755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Tag result if requested. 757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((flags & TAG_OBJECT) != 0) { 758e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke lea(result, Operand(result, kHeapObjectTag)); 759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 760e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 761e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Update allocation top. 762e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UpdateAllocationTopHelper(result_end, scratch); 763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(int header_size, 767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ScaleFactor element_size, 768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register element_count, 769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result_end, 771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required, 773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags) { 774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!result.is(result_end)); 775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load address of new object into result. 777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadAllocationTopHelper(result, result_end, scratch, flags); 778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate new top and bail out if new space is exhausted. 780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_limit = 781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference::new_space_allocation_limit_address(); 782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lea(result_end, Operand(result, element_count, element_size, header_size)); 783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmp(result_end, Operand::StaticVariable(new_space_allocation_limit)); 784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(above, gc_required); 785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Tag result if requested. 787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((flags & TAG_OBJECT) != 0) { 788e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke lea(result, Operand(result, kHeapObjectTag)); 789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 790e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 791e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Update allocation top. 792e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UpdateAllocationTopHelper(result_end, scratch); 793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(Register object_size, 797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result_end, 799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required, 801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags) { 802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!result.is(result_end)); 803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load address of new object into result. 805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadAllocationTopHelper(result, result_end, scratch, flags); 806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate new top and bail out if new space is exhausted. 808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_limit = 809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference::new_space_allocation_limit_address(); 810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!object_size.is(result_end)) { 811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(result_end, object_size); 812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block add(result_end, Operand(result)); 814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmp(result_end, Operand::StaticVariable(new_space_allocation_limit)); 815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(above, gc_required, not_taken); 816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Tag result if requested. 818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((flags & TAG_OBJECT) != 0) { 819e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke lea(result, Operand(result, kHeapObjectTag)); 820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 821e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 822e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Update allocation top. 823e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UpdateAllocationTopHelper(result_end, scratch); 824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::UndoAllocationInNewSpace(Register object) { 828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_top = 829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference::new_space_allocation_top_address(); 830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure the object has no tag before resetting top. 832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block and_(Operand(object), Immediate(~kHeapObjectTagMask)); 833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmp(object, Operand::StaticVariable(new_space_allocation_top)); 835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(below, "Undo allocation of non allocated memory"); 836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(Operand::StaticVariable(new_space_allocation_top), object); 838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::AllocateHeapNumber(Register result, 8423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register scratch1, 8433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register scratch2, 8443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label* gc_required) { 8453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Allocate heap number in new space. 8463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block AllocateInNewSpace(HeapNumber::kSize, 8473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block result, 8483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block scratch1, 8493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block scratch2, 8503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block gc_required, 8513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block TAG_OBJECT); 8523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 8533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Set the map. 8543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block mov(FieldOperand(result, HeapObject::kMapOffset), 8553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Immediate(Factory::heap_number_map())); 8563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 8573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 8583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 859d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::AllocateTwoByteString(Register result, 860d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register length, 861d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch1, 862d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch2, 863d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch3, 864d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label* gc_required) { 865d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Calculate the number of bytes needed for the characters in the string while 866d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // observing object alignment. 867d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); 868d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(kShortSize == 2); 869e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // scratch1 = length * 2 + kObjectAlignmentMask. 870e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke lea(scratch1, Operand(length, length, times_1, kObjectAlignmentMask)); 871d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block and_(Operand(scratch1), Immediate(~kObjectAlignmentMask)); 872d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 873d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Allocate two byte string in new space. 874d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block AllocateInNewSpace(SeqTwoByteString::kHeaderSize, 875d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block times_1, 876d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block scratch1, 877d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result, 878d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block scratch2, 879d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block scratch3, 880d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block gc_required, 881d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block TAG_OBJECT); 882d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 883d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Set the map, length and hash field. 884d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mov(FieldOperand(result, HeapObject::kMapOffset), 885d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Immediate(Factory::string_map())); 886d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mov(FieldOperand(result, String::kLengthOffset), length); 887d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mov(FieldOperand(result, String::kHashFieldOffset), 888d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Immediate(String::kEmptyHashField)); 889d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 890d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 891d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 892d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::AllocateAsciiString(Register result, 893d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register length, 894d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch1, 895d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch2, 896d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch3, 897d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label* gc_required) { 898d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Calculate the number of bytes needed for the characters in the string while 899d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // observing object alignment. 900d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0); 901d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mov(scratch1, length); 902d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(kCharSize == 1); 903d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block add(Operand(scratch1), Immediate(kObjectAlignmentMask)); 904d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block and_(Operand(scratch1), Immediate(~kObjectAlignmentMask)); 905d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 906d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Allocate ascii string in new space. 907d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block AllocateInNewSpace(SeqAsciiString::kHeaderSize, 908d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block times_1, 909d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block scratch1, 910d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result, 911d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block scratch2, 912d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block scratch3, 913d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block gc_required, 914d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block TAG_OBJECT); 915d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 916d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Set the map, length and hash field. 917d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mov(FieldOperand(result, HeapObject::kMapOffset), 918d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Immediate(Factory::ascii_string_map())); 919d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mov(FieldOperand(result, String::kLengthOffset), length); 920d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mov(FieldOperand(result, String::kHashFieldOffset), 921d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Immediate(String::kEmptyHashField)); 922d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 923d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 924d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 925d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::AllocateConsString(Register result, 926d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch1, 927d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch2, 928d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label* gc_required) { 929d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Allocate heap number in new space. 930d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block AllocateInNewSpace(ConsString::kSize, 931d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result, 932d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block scratch1, 933d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block scratch2, 934d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block gc_required, 935d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block TAG_OBJECT); 936d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 937d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Set the map. The other fields are left uninitialized. 938d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mov(FieldOperand(result, HeapObject::kMapOffset), 939d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Immediate(Factory::cons_string_map())); 940d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 941d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 942d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 943d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::AllocateAsciiConsString(Register result, 944d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch1, 945d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch2, 946d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label* gc_required) { 947d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Allocate heap number in new space. 948d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block AllocateInNewSpace(ConsString::kSize, 949d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result, 950d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block scratch1, 951d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block scratch2, 952d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block gc_required, 953d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block TAG_OBJECT); 954d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 955d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Set the map. The other fields are left uninitialized. 956d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mov(FieldOperand(result, HeapObject::kMapOffset), 957d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Immediate(Factory::cons_ascii_string_map())); 958d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 959d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 960d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::NegativeZeroTest(CodeGenerator* cgen, 962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register op, 964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JumpTarget* then_target) { 965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JumpTarget ok; 966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block test(result, Operand(result)); 967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ok.Branch(not_zero, taken); 968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block test(op, Operand(op)); 969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block then_target->Branch(sign, not_taken); 970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ok.Bind(); 971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::NegativeZeroTest(Register result, 975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register op, 976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* then_label) { 977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label ok; 978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block test(result, Operand(result)); 979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(not_zero, &ok, taken); 980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block test(op, Operand(op)); 981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(sign, then_label, not_taken); 982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&ok); 983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::NegativeZeroTest(Register result, 987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register op1, 988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register op2, 989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* then_label) { 991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label ok; 992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block test(result, Operand(result)); 993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(not_zero, &ok, taken); 994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(scratch, Operand(op1)); 995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block or_(scratch, Operand(op2)); 996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(sign, then_label, not_taken); 997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&ok); 998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::TryGetFunctionPrototype(Register function, 1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block test(function, Immediate(kSmiTagMask)); 1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(zero, miss, not_taken); 1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the function really is a function. 1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CmpObjectType(function, JS_FUNCTION_TYPE, result); 1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(not_equal, miss, not_taken); 1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure that the function has an instance prototype. 1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label non_instance; 1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movzx_b(scratch, FieldOperand(result, Map::kBitFieldOffset)); 1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block test(scratch, Immediate(1 << Map::kHasNonInstancePrototype)); 1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(not_zero, &non_instance, not_taken); 1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the prototype or initial map from the function. 1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(result, 1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the prototype or initial map is the hole, don't return it and 1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // simply miss the cache instead. This will allow us to allocate a 1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // prototype object on-demand in the runtime system. 1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmp(Operand(result), Immediate(Factory::the_hole_value())); 1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(equal, miss, not_taken); 1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the function does not have an initial map, we're done. 1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label done; 1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CmpObjectType(result, MAP_TYPE, scratch); 1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(not_equal, &done); 1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the prototype from the initial map. 1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(result, FieldOperand(result, Map::kPrototypeOffset)); 1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block jmp(&done); 1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Non-instance prototype: Fetch prototype from constructor field 1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // in initial map. 1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&non_instance); 1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(result, FieldOperand(result, Map::kConstructorOffset)); 1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // All done. 1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&done); 1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CallStub(CodeStub* stub) { 1049e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(allow_stub_calls()); // Calls are not allowed in some stubs. 1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block call(stub->GetCode(), RelocInfo::CODE_TARGET); 1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1054e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeObject* MacroAssembler::TryCallStub(CodeStub* stub) { 1055e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(allow_stub_calls()); // Calls are not allowed in some stubs. 1056e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Object* result = stub->TryGetCode(); 1057e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!result->IsFailure()) { 1058e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke call(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET); 1059e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1060e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return result; 1061e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1062e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1063e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1064d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::TailCallStub(CodeStub* stub) { 1065e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(allow_stub_calls()); // Calls are not allowed in some stubs. 1066d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block jmp(stub->GetCode(), RelocInfo::CODE_TARGET); 1067d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1068d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1069d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1070e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeObject* MacroAssembler::TryTailCallStub(CodeStub* stub) { 1071e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(allow_stub_calls()); // Calls are not allowed in some stubs. 1072e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Object* result = stub->TryGetCode(); 1073e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!result->IsFailure()) { 1074e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke jmp(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET); 1075e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1076e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return result; 1077e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1078e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1079e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::StubReturn(int argc) { 1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(argc >= 1 && generating_stub()); 1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ret((argc - 1) * kPointerSize); 1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::IllegalOperation(int num_arguments) { 1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (num_arguments > 0) { 1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block add(Operand(esp), Immediate(num_arguments * kPointerSize)); 1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(eax, Immediate(Factory::undefined_value())); 1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CallRuntime(Runtime::FunctionId id, int num_arguments) { 1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CallRuntime(Runtime::FunctionForId(id), num_arguments); 1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1099e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeObject* MacroAssembler::TryCallRuntime(Runtime::FunctionId id, 1100e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int num_arguments) { 1101e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return TryCallRuntime(Runtime::FunctionForId(id), num_arguments); 1102e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1103e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1104e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) { 1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the expected number of arguments of the runtime function is 1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // constant, we check that the actual number of arguments match the 1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // expectation. 1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (f->nargs >= 0 && f->nargs != num_arguments) { 1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block IllegalOperation(num_arguments); 1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 11144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // TODO(1236192): Most runtime routines don't need the number of 11154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // arguments passed in because it is constant. At some point we 11164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // should remove this need and make the runtime routine entry code 11174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // smarter. 11184515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Set(eax, Immediate(num_arguments)); 11194515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke mov(ebx, Immediate(ExternalReference(f))); 11204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke CEntryStub ces(1); 11214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke CallStub(&ces); 1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1125e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeObject* MacroAssembler::TryCallRuntime(Runtime::Function* f, 1126e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int num_arguments) { 1127e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (f->nargs >= 0 && f->nargs != num_arguments) { 1128e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke IllegalOperation(num_arguments); 1129e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Since we did not call the stub, there was no allocation failure. 1130e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Return some non-failure object. 1131e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return Heap::undefined_value(); 1132e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1133e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 11344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // TODO(1236192): Most runtime routines don't need the number of 11354515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // arguments passed in because it is constant. At some point we 11364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // should remove this need and make the runtime routine entry code 11374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // smarter. 11384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Set(eax, Immediate(num_arguments)); 11394515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke mov(ebx, Immediate(ExternalReference(f))); 11404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke CEntryStub ces(1); 11414515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke return TryCallStub(&ces); 1142e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1143e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1144e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::TailCallRuntime(const ExternalReference& ext, 1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int num_arguments, 1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result_size) { 1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // TODO(1236192): Most runtime routines don't need the number of 1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // arguments passed in because it is constant. At some point we 1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // should remove this need and make the runtime routine entry code 1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // smarter. 1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Set(eax, Immediate(num_arguments)); 1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JumpToRuntime(ext); 1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1157d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::PushHandleScope(Register scratch) { 1158d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push the number of extensions, smi-tagged so the gc will ignore it. 1159d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReference extensions_address = 1160d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReference::handle_scope_extensions_address(); 1161d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mov(scratch, Operand::StaticVariable(extensions_address)); 1162d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_EQ(0, kSmiTag); 1163d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block shl(scratch, kSmiTagSize); 1164d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block push(scratch); 1165d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mov(Operand::StaticVariable(extensions_address), Immediate(0)); 1166d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push next and limit pointers which will be wordsize aligned and 1167d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // hence automatically smi tagged. 1168d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReference next_address = 1169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReference::handle_scope_next_address(); 1170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block push(Operand::StaticVariable(next_address)); 1171d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReference limit_address = 1172d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReference::handle_scope_limit_address(); 1173d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block push(Operand::StaticVariable(limit_address)); 1174d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1175d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1176d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1177e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeObject* MacroAssembler::PopHandleScopeHelper(Register saved, 1178e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch, 1179e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke bool gc_allowed) { 1180e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Object* result = NULL; 1181d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReference extensions_address = 1182d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReference::handle_scope_extensions_address(); 1183d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label write_back; 1184d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mov(scratch, Operand::StaticVariable(extensions_address)); 1185d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cmp(Operand(scratch), Immediate(0)); 1186d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block j(equal, &write_back); 1187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Calling a runtime function messes with registers so we save and 1188d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // restore any one we're asked not to change 1189d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (saved.is_valid()) push(saved); 1190e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (gc_allowed) { 1191e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke CallRuntime(Runtime::kDeleteHandleScopeExtensions, 0); 1192e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 1193e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke result = TryCallRuntime(Runtime::kDeleteHandleScopeExtensions, 0); 1194e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (result->IsFailure()) return result; 1195e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (saved.is_valid()) pop(saved); 1197d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bind(&write_back); 1199d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReference limit_address = 1200d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReference::handle_scope_limit_address(); 1201d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block pop(Operand::StaticVariable(limit_address)); 1202d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReference next_address = 1203d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReference::handle_scope_next_address(); 1204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block pop(Operand::StaticVariable(next_address)); 1205d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block pop(scratch); 1206d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block shr(scratch, kSmiTagSize); 1207d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mov(Operand::StaticVariable(extensions_address), scratch); 1208e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1209e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return result; 1210e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1211e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1212e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1213e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::PopHandleScope(Register saved, Register scratch) { 1214e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke PopHandleScopeHelper(saved, scratch, true); 1215e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1216e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1217e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1218e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeObject* MacroAssembler::TryPopHandleScope(Register saved, Register scratch) { 1219e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return PopHandleScopeHelper(saved, scratch, false); 1220d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1221d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1222d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::JumpToRuntime(const ExternalReference& ext) { 1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the entry point and jump to the C entry runtime stub. 1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(ebx, Immediate(ext)); 1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CEntryStub ces(1); 1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block jmp(ces.GetCode(), RelocInfo::CODE_TARGET); 1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokePrologue(const ParameterCount& expected, 1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> code_constant, 1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const Operand& code_operand, 1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* done, 1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InvokeFlag flag) { 1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool definitely_matches = false; 1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label invoke; 1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (expected.is_immediate()) { 1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(actual.is_immediate()); 1241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (expected.immediate() == actual.immediate()) { 1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block definitely_matches = true; 1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(eax, actual.immediate()); 1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel; 1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (expected.immediate() == sentinel) { 1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Don't worry about adapting arguments for builtins that 1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // don't want that done. Skip adaption code by making it look 1249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // like we have a match between expected and actual number of 1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // arguments. 1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block definitely_matches = true; 1252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(ebx, expected.immediate()); 1254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (actual.is_immediate()) { 1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Expected is in register, actual is immediate. This is the 1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // case when we invoke function values without going through the 1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // IC mechanism. 1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmp(expected.reg(), actual.immediate()); 1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(equal, &invoke); 1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(expected.reg().is(ebx)); 1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(eax, actual.immediate()); 1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (!expected.reg().is(actual.reg())) { 1266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Both expected and actual are in (different) registers. This 1267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is the case when we invoke functions using call and apply. 1268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmp(expected.reg(), Operand(actual.reg())); 1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(equal, &invoke); 1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(actual.reg().is(eax)); 1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(expected.reg().is(ebx)); 1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!definitely_matches) { 1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> adaptor = 1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)); 1278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!code_constant.is_null()) { 1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(edx, Immediate(code_constant)); 1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block add(Operand(edx), Immediate(Code::kHeaderSize - kHeapObjectTag)); 1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (!code_operand.is_reg(edx)) { 1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(edx, code_operand); 1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (flag == CALL_FUNCTION) { 1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block call(adaptor, RelocInfo::CODE_TARGET); 1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block jmp(done); 1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block jmp(adaptor, RelocInfo::CODE_TARGET); 1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&invoke); 1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeCode(const Operand& code, 1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& expected, 1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InvokeFlag flag) { 1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label done; 1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InvokePrologue(expected, actual, Handle<Code>::null(), code, &done, flag); 1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (flag == CALL_FUNCTION) { 1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block call(code); 1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(flag == JUMP_FUNCTION); 1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block jmp(code); 1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&done); 1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeCode(Handle<Code> code, 1313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& expected, 1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::Mode rmode, 1316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InvokeFlag flag) { 1317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label done; 1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand dummy(eax); 1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InvokePrologue(expected, actual, code, dummy, &done, flag); 1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (flag == CALL_FUNCTION) { 1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block call(code, rmode); 1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(flag == JUMP_FUNCTION); 1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block jmp(code, rmode); 1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&done); 1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeFunction(Register fun, 1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InvokeFlag flag) { 1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(fun.is(edi)); 1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(ebx, FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset)); 1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(edx, FieldOperand(edx, SharedFunctionInfo::kCodeOffset)); 1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lea(edx, FieldOperand(edx, Code::kHeaderSize)); 1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ParameterCount expected(ebx); 1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InvokeCode(Operand(edx), expected, actual, flag); 1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag) { 1346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool resolved; 1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> code = ResolveBuiltin(id, &resolved); 1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calls are not allowed in some stubs. 1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(flag == JUMP_FUNCTION || allow_stub_calls()); 1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Rely on the assertion to check that the number of provided 1353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // arguments match the expected number of arguments. Fake a 1354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // parameter count to avoid emitting code to do the check. 1355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ParameterCount expected(0); 1356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InvokeCode(Handle<Code>(code), expected, expected, 1357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::CODE_TARGET, flag); 1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* name = Builtins::GetName(id); 1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int argc = Builtins::GetArgumentsCount(id); 1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!resolved) { 1363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint32_t flags = 1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Bootstrapper::FixupFlagsArgumentsCount::encode(argc) | 1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Bootstrapper::FixupFlagsUseCodeObject::encode(false); 1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Unresolved entry = { pc_offset() - sizeof(int32_t), flags, name }; 1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block unresolved_.Add(entry); 1368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) { 1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool resolved; 1374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> code = ResolveBuiltin(id, &resolved); 1375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* name = Builtins::GetName(id); 1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int argc = Builtins::GetArgumentsCount(id); 1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(Operand(target), Immediate(code)); 1380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!resolved) { 1381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint32_t flags = 1382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Bootstrapper::FixupFlagsArgumentsCount::encode(argc) | 1383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Bootstrapper::FixupFlagsUseCodeObject::encode(true); 1384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Unresolved entry = { pc_offset() - sizeof(int32_t), flags, name }; 1385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block unresolved_.Add(entry); 1386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block add(Operand(target), Immediate(Code::kHeaderSize - kHeapObjectTag)); 1388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockHandle<Code> MacroAssembler::ResolveBuiltin(Builtins::JavaScript id, 1392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool* resolved) { 1393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Move the builtin function into the temporary function slot by 1394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // reading it from the builtins object. NOTE: We should be able to 1395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // reduce this to two instructions by putting the function table in 1396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the global object instead of the "builtins" object and by using a 1397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // real register for the function. 1398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(edx, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); 1399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(edx, FieldOperand(edx, GlobalObject::kBuiltinsOffset)); 1400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int builtins_offset = 1401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSBuiltinsObject::kJSBuiltinsOffset + (id * kPointerSize); 1402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(edi, FieldOperand(edx, builtins_offset)); 1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Builtins::GetCode(id, resolved); 1405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1408d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::LoadContext(Register dst, int context_chain_length) { 1409d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (context_chain_length > 0) { 1410d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Move up the chain of contexts to the context containing the slot. 1411d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mov(dst, Operand(esi, Context::SlotOffset(Context::CLOSURE_INDEX))); 1412d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load the function context (which is the incoming, outer context). 1413d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mov(dst, FieldOperand(dst, JSFunction::kContextOffset)); 1414d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 1; i < context_chain_length; i++) { 1415d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mov(dst, Operand(dst, Context::SlotOffset(Context::CLOSURE_INDEX))); 1416d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mov(dst, FieldOperand(dst, JSFunction::kContextOffset)); 1417d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1418d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // The context may be an intermediate context, not a function context. 1419d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mov(dst, Operand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX))); 1420d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { // Slot is in the current function context. 1421d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // The context may be an intermediate context, not a function context. 1422d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mov(dst, Operand(esi, Context::SlotOffset(Context::FCONTEXT_INDEX))); 1423d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1424d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1425d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1426d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1427d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Ret() { 1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ret(0); 1430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1433e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::Drop(int stack_elements) { 1434e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (stack_elements > 0) { 1435e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke add(Operand(esp), Immediate(stack_elements * kPointerSize)); 1436e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1437e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1438e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1439e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1440e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::Move(Register dst, Handle<Object> value) { 1441e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke mov(dst, value); 1442e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1443e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1444e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SetCounter(StatsCounter* counter, int value) { 1446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_native_code_counters && counter->Enabled()) { 1447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(Operand::StaticVariable(ExternalReference(counter)), Immediate(value)); 1448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::IncrementCounter(StatsCounter* counter, int value) { 1453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(value > 0); 1454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_native_code_counters && counter->Enabled()) { 1455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand operand = Operand::StaticVariable(ExternalReference(counter)); 1456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (value == 1) { 1457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inc(operand); 1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block add(operand, Immediate(value)); 1460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::DecrementCounter(StatsCounter* counter, int value) { 1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(value > 0); 1467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_native_code_counters && counter->Enabled()) { 1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand operand = Operand::StaticVariable(ExternalReference(counter)); 1469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (value == 1) { 1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block dec(operand); 1471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block sub(operand, Immediate(value)); 1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1478d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid MacroAssembler::IncrementCounter(Condition cc, 1479d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke StatsCounter* counter, 1480d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke int value) { 1481d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ASSERT(value > 0); 1482d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (FLAG_native_code_counters && counter->Enabled()) { 1483d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label skip; 1484d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke j(NegateCondition(cc), &skip); 1485d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke pushfd(); 1486d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke IncrementCounter(counter, value); 1487d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke popfd(); 1488d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke bind(&skip); 1489d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 1490d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 1491d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1492d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1493d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid MacroAssembler::DecrementCounter(Condition cc, 1494d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke StatsCounter* counter, 1495d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke int value) { 1496d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ASSERT(value > 0); 1497d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (FLAG_native_code_counters && counter->Enabled()) { 1498d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label skip; 1499d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke j(NegateCondition(cc), &skip); 1500d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke pushfd(); 1501d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke DecrementCounter(counter, value); 1502d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke popfd(); 1503d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke bind(&skip); 1504d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 1505d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 1506d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1507d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Assert(Condition cc, const char* msg) { 1509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_debug_code) Check(cc, msg); 1510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Check(Condition cc, const char* msg) { 1514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label L; 1515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(cc, &L, taken); 1516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Abort(msg); 1517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // will not return here 1518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&L); 1519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Abort(const char* msg) { 1523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We want to pass the msg string like a smi to avoid GC 1524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // problems, however msg is not guaranteed to be aligned 1525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // properly. Instead, we pass an aligned pointer that is 1526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // a proper v8 smi, but also pass the alignment difference 1527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // from the real pointer as a smi. 1528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block intptr_t p1 = reinterpret_cast<intptr_t>(msg); 1529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block intptr_t p0 = (p1 & ~kSmiTagMask) + kSmiTag; 1530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(reinterpret_cast<Object*>(p0)->IsSmi()); 1531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 1532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (msg != NULL) { 1533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RecordComment("Abort message: "); 1534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RecordComment(msg); 1535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1537d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Disable stub call restrictions to always allow calls to abort. 1538d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block set_allow_stub_calls(true); 1539d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(eax); 1541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Immediate(p0)); 1542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Immediate(reinterpret_cast<intptr_t>(Smi::FromInt(p1 - p0)))); 1543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CallRuntime(Runtime::kAbort, 2); 1544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // will not return here 1545d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int3(); 1546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1549d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register object1, 1550d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Register object2, 1551d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Register scratch1, 1552d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Register scratch2, 1553d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label* failure) { 1554d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Check that both objects are not smis. 1555d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ASSERT_EQ(0, kSmiTag); 1556d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke mov(scratch1, Operand(object1)); 1557d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke and_(scratch1, Operand(object2)); 1558d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke test(scratch1, Immediate(kSmiTagMask)); 1559d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke j(zero, failure); 1560d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1561d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Load instance type for both strings. 1562d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke mov(scratch1, FieldOperand(object1, HeapObject::kMapOffset)); 1563d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke mov(scratch2, FieldOperand(object2, HeapObject::kMapOffset)); 1564d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke movzx_b(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset)); 1565d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke movzx_b(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset)); 1566d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1567d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Check that both are flat ascii strings. 1568d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke const int kFlatAsciiStringMask = 1569d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; 1570d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke const int kFlatAsciiStringTag = ASCII_STRING_TYPE; 1571d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Interleave bits from both instance types and compare them in one check. 1572d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ASSERT_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3)); 1573d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke and_(scratch1, kFlatAsciiStringMask); 1574d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke and_(scratch2, kFlatAsciiStringMask); 1575d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke lea(scratch1, Operand(scratch1, scratch2, times_8, 0)); 1576d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke cmp(scratch1, kFlatAsciiStringTag | (kFlatAsciiStringTag << 3)); 1577d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke j(not_equal, failure); 1578d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 1579d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1580d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCodePatcher::CodePatcher(byte* address, int size) 1582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : address_(address), size_(size), masm_(address, size + Assembler::kGap) { 1583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Create a new macro assembler pointing to the address of the code to patch. 1584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The size is adjusted with kGap on order for the assembler to generate size 1585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // bytes of instructions without failing with buffer size constraints. 1586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); 1587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCodePatcher::~CodePatcher() { 1591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Indicate that code has changed. 1592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CPU::FlushICache(address_, size_); 1593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the code was patched as expected. 1595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(masm_.pc_ == address_ + size_); 1596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); 1597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 1601