macro-assembler-x64.cc revision 756813857a4c2a4d8ad2e805969d5768d3cf43a0
1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2009 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h" 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 30f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_X64) 31f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "bootstrapper.h" 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "codegen-inl.h" 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "assembler-x64.h" 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "macro-assembler-x64.h" 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "serialize.h" 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "debug.h" 389dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen#include "heap.h" 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockMacroAssembler::MacroAssembler(void* buffer, int size) 443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block : Assembler(buffer, size), 453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block generating_stub_(false), 463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block allow_stub_calls_(true), 473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block code_object_(Heap::undefined_value()) { 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index) { 526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(destination, Operand(kRootRegister, index << kPointerSizeLog2)); 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsenvoid MacroAssembler::StoreRoot(Register source, Heap::RootListIndex index) { 5725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen movq(Operand(kRootRegister, index << kPointerSizeLog2), source); 5825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen} 5925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen 6025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::PushRoot(Heap::RootListIndex index) { 626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block push(Operand(kRootRegister, index << kPointerSizeLog2)); 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) { 676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block cmpq(with, Operand(kRootRegister, index << kPointerSizeLog2)); 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::CompareRoot(Operand with, Heap::RootListIndex index) { 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadRoot(kScratchRegister, index); 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(with, kScratchRegister); 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 77d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::StackLimitCheck(Label* on_stack_overflow) { 78d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block CompareRoot(rsp, Heap::kStackLimitRootIndex); 79d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block j(below, on_stack_overflow); 80d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 81d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 82d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 836ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::RecordWriteHelper(Register object, 846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register addr, 856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch) { 866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (FLAG_debug_code) { 876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the object is not in new space. 886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label not_in_new_space; 896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block InNewSpace(object, scratch, not_equal, ¬_in_new_space); 906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Abort("new-space object passed to RecordWriteHelper"); 916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block bind(¬_in_new_space); 926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute the page start address from the heap object pointer, and reuse 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the 'object' register for it. 967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch and_(object, Immediate(~Page::kPageAlignmentMask)); 977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Compute number of region covering addr. See Page::GetRegionNumberForAddress 997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // method for more details. 1007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch shrl(addr, Immediate(Page::kRegionSizeLog2)); 1019dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen andl(addr, Immediate(Page::kPageAlignmentMask >> Page::kRegionSizeLog2)); 1027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Set dirty mark for region. 1047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch bts(Operand(object, Page::kDirtyFlagOffset), addr); 1057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 1067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::RecordWrite(Register object, 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset, 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register value, 1119dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Register index) { 1124515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // The compiled code assumes that record write doesn't change the 1134515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // context register, so we check that none of the clobbered 1144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // registers are rsi. 1159dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen ASSERT(!object.is(rsi) && !value.is(rsi) && !index.is(rsi)); 1164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 1177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // First, check if a write barrier is even needed. The tests below 1187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // catch stores of Smis and stores into young gen. 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label done; 1203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block JumpIfSmi(value, &done); 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1229dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen RecordWriteNonSmi(object, offset, value, index); 1233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bind(&done); 1244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 1254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Clobber all input registers when running with the debug-code flag 1264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // turned on to provoke errors. This clobbering repeats the 1274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // clobbering done inside RecordWriteNonSmi but it's necessary to 1284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // avoid having the fast case for smis leave the registers 1294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // unchanged. 1304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (FLAG_debug_code) { 1316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE); 1326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE); 1339dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen movq(index, BitCast<int64_t>(kZapValue), RelocInfo::NONE); 1344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 1353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 1363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1388defd9ff6930b4e24729971a61cf7469daf119beSteve Blockvoid MacroAssembler::RecordWrite(Register object, 1398defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register address, 1408defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register value) { 1418defd9ff6930b4e24729971a61cf7469daf119beSteve Block // The compiled code assumes that record write doesn't change the 1428defd9ff6930b4e24729971a61cf7469daf119beSteve Block // context register, so we check that none of the clobbered 1438defd9ff6930b4e24729971a61cf7469daf119beSteve Block // registers are esi. 1448defd9ff6930b4e24729971a61cf7469daf119beSteve Block ASSERT(!object.is(rsi) && !value.is(rsi) && !address.is(rsi)); 1458defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1468defd9ff6930b4e24729971a61cf7469daf119beSteve Block // First, check if a write barrier is even needed. The tests below 1478defd9ff6930b4e24729971a61cf7469daf119beSteve Block // catch stores of Smis and stores into young gen. 1488defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label done; 1498defd9ff6930b4e24729971a61cf7469daf119beSteve Block JumpIfSmi(value, &done); 1508defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1518defd9ff6930b4e24729971a61cf7469daf119beSteve Block InNewSpace(object, value, equal, &done); 1528defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1538defd9ff6930b4e24729971a61cf7469daf119beSteve Block RecordWriteHelper(object, address, value); 1548defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1558defd9ff6930b4e24729971a61cf7469daf119beSteve Block bind(&done); 1568defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1578defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Clobber all input registers when running with the debug-code flag 1588defd9ff6930b4e24729971a61cf7469daf119beSteve Block // turned on to provoke errors. 1598defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (FLAG_debug_code) { 1608defd9ff6930b4e24729971a61cf7469daf119beSteve Block movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE); 1618defd9ff6930b4e24729971a61cf7469daf119beSteve Block movq(address, BitCast<int64_t>(kZapValue), RelocInfo::NONE); 1628defd9ff6930b4e24729971a61cf7469daf119beSteve Block movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE); 1638defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 1648defd9ff6930b4e24729971a61cf7469daf119beSteve Block} 1658defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1668defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::RecordWriteNonSmi(Register object, 1683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int offset, 1693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register scratch, 1709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Register index) { 1713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label done; 1724515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 1734515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (FLAG_debug_code) { 1744515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Label okay; 1754515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke JumpIfNotSmi(object, &okay); 1764515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Abort("MacroAssembler::RecordWriteNonSmi cannot deal with smis"); 1774515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke bind(&okay); 1789dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 1799dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (offset == 0) { 1809dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // index must be int32. 1819dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Register tmp = index.is(rax) ? rbx : rax; 1829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen push(tmp); 1839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen movl(tmp, index); 1849dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen cmpq(tmp, index); 1859dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Check(equal, "Index register for RecordWrite must be untagged int32."); 1869dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen pop(tmp); 1879dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 1884515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 1894515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 1907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Test that the object address is not in the new space. We cannot 1917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // update page dirty marks for new space pages. 1926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block InNewSpace(object, scratch, equal, &done); 1936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // The offset is relative to a tagged or untagged HeapObject pointer, 1956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // so either offset or offset + kHeapObjectTag must be a 1966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // multiple of kPointerSize. 1976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(IsAligned(offset, kPointerSize) || 1986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block IsAligned(offset + kHeapObjectTag, kPointerSize)); 1996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2009dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Register dst = index; 2017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (offset != 0) { 2027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch lea(dst, Operand(object, offset)); 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 2047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // array access: calculate the destination address in the same manner as 2057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // KeyedStoreIC::GenerateGeneric. 2067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch lea(dst, FieldOperand(object, 2079dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen index, 2089dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen times_pointer_size, 2097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch FixedArray::kHeaderSize)); 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch RecordWriteHelper(object, dst, scratch); 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&done); 2144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 2154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Clobber all input registers when running with the debug-code flag 2164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // turned on to provoke errors. 2174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (FLAG_debug_code) { 2186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE); 2196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(scratch, BitCast<int64_t>(kZapValue), RelocInfo::NONE); 2209dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen movq(index, BitCast<int64_t>(kZapValue), RelocInfo::NONE); 2216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 2226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 2236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2256ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::InNewSpace(Register object, 2266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch, 2276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Condition cc, 2286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label* branch) { 2296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (Serializer::enabled()) { 2306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Can't do arithmetic on external references if it might get serialized. 2316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // The mask isn't really an address. We load it as an external reference in 2326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // case the size of the new space is different between the snapshot maker 2336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // and the running system. 2346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (scratch.is(object)) { 2356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(kScratchRegister, ExternalReference::new_space_mask()); 2366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block and_(scratch, kScratchRegister); 2376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 2386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(scratch, ExternalReference::new_space_mask()); 2396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block and_(scratch, object); 2406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 2416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(kScratchRegister, ExternalReference::new_space_start()); 2426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block cmpq(scratch, kScratchRegister); 2436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block j(cc, branch); 2446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 2456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(is_int32(static_cast<int64_t>(Heap::NewSpaceMask()))); 2466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block intptr_t new_space_start = 2476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block reinterpret_cast<intptr_t>(Heap::NewSpaceStart()); 2486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(kScratchRegister, -new_space_start, RelocInfo::NONE); 2496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (scratch.is(object)) { 2506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block addq(scratch, kScratchRegister); 2516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 2526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block lea(scratch, Operand(object, kScratchRegister, times_1, 0)); 2536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 2546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block and_(scratch, Immediate(static_cast<int32_t>(Heap::NewSpaceMask()))); 2556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block j(cc, branch); 2564515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Assert(Condition cc, const char* msg) { 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_debug_code) Check(cc, msg); 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 265756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid MacroAssembler::AssertFastElements(Register elements) { 266756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (FLAG_debug_code) { 267756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Label ok; 268756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CompareRoot(FieldOperand(elements, HeapObject::kMapOffset), 269756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Heap::kFixedArrayMapRootIndex); 270756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick j(equal, &ok); 271756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CompareRoot(FieldOperand(elements, HeapObject::kMapOffset), 272756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Heap::kFixedCOWArrayMapRootIndex); 273756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick j(equal, &ok); 274756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Abort("JSObject with fast elements map has slow elements"); 275756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick bind(&ok); 276756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 277756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick} 278756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 279756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Check(Condition cc, const char* msg) { 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label L; 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(cc, &L); 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Abort(msg); 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // will not return here 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&L); 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2896ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::CheckStackAlignment() { 2906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int frame_alignment = OS::ActivationFrameAlignment(); 2916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int frame_alignment_mask = frame_alignment - 1; 2926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (frame_alignment > kPointerSize) { 2936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(IsPowerOf2(frame_alignment)); 2946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label alignment_as_expected; 2956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block testq(rsp, Immediate(frame_alignment_mask)); 2966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block j(zero, &alignment_as_expected); 2976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Abort if stack is not aligned. 2986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int3(); 2996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block bind(&alignment_as_expected); 3006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 3026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::NegativeZeroTest(Register result, 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register op, 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* then_label) { 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label ok; 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block testl(result, result); 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(not_zero, &ok); 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block testl(op, op); 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(sign, then_label); 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&ok); 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Abort(const char* msg) { 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We want to pass the msg string like a smi to avoid GC 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // problems, however msg is not guaranteed to be aligned 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // properly. Instead, we pass an aligned pointer that is 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // a proper v8 smi, but also pass the alignment difference 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // from the real pointer as a smi. 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block intptr_t p1 = reinterpret_cast<intptr_t>(msg); 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block intptr_t p0 = (p1 & ~kSmiTagMask) + kSmiTag; 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Note: p0 might not be a valid Smi *value*, but it has a valid Smi tag. 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(reinterpret_cast<Object*>(p0)->IsSmi()); 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (msg != NULL) { 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RecordComment("Abort message: "); 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RecordComment(msg); 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 332d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Disable stub call restrictions to always allow calls to abort. 333d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block set_allow_stub_calls(true); 334d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(rax); 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, p0, RelocInfo::NONE); 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(kScratchRegister); 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, 339d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(p1 - p0))), 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::NONE); 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(kScratchRegister); 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CallRuntime(Runtime::kAbort, 2); 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // will not return here 344d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int3(); 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CallStub(CodeStub* stub) { 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(allow_stub_calls()); // calls are not allowed in some stubs 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Call(stub->GetCode(), RelocInfo::CODE_TARGET); 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 354bb769b257e753aafcbd96767abb2abc645eaa20cBen MurdochObject* MacroAssembler::TryCallStub(CodeStub* stub) { 355bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch ASSERT(allow_stub_calls()); // Calls are not allowed in some stubs. 356bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Object* result = stub->TryGetCode(); 357bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if (!result->IsFailure()) { 358bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch call(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET); 359bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } 360bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch return result; 361bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 362bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 363bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 364e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::TailCallStub(CodeStub* stub) { 365e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(allow_stub_calls()); // calls are not allowed in some stubs 366e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Jump(stub->GetCode(), RelocInfo::CODE_TARGET); 367e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 368e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 369e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 370bb769b257e753aafcbd96767abb2abc645eaa20cBen MurdochObject* MacroAssembler::TryTailCallStub(CodeStub* stub) { 371bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch ASSERT(allow_stub_calls()); // Calls are not allowed in some stubs. 372bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Object* result = stub->TryGetCode(); 373bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if (!result->IsFailure()) { 374bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch jmp(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET); 375bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } 376bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch return result; 377bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 378bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 379bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::StubReturn(int argc) { 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(argc >= 1 && generating_stub()); 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ret((argc - 1) * kPointerSize); 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::IllegalOperation(int num_arguments) { 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (num_arguments > 0) { 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addq(rsp, Immediate(num_arguments * kPointerSize)); 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadRoot(rax, Heap::kUndefinedValueRootIndex); 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CallRuntime(Runtime::FunctionId id, int num_arguments) { 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CallRuntime(Runtime::FunctionForId(id), num_arguments); 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 399bb769b257e753aafcbd96767abb2abc645eaa20cBen MurdochObject* MacroAssembler::TryCallRuntime(Runtime::FunctionId id, 400bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch int num_arguments) { 401bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch return TryCallRuntime(Runtime::FunctionForId(id), num_arguments); 402bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 403bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 404bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) { 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the expected number of arguments of the runtime function is 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // constant, we check that the actual number of arguments match the 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // expectation. 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (f->nargs >= 0 && f->nargs != num_arguments) { 410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block IllegalOperation(num_arguments); 411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // TODO(1236192): Most runtime routines don't need the number of 4154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // arguments passed in because it is constant. At some point we 4164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // should remove this need and make the runtime routine entry code 4174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // smarter. 4188defd9ff6930b4e24729971a61cf7469daf119beSteve Block Set(rax, num_arguments); 4194515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke movq(rbx, ExternalReference(f)); 4204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke CEntryStub ces(f->result_size); 4214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke CallStub(&ces); 422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 425bb769b257e753aafcbd96767abb2abc645eaa20cBen MurdochObject* MacroAssembler::TryCallRuntime(Runtime::Function* f, 426bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch int num_arguments) { 427bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if (f->nargs >= 0 && f->nargs != num_arguments) { 428bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch IllegalOperation(num_arguments); 429bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Since we did not call the stub, there was no allocation failure. 430bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Return some non-failure object. 431bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch return Heap::undefined_value(); 432bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } 433bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 434bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // TODO(1236192): Most runtime routines don't need the number of 435bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // arguments passed in because it is constant. At some point we 436bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // should remove this need and make the runtime routine entry code 437bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // smarter. 438bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Set(rax, num_arguments); 439bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch movq(rbx, ExternalReference(f)); 440bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch CEntryStub ces(f->result_size); 441bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch return TryCallStub(&ces); 442bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 443bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 444bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 445402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::CallExternalReference(const ExternalReference& ext, 446402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu int num_arguments) { 4478defd9ff6930b4e24729971a61cf7469daf119beSteve Block Set(rax, num_arguments); 448402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu movq(rbx, ext); 449402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 450402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu CEntryStub stub(1); 451402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu CallStub(&stub); 452402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 453402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 454402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 4556ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::TailCallExternalReference(const ExternalReference& ext, 4566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int num_arguments, 4576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int result_size) { 458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rsp[0] : return address 460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rsp[8] : argument num_arguments - 1 461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ... 462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rsp[8 * num_arguments] : argument 0 (receiver) 463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // TODO(1236192): Most runtime routines don't need the number of 466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // arguments passed in because it is constant. At some point we 467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // should remove this need and make the runtime routine entry code 468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // smarter. 4698defd9ff6930b4e24729971a61cf7469daf119beSteve Block Set(rax, num_arguments); 4706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JumpToExternalReference(ext, result_size); 471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4746ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::TailCallRuntime(Runtime::FunctionId fid, 4756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int num_arguments, 4766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int result_size) { 4776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block TailCallExternalReference(ExternalReference(fid), num_arguments, result_size); 4786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 4796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 4806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 481bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochstatic int Offset(ExternalReference ref0, ExternalReference ref1) { 482bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch int64_t offset = (ref0.address() - ref1.address()); 483bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Check that fits into int. 484bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch ASSERT(static_cast<int>(offset) == offset); 485bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch return static_cast<int>(offset); 486bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 487bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 488bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 489bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid MacroAssembler::PushHandleScope(Register scratch) { 490bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch ExternalReference extensions_address = 491bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch ExternalReference::handle_scope_extensions_address(); 492bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch const int kExtensionsOffset = 0; 493bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch const int kNextOffset = Offset( 494bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch ExternalReference::handle_scope_next_address(), 495bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch extensions_address); 496bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch const int kLimitOffset = Offset( 497bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch ExternalReference::handle_scope_limit_address(), 498bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch extensions_address); 499bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 500bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Push the number of extensions, smi-tagged so the gc will ignore it. 501bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch movq(kScratchRegister, extensions_address); 502bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch movq(scratch, Operand(kScratchRegister, kExtensionsOffset)); 503bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch movq(Operand(kScratchRegister, kExtensionsOffset), Immediate(0)); 504bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Integer32ToSmi(scratch, scratch); 505bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch push(scratch); 506bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Push next and limit pointers which will be wordsize aligned and 507bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // hence automatically smi tagged. 508bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch push(Operand(kScratchRegister, kNextOffset)); 509bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch push(Operand(kScratchRegister, kLimitOffset)); 510bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 511bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 512bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 513bb769b257e753aafcbd96767abb2abc645eaa20cBen MurdochObject* MacroAssembler::PopHandleScopeHelper(Register saved, 514bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Register scratch, 515bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch bool gc_allowed) { 516bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch ExternalReference extensions_address = 517bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch ExternalReference::handle_scope_extensions_address(); 518bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch const int kExtensionsOffset = 0; 519bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch const int kNextOffset = Offset( 520bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch ExternalReference::handle_scope_next_address(), 521bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch extensions_address); 522bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch const int kLimitOffset = Offset( 523bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch ExternalReference::handle_scope_limit_address(), 524bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch extensions_address); 525bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 526bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Object* result = NULL; 527bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Label write_back; 528bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch movq(kScratchRegister, extensions_address); 529bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch cmpq(Operand(kScratchRegister, kExtensionsOffset), Immediate(0)); 530bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch j(equal, &write_back); 531bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch push(saved); 532bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if (gc_allowed) { 533bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch CallRuntime(Runtime::kDeleteHandleScopeExtensions, 0); 534bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } else { 535bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch result = TryCallRuntime(Runtime::kDeleteHandleScopeExtensions, 0); 536bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if (result->IsFailure()) return result; 537bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } 538bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch pop(saved); 539bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch movq(kScratchRegister, extensions_address); 540bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 541bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch bind(&write_back); 542bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch pop(Operand(kScratchRegister, kLimitOffset)); 543bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch pop(Operand(kScratchRegister, kNextOffset)); 544bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch pop(scratch); 545bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch SmiToInteger32(scratch, scratch); 546bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch movq(Operand(kScratchRegister, kExtensionsOffset), scratch); 547bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 548bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch return result; 549bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 550bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 551bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 552bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid MacroAssembler::PopHandleScope(Register saved, Register scratch) { 553bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch PopHandleScopeHelper(saved, scratch, true); 554bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 555bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 556bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 557bb769b257e753aafcbd96767abb2abc645eaa20cBen MurdochObject* MacroAssembler::TryPopHandleScope(Register saved, Register scratch) { 558bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch return PopHandleScopeHelper(saved, scratch, false); 559bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 560bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 561bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 5626ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::JumpToExternalReference(const ExternalReference& ext, 5636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int result_size) { 564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the entry point and jump to the C entry runtime stub. 565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rbx, ext); 566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CEntryStub ces(result_size); 5673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block jmp(ces.GetCode(), RelocInfo::CODE_TARGET); 568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 571402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag) { 572402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Calls are not allowed in some stubs. 573402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ASSERT(flag == JUMP_FUNCTION || allow_stub_calls()); 574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 575402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Rely on the assertion to check that the number of provided 576402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // arguments match the expected number of arguments. Fake a 577402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // parameter count to avoid emitting code to do the check. 578402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ParameterCount expected(0); 579402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GetBuiltinEntry(rdx, id); 580402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu InvokeCode(rdx, expected, expected, flag); 581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 583402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 584402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) { 5856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(!target.is(rdi)); 5866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 5876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Load the builtins object into target register. 5886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(target, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); 5896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(target, FieldOperand(target, GlobalObject::kBuiltinsOffset)); 5906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 591402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Load the JavaScript builtin function from the builtins object. 5926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(rdi, FieldOperand(target, JSBuiltinsObject::OffsetOfFunctionWithId(id))); 5936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 5946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Load the code entry point from the builtins object. 5956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(target, FieldOperand(target, JSBuiltinsObject::OffsetOfCodeWithId(id))); 5966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (FLAG_debug_code) { 5976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Make sure the code objects in the builtins object and in the 5986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // builtin function are the same. 5996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block push(target); 600756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick movq(target, FieldOperand(rdi, JSFunction::kCodeOffset)); 6016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block cmpq(target, Operand(rsp, 0)); 6026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Assert(equal, "Builtin code object changed"); 6036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block pop(target); 6046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 6056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block lea(target, FieldOperand(target, Code::kHeaderSize)); 606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Set(Register dst, int64_t x) { 610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (x == 0) { 6118defd9ff6930b4e24729971a61cf7469daf119beSteve Block xorl(dst, dst); 612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (is_int32(x)) { 613d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block movq(dst, Immediate(static_cast<int32_t>(x))); 614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (is_uint32(x)) { 615d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block movl(dst, Immediate(static_cast<uint32_t>(x))); 616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(dst, x, RelocInfo::NONE); 618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Set(const Operand& dst, int64_t x) { 6229dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (is_int32(x)) { 623d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block movq(dst, Immediate(static_cast<int32_t>(x))); 624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, x, RelocInfo::NONE); 626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(dst, kScratchRegister); 627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ---------------------------------------------------------------------------- 631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Smi tagging, untagging and tag detection. 632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockstatic int kSmiShift = kSmiTagSize + kSmiShiftSize; 634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6358defd9ff6930b4e24729971a61cf7469daf119beSteve BlockRegister MacroAssembler::GetSmiConstant(Smi* source) { 6368defd9ff6930b4e24729971a61cf7469daf119beSteve Block int value = source->value(); 6378defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (value == 0) { 6388defd9ff6930b4e24729971a61cf7469daf119beSteve Block xorl(kScratchRegister, kScratchRegister); 6398defd9ff6930b4e24729971a61cf7469daf119beSteve Block return kScratchRegister; 6408defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 6418defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (value == 1) { 6428defd9ff6930b4e24729971a61cf7469daf119beSteve Block return kSmiConstantRegister; 6438defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 6448defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(kScratchRegister, source); 6458defd9ff6930b4e24729971a61cf7469daf119beSteve Block return kScratchRegister; 6468defd9ff6930b4e24729971a61cf7469daf119beSteve Block} 6478defd9ff6930b4e24729971a61cf7469daf119beSteve Block 6488defd9ff6930b4e24729971a61cf7469daf119beSteve Blockvoid MacroAssembler::LoadSmiConstant(Register dst, Smi* source) { 6498defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (FLAG_debug_code) { 6508defd9ff6930b4e24729971a61cf7469daf119beSteve Block movq(dst, 6518defd9ff6930b4e24729971a61cf7469daf119beSteve Block reinterpret_cast<uint64_t>(Smi::FromInt(kSmiConstantRegisterValue)), 6528defd9ff6930b4e24729971a61cf7469daf119beSteve Block RelocInfo::NONE); 6538defd9ff6930b4e24729971a61cf7469daf119beSteve Block cmpq(dst, kSmiConstantRegister); 6548defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (allow_stub_calls()) { 6558defd9ff6930b4e24729971a61cf7469daf119beSteve Block Assert(equal, "Uninitialized kSmiConstantRegister"); 6568defd9ff6930b4e24729971a61cf7469daf119beSteve Block } else { 6578defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label ok; 6588defd9ff6930b4e24729971a61cf7469daf119beSteve Block j(equal, &ok); 6598defd9ff6930b4e24729971a61cf7469daf119beSteve Block int3(); 6608defd9ff6930b4e24729971a61cf7469daf119beSteve Block bind(&ok); 6618defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 6628defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 6638defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (source->value() == 0) { 6648defd9ff6930b4e24729971a61cf7469daf119beSteve Block xorl(dst, dst); 6658defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 6668defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 6678defd9ff6930b4e24729971a61cf7469daf119beSteve Block int value = source->value(); 6688defd9ff6930b4e24729971a61cf7469daf119beSteve Block bool negative = value < 0; 6698defd9ff6930b4e24729971a61cf7469daf119beSteve Block unsigned int uvalue = negative ? -value : value; 6708defd9ff6930b4e24729971a61cf7469daf119beSteve Block 6718defd9ff6930b4e24729971a61cf7469daf119beSteve Block switch (uvalue) { 6728defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 9: 6738defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_8, 0)); 6748defd9ff6930b4e24729971a61cf7469daf119beSteve Block break; 6758defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 8: 6768defd9ff6930b4e24729971a61cf7469daf119beSteve Block xorl(dst, dst); 6778defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(dst, kSmiConstantRegister, times_8, 0)); 6788defd9ff6930b4e24729971a61cf7469daf119beSteve Block break; 6798defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 4: 6808defd9ff6930b4e24729971a61cf7469daf119beSteve Block xorl(dst, dst); 6818defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(dst, kSmiConstantRegister, times_4, 0)); 6828defd9ff6930b4e24729971a61cf7469daf119beSteve Block break; 6838defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 5: 6848defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_4, 0)); 6858defd9ff6930b4e24729971a61cf7469daf119beSteve Block break; 6868defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 3: 6878defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_2, 0)); 6888defd9ff6930b4e24729971a61cf7469daf119beSteve Block break; 6898defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 2: 6908defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_1, 0)); 6918defd9ff6930b4e24729971a61cf7469daf119beSteve Block break; 6928defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 1: 6938defd9ff6930b4e24729971a61cf7469daf119beSteve Block movq(dst, kSmiConstantRegister); 6948defd9ff6930b4e24729971a61cf7469daf119beSteve Block break; 6958defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 0: 6968defd9ff6930b4e24729971a61cf7469daf119beSteve Block UNREACHABLE(); 6978defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 6988defd9ff6930b4e24729971a61cf7469daf119beSteve Block default: 6998defd9ff6930b4e24729971a61cf7469daf119beSteve Block movq(dst, reinterpret_cast<uint64_t>(source), RelocInfo::NONE); 7008defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 7018defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 7028defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (negative) { 7038defd9ff6930b4e24729971a61cf7469daf119beSteve Block neg(dst); 7048defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 7058defd9ff6930b4e24729971a61cf7469daf119beSteve Block} 7068defd9ff6930b4e24729971a61cf7469daf119beSteve Block 707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Integer32ToSmi(Register dst, Register src) { 708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, kSmiTag); 7093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src)) { 7103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movl(dst, src); 711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 7123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(kSmiShift)); 713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Integer32ToSmi(Register dst, 717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_overflow) { 719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, kSmiTag); 7203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // 32-bit integer always fits in a long smi. 721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!dst.is(src)) { 722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movl(dst, src); 723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 7243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(kSmiShift)); 725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7289dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::Integer32ToSmiField(const Operand& dst, Register src) { 7299dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (FLAG_debug_code) { 7309dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen testb(dst, Immediate(0x01)); 7319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Label ok; 7329dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen j(zero, &ok); 7339dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (allow_stub_calls()) { 7349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Abort("Integer32ToSmiField writing to non-smi location"); 7359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } else { 7369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen int3(); 7379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 7389dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen bind(&ok); 7399dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 7409dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen ASSERT(kSmiShift % kBitsPerByte == 0); 7419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen movl(Operand(dst, kSmiShift / kBitsPerByte), src); 7429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 7439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 7449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 7453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::Integer64PlusConstantToSmi(Register dst, 7463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register src, 7473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int constant) { 7483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (dst.is(src)) { 7493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block addq(dst, Immediate(constant)); 7503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 7513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block lea(dst, Operand(src, constant)); 7523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 7533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(kSmiShift)); 754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiToInteger32(Register dst, Register src) { 758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, kSmiTag); 759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!dst.is(src)) { 7603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 7623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shr(dst, Immediate(kSmiShift)); 763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid MacroAssembler::SmiToInteger32(Register dst, const Operand& src) { 7677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch movl(dst, Operand(src, kSmiShift / kBitsPerByte)); 7687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 7697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 7707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiToInteger64(Register dst, Register src) { 772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, kSmiTag); 7733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src)) { 7743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 7763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block sar(dst, Immediate(kSmiShift)); 777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7809dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::SmiToInteger64(Register dst, const Operand& src) { 7819dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen movsxlq(dst, Operand(src, kSmiShift / kBitsPerByte)); 7829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 7839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 7849dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 7853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiTest(Register src) { 7863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testq(src, src); 787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(Register dst, Register src) { 7913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block cmpq(dst, src); 792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(Register dst, Smi* src) { 7963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 7973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (src->value() == 0) { 7983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testq(dst, dst); 7993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 800756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Register constant_reg = GetSmiConstant(src); 801756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick cmpq(dst, constant_reg); 802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 806f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid MacroAssembler::SmiCompare(Register dst, const Operand& src) { 8076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block cmpq(dst, src); 8086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 8096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(const Operand& dst, Register src) { 8123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block cmpq(dst, src); 813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(const Operand& dst, Smi* src) { 8177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch cmpl(Operand(dst, kSmiShift / kBitsPerByte), Immediate(src->value())); 818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8219dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::SmiCompareInteger32(const Operand& dst, Register src) { 8229dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen cmpl(Operand(dst, kSmiShift / kBitsPerByte), src); 8239dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 8249dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 8259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 8263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::PositiveSmiTimesPowerOfTwoToInteger64(Register dst, 8273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register src, 8283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int power) { 8293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(power >= 0); 8303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(power < 64); 8313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (power == 0) { 8323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiToInteger64(dst, src); 8333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block return; 8343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 8353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src)) { 8363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 8373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 8383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (power < kSmiShift) { 8393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block sar(dst, Immediate(kSmiShift - power)); 8403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (power > kSmiShift) { 8413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(power - kSmiShift)); 8423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid MacroAssembler::PositiveSmiDivPowerOfTwoToInteger32(Register dst, 8477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register src, 8487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch int power) { 8497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT((0 <= power) && (power < 32)); 8507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (dst.is(src)) { 8517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch shr(dst, Immediate(power + kSmiShift)); 8527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 8537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch UNIMPLEMENTED(); // Not used. 8547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 8557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 8567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 8577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 8583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockCondition MacroAssembler::CheckSmi(Register src) { 859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, kSmiTag); 860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block testb(src, Immediate(kSmiTagMask)); 8613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block return zero; 862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCondition MacroAssembler::CheckPositiveSmi(Register src) { 866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, kSmiTag); 8678defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Make mask 0x8000000000000001 and test that both bits are zero. 8683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(kScratchRegister, src); 8693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block rol(kScratchRegister, Immediate(1)); 8708defd9ff6930b4e24729971a61cf7469daf119beSteve Block testb(kScratchRegister, Immediate(3)); 871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return zero; 872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCondition MacroAssembler::CheckBothSmi(Register first, Register second) { 876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (first.is(second)) { 877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return CheckSmi(first); 878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 8798defd9ff6930b4e24729971a61cf7469daf119beSteve Block ASSERT(kSmiTag == 0 && kHeapObjectTag == 1 && kHeapObjectTagMask == 3); 8808defd9ff6930b4e24729971a61cf7469daf119beSteve Block leal(kScratchRegister, Operand(first, second, times_1, 0)); 8818defd9ff6930b4e24729971a61cf7469daf119beSteve Block testb(kScratchRegister, Immediate(0x03)); 8823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block return zero; 883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 886d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeCondition MacroAssembler::CheckBothPositiveSmi(Register first, 887d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Register second) { 888d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (first.is(second)) { 889d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return CheckPositiveSmi(first); 890d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 8918defd9ff6930b4e24729971a61cf7469daf119beSteve Block movq(kScratchRegister, first); 8928defd9ff6930b4e24729971a61cf7469daf119beSteve Block or_(kScratchRegister, second); 893d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke rol(kScratchRegister, Immediate(1)); 894d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke testl(kScratchRegister, Immediate(0x03)); 895d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return zero; 896d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 897d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 898d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 899bb769b257e753aafcbd96767abb2abc645eaa20cBen MurdochCondition MacroAssembler::CheckEitherSmi(Register first, 900bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Register second, 901bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Register scratch) { 902e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (first.is(second)) { 903e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return CheckSmi(first); 904e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 905bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if (scratch.is(second)) { 906bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch andl(scratch, first); 907bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } else { 908bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if (!scratch.is(first)) { 909bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch movl(scratch, first); 910bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } 911bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch andl(scratch, second); 912bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } 913bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch testb(scratch, Immediate(kSmiTagMask)); 914e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return zero; 915e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 916e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 917e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCondition MacroAssembler::CheckIsMinSmi(Register src) { 9198defd9ff6930b4e24729971a61cf7469daf119beSteve Block ASSERT(!src.is(kScratchRegister)); 9208defd9ff6930b4e24729971a61cf7469daf119beSteve Block // If we overflow by subtracting one, it's the minimal smi value. 9218defd9ff6930b4e24729971a61cf7469daf119beSteve Block cmpq(src, kSmiConstantRegister); 9228defd9ff6930b4e24729971a61cf7469daf119beSteve Block return overflow; 923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockCondition MacroAssembler::CheckInteger32ValidSmiValue(Register src) { 9273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // A 32-bit integer value can always be converted to a smi. 9283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block return always; 929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockCondition MacroAssembler::CheckUInteger32ValidSmiValue(Register src) { 9333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // An unsigned 32-bit integer value is valid as long as the high bit 9343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // is not set. 9358defd9ff6930b4e24729971a61cf7469daf119beSteve Block testl(src, src); 9368defd9ff6930b4e24729971a61cf7469daf119beSteve Block return positive; 937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiNeg(Register dst, Register src, Label* on_smi_result) { 9413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (dst.is(src)) { 9423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 9433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(kScratchRegister, src); 9443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block neg(dst); // Low 32 bits are retained as zero by negation. 9453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Test if result is zero or Smi::kMinValue. 9463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block cmpq(dst, kScratchRegister); 9473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(not_equal, on_smi_result); 9483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src, kScratchRegister); 9493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 9503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 9513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block neg(dst); 9523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block cmpq(dst, src); 9533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // If the result is zero or Smi::kMinValue, negation failed to create a smi. 9543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(not_equal, on_smi_result); 955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiAdd(Register dst, 960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2, 962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smi_result) { 963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(src2)); 9646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (on_not_smi_result == NULL) { 9656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // No overflow checking. Use only when it's known that 9666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // overflowing is impossible. 9676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (dst.is(src1)) { 9686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block addq(dst, src2); 9696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 9706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(dst, src1); 9716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block addq(dst, src2); 9726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 9739dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Assert(no_overflow, "Smi addition overflow"); 9746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (dst.is(src1)) { 9759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen movq(kScratchRegister, src1); 9769dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen addq(kScratchRegister, src2); 9779dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen j(overflow, on_not_smi_result); 9789dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen movq(dst, kScratchRegister); 9793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 9803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src1); 9813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block addq(dst, src2); 9823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(overflow, on_not_smi_result); 983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiSub(Register dst, 988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2, 990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smi_result) { 991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(src2)); 992d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (on_not_smi_result == NULL) { 993d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // No overflow checking. Use only when it's known that 994d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // overflowing is impossible (e.g., subtracting two positive smis). 995d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (dst.is(src1)) { 996d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke subq(dst, src2); 997d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else { 998d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke movq(dst, src1); 999d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke subq(dst, src2); 1000d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 10019dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Assert(no_overflow, "Smi subtraction overflow"); 1002d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else if (dst.is(src1)) { 10039dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen cmpq(dst, src2); 10049dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen j(overflow, on_not_smi_result); 10053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block subq(dst, src2); 10063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 10073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src1); 10083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block subq(dst, src2); 10093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(overflow, on_not_smi_result); 1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10146ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::SmiSub(Register dst, 10156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register src1, 1016f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke const Operand& src2, 10176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label* on_not_smi_result) { 10186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (on_not_smi_result == NULL) { 10196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // No overflow checking. Use only when it's known that 10206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // overflowing is impossible (e.g., subtracting two positive smis). 10216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (dst.is(src1)) { 10226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block subq(dst, src2); 10236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 10246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(dst, src1); 10256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block subq(dst, src2); 10266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 10279dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Assert(no_overflow, "Smi subtraction overflow"); 10286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (dst.is(src1)) { 10298defd9ff6930b4e24729971a61cf7469daf119beSteve Block movq(kScratchRegister, src2); 10308defd9ff6930b4e24729971a61cf7469daf119beSteve Block cmpq(src1, kScratchRegister); 10319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen j(overflow, on_not_smi_result); 10328defd9ff6930b4e24729971a61cf7469daf119beSteve Block subq(src1, kScratchRegister); 10336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 10346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(dst, src1); 10356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block subq(dst, src2); 10366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block j(overflow, on_not_smi_result); 10376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 10386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 10396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiMul(Register dst, 1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2, 1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smi_result) { 1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(src2)); 10453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 10463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src1.is(kScratchRegister)); 10473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src2.is(kScratchRegister)); 1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (dst.is(src1)) { 10503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label failure, zero_correct_result; 10513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(kScratchRegister, src1); // Create backup for later testing. 10523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiToInteger64(dst, src1); 10533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block imul(dst, src2); 10543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(overflow, &failure); 10553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 10563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check for negative zero result. If product is zero, and one 10573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // argument is negative, go to slow case. 10583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label correct_result; 10593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testq(dst, dst); 10603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(not_zero, &correct_result); 1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, kScratchRegister); 10633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block xor_(dst, src2); 10643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(positive, &zero_correct_result); // Result was positive zero. 1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bind(&failure); // Reused failure exit, restores src1. 10673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src1, kScratchRegister); 10683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block jmp(on_not_smi_result); 1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bind(&zero_correct_result); 10713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block xor_(dst, dst); 10723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 10733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bind(&correct_result); 10743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 10753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiToInteger64(dst, src1); 10763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block imul(dst, src2); 10773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(overflow, on_not_smi_result); 10783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check for negative zero result. If product is zero, and one 10793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // argument is negative, go to slow case. 10803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label correct_result; 10813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testq(dst, dst); 10823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(not_zero, &correct_result); 10833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // One of src1 and src2 is zero, the check whether the other is 10843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // negative. 10853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(kScratchRegister, src1); 10863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block xor_(kScratchRegister, src2); 10873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(negative, on_not_smi_result); 10883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bind(&correct_result); 10893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiTryAddConstant(Register dst, 1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 10953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Smi* constant, 1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smi_result) { 1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Does not assume that src is a smi. 10983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT_EQ(static_cast<int>(1), static_cast<int>(kSmiTagMask)); 1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, kSmiTag); 11003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 11013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src.is(kScratchRegister)); 1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 11033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block JumpIfNotSmi(src, on_not_smi_result); 11043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register tmp = (dst.is(src) ? kScratchRegister : dst); 11058defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(tmp, constant); 11063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block addq(tmp, src); 11073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(overflow, on_not_smi_result); 11083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (dst.is(src)) { 11093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, tmp); 11103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 11113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 11123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 11133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 11143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiAddConstant(Register dst, Register src, Smi* constant) { 11153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (constant->value() == 0) { 11163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src)) { 11173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 11183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 11198defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 11203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (dst.is(src)) { 11213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 11228defd9ff6930b4e24729971a61cf7469daf119beSteve Block switch (constant->value()) { 11238defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 1: 11248defd9ff6930b4e24729971a61cf7469daf119beSteve Block addq(dst, kSmiConstantRegister); 11258defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 11268defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 2: 11278defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(src, kSmiConstantRegister, times_2, 0)); 11288defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 11298defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 4: 11308defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(src, kSmiConstantRegister, times_4, 0)); 11318defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 11328defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 8: 11338defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(src, kSmiConstantRegister, times_8, 0)); 11348defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 11358defd9ff6930b4e24729971a61cf7469daf119beSteve Block default: 11368defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register constant_reg = GetSmiConstant(constant); 11378defd9ff6930b4e24729971a61cf7469daf119beSteve Block addq(dst, constant_reg); 11388defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 11398defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 11418defd9ff6930b4e24729971a61cf7469daf119beSteve Block switch (constant->value()) { 11428defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 1: 11438defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(src, kSmiConstantRegister, times_1, 0)); 11448defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 11458defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 2: 11468defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(src, kSmiConstantRegister, times_2, 0)); 11478defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 11488defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 4: 11498defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(src, kSmiConstantRegister, times_4, 0)); 11508defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 11518defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 8: 11528defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(src, kSmiConstantRegister, times_8, 0)); 11538defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 11548defd9ff6930b4e24729971a61cf7469daf119beSteve Block default: 11558defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(dst, constant); 11568defd9ff6930b4e24729971a61cf7469daf119beSteve Block addq(dst, src); 11578defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 11588defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1163f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid MacroAssembler::SmiAddConstant(const Operand& dst, Smi* constant) { 1164f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (constant->value() != 0) { 11657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch addl(Operand(dst, kSmiShift / kBitsPerByte), Immediate(constant->value())); 1166f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1167f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1168f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1169f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiAddConstant(Register dst, 1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 11723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Smi* constant, 1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smi_result) { 11743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (constant->value() == 0) { 11753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src)) { 11763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 11783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (dst.is(src)) { 11793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 11803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 11818defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(kScratchRegister, constant); 11828defd9ff6930b4e24729971a61cf7469daf119beSteve Block addq(kScratchRegister, src); 11839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen j(overflow, on_not_smi_result); 11849dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen movq(dst, kScratchRegister); 1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 11868defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(dst, constant); 11873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block addq(dst, src); 11883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(overflow, on_not_smi_result); 11893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 11903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 11913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 11923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 11933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiSubConstant(Register dst, Register src, Smi* constant) { 11943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (constant->value() == 0) { 1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!dst.is(src)) { 11963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 11983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (dst.is(src)) { 11993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 12008defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register constant_reg = GetSmiConstant(constant); 12018defd9ff6930b4e24729971a61cf7469daf119beSteve Block subq(dst, constant_reg); 12023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 12033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (constant->value() == Smi::kMinValue) { 12048defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(dst, constant); 12059dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Adding and subtracting the min-value gives the same result, it only 12069dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // differs on the overflow bit, which we don't check here. 12079dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen addq(dst, src); 1208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 12099dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Subtract by adding the negation. 12108defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(dst, Smi::FromInt(-constant->value())); 12113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block addq(dst, src); 1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiSubConstant(Register dst, 1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 12193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Smi* constant, 1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smi_result) { 12213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (constant->value() == 0) { 12223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src)) { 12233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 12253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (dst.is(src)) { 12263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 12273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (constant->value() == Smi::kMinValue) { 12289dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Subtracting min-value from any non-negative value will overflow. 12299dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // We test the non-negativeness before doing the subtraction. 12309dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen testq(src, src); 12319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen j(not_sign, on_not_smi_result); 12328defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(kScratchRegister, constant); 12333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block subq(dst, kScratchRegister); 12349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } else { 12359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Subtract by adding the negation. 12368defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(kScratchRegister, Smi::FromInt(-constant->value())); 12379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen addq(kScratchRegister, dst); 12383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(overflow, on_not_smi_result); 12399dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen movq(dst, kScratchRegister); 12409dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 12419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } else { 12429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (constant->value() == Smi::kMinValue) { 12439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Subtracting min-value from any non-negative value will overflow. 12449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // We test the non-negativeness before doing the subtraction. 12459dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen testq(src, src); 12469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen j(not_sign, on_not_smi_result); 12478defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(dst, constant); 12489dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Adding and subtracting the min-value gives the same result, it only 12499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // differs on the overflow bit, which we don't check here. 12509dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen addq(dst, src); 12513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 12529dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Subtract by adding the negation. 12538defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(dst, Smi::FromInt(-(constant->value()))); 12543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block addq(dst, src); 12553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(overflow, on_not_smi_result); 12563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiDiv(Register dst, 1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2, 1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smi_result) { 12653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src1.is(kScratchRegister)); 12663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src2.is(kScratchRegister)); 12673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 1268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!src2.is(rax)); 1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!src2.is(rdx)); 1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!src1.is(rdx)); 1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for 0 divisor (result is +/-Infinity). 1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label positive_divisor; 12743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testq(src2, src2); 1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(zero, on_not_smi_result); 1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (src1.is(rax)) { 12783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(kScratchRegister, src1); 1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 12803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiToInteger32(rax, src1); 12813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // We need to rule out dividing Smi::kMinValue by -1, since that would 12823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // overflow in idiv and raise an exception. 12833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // We combine this with negative zero test (negative zero only happens 12843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // when dividing zero by a negative number). 12853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // We overshoot a little and go to slow case if we divide min-value 12873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // by any negative value, not just -1. 12883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label safe_div; 12893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testl(rax, Immediate(0x7fffffff)); 12903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(not_zero, &safe_div); 12913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testq(src2, src2); 12923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (src1.is(rax)) { 12933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(positive, &safe_div); 12943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src1, kScratchRegister); 12953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block jmp(on_not_smi_result); 12963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 12973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(negative, on_not_smi_result); 12983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 12993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bind(&safe_div); 1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiToInteger32(src2, src2); 13023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Sign extend src1 into edx:eax. 13033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block cdq(); 1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block idivl(src2); 13053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Integer32ToSmi(src2, src2); 1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the remainder is zero. 1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block testl(rdx, rdx); 13083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (src1.is(rax)) { 13093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label smi_result; 13103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(zero, &smi_result); 13113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src1, kScratchRegister); 13123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block jmp(on_not_smi_result); 13133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bind(&smi_result); 13143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 13153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(not_zero, on_not_smi_result); 13163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 13173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src1) && src1.is(rax)) { 13183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src1, kScratchRegister); 13193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Integer32ToSmi(dst, rax); 1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiMod(Register dst, 1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2, 1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smi_result) { 1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(kScratchRegister)); 1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!src1.is(kScratchRegister)); 1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!src2.is(kScratchRegister)); 1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!src2.is(rax)); 1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!src2.is(rdx)); 1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!src1.is(rdx)); 13343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src1.is(src2)); 1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testq(src2, src2); 1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(zero, on_not_smi_result); 1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (src1.is(rax)) { 13403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(kScratchRegister, src1); 13413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 13423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiToInteger32(rax, src1); 13433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiToInteger32(src2, src2); 13443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Test for the edge case of dividing Smi::kMinValue by -1 (will overflow). 13463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label safe_div; 13473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block cmpl(rax, Immediate(Smi::kMinValue)); 13483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(not_equal, &safe_div); 13493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block cmpl(src2, Immediate(-1)); 13503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(not_equal, &safe_div); 13513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Retag inputs and go slow case. 13523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Integer32ToSmi(src2, src2); 13533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (src1.is(rax)) { 13543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src1, kScratchRegister); 1355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 13563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block jmp(on_not_smi_result); 13573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bind(&safe_div); 13583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Sign extend eax into edx:eax. 1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cdq(); 1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block idivl(src2); 13623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Restore smi tags on inputs. 13633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Integer32ToSmi(src2, src2); 1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (src1.is(rax)) { 13653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src1, kScratchRegister); 1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 13673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check for a negative zero result. If the result is zero, and the 13683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // dividend is negative, go slow to return a floating point negative zero. 13693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label smi_result; 13703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testl(rdx, rdx); 13713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(not_zero, &smi_result); 13723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testq(src1, src1); 1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(negative, on_not_smi_result); 13743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bind(&smi_result); 13753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Integer32ToSmi(dst, rdx); 1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiNot(Register dst, Register src) { 13803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 13813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src.is(kScratchRegister)); 13823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Set tag and padding bits before negating, so that they are zero afterwards. 13833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movl(kScratchRegister, Immediate(~0)); 1384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (dst.is(src)) { 13853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block xor_(dst, kScratchRegister); 1386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 13873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block lea(dst, Operand(src, kScratchRegister, times_1, 0)); 1388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 13893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block not_(dst); 1390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiAnd(Register dst, Register src1, Register src2) { 13943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(src2)); 1395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!dst.is(src1)) { 13963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src1); 1397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block and_(dst, src2); 1399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 14023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiAndConstant(Register dst, Register src, Smi* constant) { 14033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (constant->value() == 0) { 14043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block xor_(dst, dst); 14053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (dst.is(src)) { 14063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 14078defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register constant_reg = GetSmiConstant(constant); 14088defd9ff6930b4e24729971a61cf7469daf119beSteve Block and_(dst, constant_reg); 14093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 14108defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(dst, constant); 14113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block and_(dst, src); 1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiOr(Register dst, Register src1, Register src2) { 1417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!dst.is(src1)) { 14183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src1); 1419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block or_(dst, src2); 1421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 14243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiOrConstant(Register dst, Register src, Smi* constant) { 14253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (dst.is(src)) { 14263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 14278defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register constant_reg = GetSmiConstant(constant); 14288defd9ff6930b4e24729971a61cf7469daf119beSteve Block or_(dst, constant_reg); 14293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 14308defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(dst, constant); 14313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block or_(dst, src); 1432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 14353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiXor(Register dst, Register src1, Register src2) { 1437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!dst.is(src1)) { 14383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src1); 1439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block xor_(dst, src2); 1441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 14443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiXorConstant(Register dst, Register src, Smi* constant) { 14453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (dst.is(src)) { 14463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 14478defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register constant_reg = GetSmiConstant(constant); 14488defd9ff6930b4e24729971a61cf7469daf119beSteve Block xor_(dst, constant_reg); 14493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 14508defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(dst, constant); 14513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block xor_(dst, src); 1452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftArithmeticRightConstant(Register dst, 1457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int shift_value) { 14593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(is_uint5(shift_value)); 1460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (shift_value > 0) { 1461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (dst.is(src)) { 14623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block sar(dst, Immediate(shift_value + kSmiShift)); 14633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(kSmiShift)); 1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNIMPLEMENTED(); // Not used. 1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftLogicalRightConstant(Register dst, 1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int shift_value, 1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smi_result) { 1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Logic right shift interprets its result as an *unsigned* number. 1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (dst.is(src)) { 1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNIMPLEMENTED(); // Not used. 1478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 14793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 14803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (shift_value == 0) { 14813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testq(dst, dst); 1482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(negative, on_not_smi_result); 1483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 14843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shr(dst, Immediate(shift_value + kSmiShift)); 14853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(kSmiShift)); 1486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftLeftConstant(Register dst, 1491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 149225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen int shift_value) { 14933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src)) { 14943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 14953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 14963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (shift_value > 0) { 14973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(shift_value)); 1498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftLeft(Register dst, 1503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 150425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Register src2) { 1505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(rcx)); 1506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label result_ok; 15073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Untag shift amount. 15083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src1)) { 15093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src1); 1510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 15113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiToInteger32(rcx, src2); 15123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Shift amount specified by lower 5 bits, not six as the shl opcode. 15133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block and_(rcx, Immediate(0x1f)); 1514d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block shl_cl(dst); 1515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftLogicalRight(Register dst, 1519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 1520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2, 1521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smi_result) { 15223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 15233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src1.is(kScratchRegister)); 15243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src2.is(kScratchRegister)); 1525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(rcx)); 1526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label result_ok; 15273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (src1.is(rcx) || src2.is(rcx)) { 15283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(kScratchRegister, rcx); 15293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 15303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src1)) { 15313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src1); 15323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SmiToInteger32(rcx, src2); 15343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block orl(rcx, Immediate(kSmiShift)); 1535d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block shr_cl(dst); // Shift is rcx modulo 0x1f + 32. 15363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(kSmiShift)); 15373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testq(dst, dst); 15383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (src1.is(rcx) || src2.is(rcx)) { 15393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label positive_result; 15403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(positive, &positive_result); 15413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (src1.is(rcx)) { 15423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src1, kScratchRegister); 15433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 15443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src2, kScratchRegister); 15453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 15463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block jmp(on_not_smi_result); 15473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bind(&positive_result); 15483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 15493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(negative, on_not_smi_result); // src2 was zero and src1 negative. 1550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftArithmeticRight(Register dst, 1555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 1556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2) { 15573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 15583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src1.is(kScratchRegister)); 15593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src2.is(kScratchRegister)); 1560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(rcx)); 15613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (src1.is(rcx)) { 15623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(kScratchRegister, src1); 15633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (src2.is(rcx)) { 15643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(kScratchRegister, src2); 15653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 15663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src1)) { 15673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src1); 15683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SmiToInteger32(rcx, src2); 15703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block orl(rcx, Immediate(kSmiShift)); 1571d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block sar_cl(dst); // Shift 32 + original rcx & 0x1f. 15723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(kSmiShift)); 15733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (src1.is(rcx)) { 15743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src1, kScratchRegister); 15753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (src2.is(rcx)) { 15763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src2, kScratchRegister); 15773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SelectNonSmi(Register dst, 1582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 1583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2, 1584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smis) { 15853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 15863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src1.is(kScratchRegister)); 15873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src2.is(kScratchRegister)); 1588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(src1)); 1589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(src2)); 1590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Both operands must not be smis. 1591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 15923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (allow_stub_calls()) { // Check contains a stub call. 15933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Condition not_both_smis = NegateCondition(CheckBothSmi(src1, src2)); 15943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Check(not_both_smis, "Both registers were smis in SelectNonSmi."); 15953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, kSmiTag); 1598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, Smi::FromInt(0)); 15993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movl(kScratchRegister, Immediate(kSmiTagMask)); 1600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block and_(kScratchRegister, src1); 1601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block testl(kScratchRegister, src2); 16023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // If non-zero then both are smis. 1603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(not_zero, on_not_smis); 1604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Exactly one operand is a smi. 1606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(1, static_cast<int>(kSmiTagMask)); 1607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // kScratchRegister still holds src1 & kSmiTag, which is either zero or one. 1608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block subq(kScratchRegister, Immediate(1)); 1609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If src1 is a smi, then scratch register all 1s, else it is all 0s. 1610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(dst, src1); 1611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block xor_(dst, src2); 1612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block and_(dst, kScratchRegister); 1613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If src1 is a smi, dst holds src1 ^ src2, else it is zero. 1614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block xor_(dst, src1); 16153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // If src1 is a smi, dst is src2, else it is src1, i.e., the non-smi. 1616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16188defd9ff6930b4e24729971a61cf7469daf119beSteve Block 16193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockSmiIndex MacroAssembler::SmiToIndex(Register dst, 16203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register src, 16213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int shift) { 1622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_uint6(shift)); 16233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // There is a possible optimization if shift is in the range 60-63, but that 16243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // will (and must) never happen. 16253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src)) { 16263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 16273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 16283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (shift < kSmiShift) { 16293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block sar(dst, Immediate(kSmiShift - shift)); 16303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 16313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(shift - kSmiShift)); 16323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return SmiIndex(dst, times_1); 1634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockSmiIndex MacroAssembler::SmiToNegativeIndex(Register dst, 1637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 1638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int shift) { 1639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Register src holds a positive smi. 1640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_uint6(shift)); 16413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src)) { 16423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 1643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block neg(dst); 16453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (shift < kSmiShift) { 16463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block sar(dst, Immediate(kSmiShift - shift)); 16473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 16483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(shift - kSmiShift)); 16493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return SmiIndex(dst, times_1); 1651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfSmi(Register src, Label* on_smi) { 16553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT_EQ(0, kSmiTag); 16563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Condition smi = CheckSmi(src); 16573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(smi, on_smi); 16583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 16593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfNotSmi(Register src, Label* on_not_smi) { 16623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Condition smi = CheckSmi(src); 16633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(NegateCondition(smi), on_not_smi); 1664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 16673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfNotPositiveSmi(Register src, 16683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label* on_not_positive_smi) { 16693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Condition positive_smi = CheckPositiveSmi(src); 16703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(NegateCondition(positive_smi), on_not_positive_smi); 16713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 16723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 16733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 16743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfSmiEqualsConstant(Register src, 16753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Smi* constant, 16763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label* on_equals) { 16773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiCompare(src, constant); 16783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(equal, on_equals); 16793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 16803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 16813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 16823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfNotValidSmiValue(Register src, Label* on_invalid) { 16833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Condition is_valid = CheckInteger32ValidSmiValue(src); 16843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(NegateCondition(is_valid), on_invalid); 16853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 16863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 16873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 16883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfUIntNotValidSmiValue(Register src, 16893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label* on_invalid) { 16903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Condition is_valid = CheckUInteger32ValidSmiValue(src); 16913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(NegateCondition(is_valid), on_invalid); 16923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 16933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 16943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 16953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfNotBothSmi(Register src1, Register src2, 16963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label* on_not_both_smi) { 16973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Condition both_smi = CheckBothSmi(src1, src2); 16983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(NegateCondition(both_smi), on_not_both_smi); 1699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1702d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid MacroAssembler::JumpIfNotBothPositiveSmi(Register src1, Register src2, 1703d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label* on_not_both_smi) { 1704d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Condition both_smi = CheckBothPositiveSmi(src1, src2); 1705d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke j(NegateCondition(both_smi), on_not_both_smi); 1706d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 1707d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1708d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1709d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1710e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register first_object, 1711e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register second_object, 1712e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch1, 1713e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch2, 1714e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* on_fail) { 1715e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that both objects are not smis. 1716e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Condition either_smi = CheckEitherSmi(first_object, second_object); 1717e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke j(either_smi, on_fail); 1718e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1719e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Load instance type for both strings. 1720e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movq(scratch1, FieldOperand(first_object, HeapObject::kMapOffset)); 1721e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movq(scratch2, FieldOperand(second_object, HeapObject::kMapOffset)); 1722e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movzxbl(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset)); 1723e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movzxbl(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset)); 1724e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1725e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that both are flat ascii strings. 1726e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(kNotStringTag != 0); 1727e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const int kFlatAsciiStringMask = 1728e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; 1729d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke const int kFlatAsciiStringTag = ASCII_STRING_TYPE; 1730e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1731e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke andl(scratch1, Immediate(kFlatAsciiStringMask)); 1732e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke andl(scratch2, Immediate(kFlatAsciiStringMask)); 1733e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Interleave the bits to check both scratch1 and scratch2 in one test. 1734e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3)); 1735e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke lea(scratch1, Operand(scratch1, scratch2, times_8, 0)); 1736e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke cmpl(scratch1, 1737d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Immediate(kFlatAsciiStringTag + (kFlatAsciiStringTag << 3))); 1738e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke j(not_equal, on_fail); 1739e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1740e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1741e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 17426ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii( 17436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register instance_type, 17446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch, 17456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label *failure) { 17466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (!scratch.is(instance_type)) { 17476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movl(scratch, instance_type); 17486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 17496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int kFlatAsciiStringMask = 17516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; 17526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block andl(scratch, Immediate(kFlatAsciiStringMask)); 17546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block cmpl(scratch, Immediate(kStringTag | kSeqStringTag | kAsciiStringTag)); 17556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block j(not_equal, failure); 17566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 17576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17596ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialAscii( 17606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register first_object_instance_type, 17616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register second_object_instance_type, 17626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch1, 17636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch2, 17646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label* on_fail) { 17656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Load instance type for both strings. 17666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(scratch1, first_object_instance_type); 17676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(scratch2, second_object_instance_type); 17686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that both are flat ascii strings. 17706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(kNotStringTag != 0); 17716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int kFlatAsciiStringMask = 17726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; 17736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int kFlatAsciiStringTag = ASCII_STRING_TYPE; 17746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block andl(scratch1, Immediate(kFlatAsciiStringMask)); 17766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block andl(scratch2, Immediate(kFlatAsciiStringMask)); 17776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Interleave the bits to check both scratch1 and scratch2 in one test. 17786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3)); 17796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block lea(scratch1, Operand(scratch1, scratch2, times_8, 0)); 17806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block cmpl(scratch1, 17816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Immediate(kFlatAsciiStringTag + (kFlatAsciiStringTag << 3))); 17826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block j(not_equal, on_fail); 17836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 17846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Move(Register dst, Handle<Object> source) { 1787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!source->IsFailure()); 1788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (source->IsSmi()) { 17893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(dst, Smi::cast(*source)); 1790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(dst, source, RelocInfo::EMBEDDED_OBJECT); 1792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Move(const Operand& dst, Handle<Object> source) { 17973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!source->IsFailure()); 1798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (source->IsSmi()) { 17993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(dst, Smi::cast(*source)); 1800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT); 1802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(dst, kScratchRegister); 1803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Cmp(Register dst, Handle<Object> source) { 18083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (source->IsSmi()) { 18093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiCompare(dst, Smi::cast(*source)); 18103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 18113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(kScratchRegister, source); 18123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block cmpq(dst, kScratchRegister); 18133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Cmp(const Operand& dst, Handle<Object> source) { 1818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (source->IsSmi()) { 18193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiCompare(dst, Smi::cast(*source)); 1820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(source->IsHeapObject()); 1822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT); 1823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(dst, kScratchRegister); 1824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Push(Handle<Object> source) { 1829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (source->IsSmi()) { 18303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Push(Smi::cast(*source)); 1831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(source->IsHeapObject()); 1833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT); 1834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(kScratchRegister); 1835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Push(Smi* source) { 18403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block intptr_t smi = reinterpret_cast<intptr_t>(source); 18413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (is_int32(smi)) { 18423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block push(Immediate(static_cast<int32_t>(smi))); 18433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 18448defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register constant = GetSmiConstant(source); 18458defd9ff6930b4e24729971a61cf7469daf119beSteve Block push(constant); 18463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 18473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 18483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 18493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1850e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::Drop(int stack_elements) { 1851e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (stack_elements > 0) { 1852e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke addq(rsp, Immediate(stack_elements * kPointerSize)); 1853e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1854e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1855e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1856e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 18573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::Test(const Operand& src, Smi* source) { 1858f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke testl(Operand(src, kIntSize), Immediate(source->value())); 1859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Jump(ExternalReference ext) { 1863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, ext); 1864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block jmp(kScratchRegister); 1865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Jump(Address destination, RelocInfo::Mode rmode) { 1869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, destination, rmode); 1870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block jmp(kScratchRegister); 1871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Jump(Handle<Code> code_object, RelocInfo::Mode rmode) { 18753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // TODO(X64): Inline this 18763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block jmp(code_object, rmode); 1877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Call(ExternalReference ext) { 1881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, ext); 1882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block call(kScratchRegister); 1883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Call(Address destination, RelocInfo::Mode rmode) { 1887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, destination, rmode); 1888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block call(kScratchRegister); 1889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Call(Handle<Code> code_object, RelocInfo::Mode rmode) { 1893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(RelocInfo::IsCodeTarget(rmode)); 1894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block WriteRecordedPositions(); 18953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block call(code_object, rmode); 1896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::PushTryHandler(CodeLocation try_location, 1900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HandlerType type) { 1901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Adjust this code if not the case. 1902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); 1903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The pc (return address) is already on TOS. This code pushes state, 1905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // frame pointer and current handler. Check that they are expected 1906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // next on the stack, in that order. 1907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(StackHandlerConstants::kStateOffset, 1908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StackHandlerConstants::kPCOffset - kPointerSize); 1909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(StackHandlerConstants::kFPOffset, 1910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StackHandlerConstants::kStateOffset - kPointerSize); 1911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(StackHandlerConstants::kNextOffset, 1912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StackHandlerConstants::kFPOffset - kPointerSize); 1913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (try_location == IN_JAVASCRIPT) { 1915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (type == TRY_CATCH_HANDLER) { 1916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Immediate(StackHandler::TRY_CATCH)); 1917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Immediate(StackHandler::TRY_FINALLY)); 1919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(rbp); 1921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(try_location == IN_JS_ENTRY); 1923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The frame pointer does not point to a JS frame so we save NULL 1924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // for rbp. We expect the code throwing an exception to check rbp 1925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // before dereferencing it to restore the context. 1926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Immediate(StackHandler::ENTRY)); 1927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Immediate(0)); // NULL frame pointer. 1928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save the current handler. 1930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, ExternalReference(Top::k_handler_address)); 1931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Operand(kScratchRegister, 0)); 1932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Link this handler. 1933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(Operand(kScratchRegister, 0), rsp); 1934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1937e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::PopTryHandler() { 1938e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(0, StackHandlerConstants::kNextOffset); 1939e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Unlink this handler. 1940e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movq(kScratchRegister, ExternalReference(Top::k_handler_address)); 1941e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke pop(Operand(kScratchRegister, 0)); 1942e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Remove the remaining fields. 1943e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke addq(rsp, Immediate(StackHandlerConstants::kSize - kPointerSize)); 1944e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1945e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1946e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Ret() { 1948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ret(0); 1949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::FCmp() { 19533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block fucomip(); 19548defd9ff6930b4e24729971a61cf7469daf119beSteve Block fstp(0); 1955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpObjectType(Register heap_object, 1959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstanceType type, 1960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register map) { 1961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(map, FieldOperand(heap_object, HeapObject::kMapOffset)); 1962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CmpInstanceType(map, type); 1963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpInstanceType(Register map, InstanceType type) { 1967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpb(FieldOperand(map, Map::kInstanceTypeOffset), 1968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(static_cast<int8_t>(type))); 1969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 19723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::CheckMap(Register obj, 19733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Handle<Map> map, 19743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Label* fail, 19753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu bool is_heap_object) { 19763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (!is_heap_object) { 19773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu JumpIfSmi(obj, fail); 19783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 19793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Cmp(FieldOperand(obj, HeapObject::kMapOffset), map); 19803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu j(not_equal, fail); 19813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 19823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 19833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1984f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid MacroAssembler::AbortIfNotNumber(Register object) { 1985402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Label ok; 1986402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Condition is_smi = CheckSmi(object); 1987402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu j(is_smi, &ok); 1988402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Cmp(FieldOperand(object, HeapObject::kMapOffset), 1989402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Factory::heap_number_map()); 1990f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Assert(equal, "Operand not a number"); 1991402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu bind(&ok); 1992402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 1993402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1994402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1995756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid MacroAssembler::AbortIfSmi(Register object) { 1996756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Label ok; 1997756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Condition is_smi = CheckSmi(object); 1998756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Assert(NegateCondition(is_smi), "Operand is a smi"); 1999756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick} 2000756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 2001756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 2002f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid MacroAssembler::AbortIfNotSmi(Register object) { 20036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label ok; 20046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Condition is_smi = CheckSmi(object); 2005756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Assert(is_smi, "Operand is not a smi"); 20066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 20076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 20086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 20099dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::AbortIfNotRootValue(Register src, 20109dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Heap::RootListIndex root_value_index, 20119dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const char* message) { 20129dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen ASSERT(!src.is(kScratchRegister)); 20139dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen LoadRoot(kScratchRegister, root_value_index); 20149dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen cmpq(src, kScratchRegister); 20159dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Check(equal, message); 20169dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 20179dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 20189dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 20199dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 2020d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeCondition MacroAssembler::IsObjectStringType(Register heap_object, 2021d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Register map, 2022d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Register instance_type) { 2023d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke movq(map, FieldOperand(heap_object, HeapObject::kMapOffset)); 20244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke movzxbl(instance_type, FieldOperand(map, Map::kInstanceTypeOffset)); 2025d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ASSERT(kNotStringTag != 0); 2026d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke testb(instance_type, Immediate(kIsNotStringMask)); 2027d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return zero; 2028d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 2029d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 2030d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 2031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::TryGetFunctionPrototype(Register function, 2032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 2033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 2034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 2035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block testl(function, Immediate(kSmiTagMask)); 2036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(zero, miss); 2037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the function really is a function. 2039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CmpObjectType(function, JS_FUNCTION_TYPE, result); 2040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(not_equal, miss); 2041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure that the function has an instance prototype. 2043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label non_instance; 2044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block testb(FieldOperand(result, Map::kBitFieldOffset), 2045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(1 << Map::kHasNonInstancePrototype)); 2046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(not_zero, &non_instance); 2047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the prototype or initial map from the function. 2049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(result, 2050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 2051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the prototype or initial map is the hole, don't return it and 2053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // simply miss the cache instead. This will allow us to allocate a 2054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // prototype object on-demand in the runtime system. 2055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CompareRoot(result, Heap::kTheHoleValueRootIndex); 2056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(equal, miss); 2057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the function does not have an initial map, we're done. 2059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label done; 2060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CmpObjectType(result, MAP_TYPE, kScratchRegister); 2061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(not_equal, &done); 2062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the prototype from the initial map. 2064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(result, FieldOperand(result, Map::kPrototypeOffset)); 2065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block jmp(&done); 2066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Non-instance prototype: Fetch prototype from constructor field 2068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // in initial map. 2069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&non_instance); 2070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(result, FieldOperand(result, Map::kConstructorOffset)); 2071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // All done. 2073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&done); 2074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SetCounter(StatsCounter* counter, int value) { 2078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_native_code_counters && counter->Enabled()) { 2079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, ExternalReference(counter)); 2080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movl(Operand(kScratchRegister, 0), Immediate(value)); 2081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::IncrementCounter(StatsCounter* counter, int value) { 2086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(value > 0); 2087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_native_code_counters && counter->Enabled()) { 2088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, ExternalReference(counter)); 2089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand operand(kScratchRegister, 0); 2090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (value == 1) { 2091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block incl(operand); 2092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 2093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addl(operand, Immediate(value)); 2094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::DecrementCounter(StatsCounter* counter, int value) { 2100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(value > 0); 2101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_native_code_counters && counter->Enabled()) { 2102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, ExternalReference(counter)); 2103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand operand(kScratchRegister, 0); 2104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (value == 1) { 2105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block decl(operand); 2106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 2107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block subl(operand, Immediate(value)); 2108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT 2113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::PushRegistersFromMemory(RegList regs) { 2115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((regs & ~kJSCallerSaved) == 0); 2116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Push the content of the memory location to the stack. 2117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < kNumJSCallerSaved; i++) { 2118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int r = JSCallerSavedCode(i); 2119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((regs & (1 << r)) != 0) { 2120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference reg_addr = 2121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference(Debug_Address::Register(i)); 2122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, reg_addr); 2123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Operand(kScratchRegister, 0)); 2124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 21283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SaveRegistersToMemory(RegList regs) { 2130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((regs & ~kJSCallerSaved) == 0); 2131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Copy the content of registers to memory location. 2132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < kNumJSCallerSaved; i++) { 2133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int r = JSCallerSavedCode(i); 2134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((regs & (1 << r)) != 0) { 2135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register reg = { r }; 2136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference reg_addr = 2137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference(Debug_Address::Register(i)); 2138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, reg_addr); 2139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(Operand(kScratchRegister, 0), reg); 2140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::RestoreRegistersFromMemory(RegList regs) { 2146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((regs & ~kJSCallerSaved) == 0); 2147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Copy the content of memory location to registers. 2148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = kNumJSCallerSaved - 1; i >= 0; i--) { 2149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int r = JSCallerSavedCode(i); 2150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((regs & (1 << r)) != 0) { 2151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register reg = { r }; 2152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference reg_addr = 2153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference(Debug_Address::Register(i)); 2154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, reg_addr); 2155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(reg, Operand(kScratchRegister, 0)); 2156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::PopRegistersToMemory(RegList regs) { 2162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((regs & ~kJSCallerSaved) == 0); 2163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pop the content from the stack to the memory location. 2164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = kNumJSCallerSaved - 1; i >= 0; i--) { 2165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int r = JSCallerSavedCode(i); 2166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((regs & (1 << r)) != 0) { 2167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference reg_addr = 2168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference(Debug_Address::Register(i)); 2169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, reg_addr); 2170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pop(Operand(kScratchRegister, 0)); 2171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CopyRegistersFromStackToMemory(Register base, 2177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 2178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RegList regs) { 2179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!scratch.is(kScratchRegister)); 2180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!base.is(kScratchRegister)); 2181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!base.is(scratch)); 2182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((regs & ~kJSCallerSaved) == 0); 2183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Copy the content of the stack to the memory location and adjust base. 2184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = kNumJSCallerSaved - 1; i >= 0; i--) { 2185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int r = JSCallerSavedCode(i); 2186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((regs & (1 << r)) != 0) { 2187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(scratch, Operand(base, 0)); 2188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference reg_addr = 2189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference(Debug_Address::Register(i)); 2190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, reg_addr); 2191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(Operand(kScratchRegister, 0), scratch); 2192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lea(base, Operand(base, kPointerSize)); 2193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2197402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::DebugBreak() { 2198402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ASSERT(allow_stub_calls()); 2199402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu xor_(rax, rax); // no arguments 2200402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu movq(rbx, ExternalReference(Runtime::kDebugBreak)); 2201402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu CEntryStub ces(1); 2202402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Call(ces.GetCode(), RelocInfo::DEBUG_BREAK); 2203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2204402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#endif // ENABLE_DEBUGGER_SUPPORT 2205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokePrologue(const ParameterCount& expected, 2208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 2209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> code_constant, 2210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register code_register, 2211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* done, 2212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InvokeFlag flag) { 2213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool definitely_matches = false; 2214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label invoke; 2215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (expected.is_immediate()) { 2216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(actual.is_immediate()); 2217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (expected.immediate() == actual.immediate()) { 2218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block definitely_matches = true; 2219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 22208defd9ff6930b4e24729971a61cf7469daf119beSteve Block Set(rax, actual.immediate()); 2221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (expected.immediate() == 22223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SharedFunctionInfo::kDontAdaptArgumentsSentinel) { 2223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Don't worry about adapting arguments for built-ins that 2224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // don't want that done. Skip adaption code by making it look 2225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // like we have a match between expected and actual number of 2226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // arguments. 2227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block definitely_matches = true; 2228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 22298defd9ff6930b4e24729971a61cf7469daf119beSteve Block Set(rbx, expected.immediate()); 2230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 2233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (actual.is_immediate()) { 2234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Expected is in register, actual is immediate. This is the 2235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // case when we invoke function values without going through the 2236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // IC mechanism. 2237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(expected.reg(), Immediate(actual.immediate())); 2238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(equal, &invoke); 2239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(expected.reg().is(rbx)); 22408defd9ff6930b4e24729971a61cf7469daf119beSteve Block Set(rax, actual.immediate()); 2241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (!expected.reg().is(actual.reg())) { 2242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Both expected and actual are in (different) registers. This 2243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is the case when we invoke functions using call and apply. 2244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(expected.reg(), actual.reg()); 2245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(equal, &invoke); 2246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(actual.reg().is(rax)); 2247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(expected.reg().is(rbx)); 2248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!definitely_matches) { 2252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> adaptor = 2253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)); 2254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!code_constant.is_null()) { 2255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rdx, code_constant, RelocInfo::EMBEDDED_OBJECT); 2256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addq(rdx, Immediate(Code::kHeaderSize - kHeapObjectTag)); 2257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (!code_register.is(rdx)) { 2258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rdx, code_register); 2259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (flag == CALL_FUNCTION) { 2262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Call(adaptor, RelocInfo::CODE_TARGET); 2263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block jmp(done); 2264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 2265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Jump(adaptor, RelocInfo::CODE_TARGET); 2266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&invoke); 2268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeCode(Register code, 2273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& expected, 2274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 2275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InvokeFlag flag) { 2276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label done; 2277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InvokePrologue(expected, actual, Handle<Code>::null(), code, &done, flag); 2278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (flag == CALL_FUNCTION) { 2279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block call(code); 2280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 2281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(flag == JUMP_FUNCTION); 2282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block jmp(code); 2283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&done); 2285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeCode(Handle<Code> code, 2289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& expected, 2290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 2291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::Mode rmode, 2292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InvokeFlag flag) { 2293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label done; 2294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register dummy = rax; 2295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InvokePrologue(expected, actual, code, dummy, &done, flag); 2296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (flag == CALL_FUNCTION) { 2297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Call(code, rmode); 2298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 2299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(flag == JUMP_FUNCTION); 2300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Jump(code, rmode); 2301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&done); 2303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeFunction(Register function, 2307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 2308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InvokeFlag flag) { 2309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(function.is(rdi)); 2310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rdx, FieldOperand(function, JSFunction::kSharedFunctionInfoOffset)); 2311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rsi, FieldOperand(function, JSFunction::kContextOffset)); 2312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movsxlq(rbx, 2313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FieldOperand(rdx, SharedFunctionInfo::kFormalParameterCountOffset)); 2314756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick movq(rdx, FieldOperand(rdi, JSFunction::kCodeOffset)); 2315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Advances rdx to the end of the Code object header, to the start of 2316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the executable code. 2317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lea(rdx, FieldOperand(rdx, Code::kHeaderSize)); 2318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ParameterCount expected(rbx); 2320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InvokeCode(rdx, expected, actual, flag); 2321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2324402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::InvokeFunction(JSFunction* function, 2325402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu const ParameterCount& actual, 2326402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu InvokeFlag flag) { 2327402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ASSERT(function->is_compiled()); 2328402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Get the function and setup the context. 2329402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Move(rdi, Handle<JSFunction>(function)); 2330402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); 2331402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 2332402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Invoke the cached code. 2333402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Handle<Code> code(function->code()); 2334402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ParameterCount expected(function->shared()->formal_parameter_count()); 2335402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu InvokeCode(code, expected, actual, RelocInfo::CODE_TARGET, flag); 2336402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 2337402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 2338402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 2339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::EnterFrame(StackFrame::Type type) { 2340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(rbp); 2341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rbp, rsp); 2342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(rsi); // Context. 23433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Push(Smi::FromInt(type)); 2344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT); 2345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(kScratchRegister); 2346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_debug_code) { 2347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, 2348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Factory::undefined_value(), 2349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::EMBEDDED_OBJECT); 2350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(Operand(rsp, 0), kScratchRegister); 2351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(not_equal, "code object not properly patched"); 2352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LeaveFrame(StackFrame::Type type) { 2357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_debug_code) { 23583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(kScratchRegister, Smi::FromInt(type)); 2359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(Operand(rbp, StandardFrameConstants::kMarkerOffset), kScratchRegister); 2360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(equal, "stack frame types must match"); 2361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rsp, rbp); 2363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pop(rbp); 2364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2367bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid MacroAssembler::EnterExitFramePrologue(ExitFrame::Mode mode, 2368bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch bool save_rax) { 2369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Setup the frame structure on the stack. 2370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // All constants are relative to the frame pointer of the exit frame. 2371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize); 2372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize); 2373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize); 2374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(rbp); 2375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rbp, rsp); 2376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Reserve room for entry stack pointer and push the debug marker. 23783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize); 2379402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu push(Immediate(0)); // Saved entry sp, patched before call. 2380402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT); 2381402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu push(kScratchRegister); // Accessed from EditFrame::code_slot. 2382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save the frame pointer and the context in top. 2384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address); 2385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference context_address(Top::k_context_address); 2386bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if (save_rax) { 2387bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch movq(r14, rax); // Backup rax before we use it. 2388bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } 2389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rax, rbp); 2391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block store_rax(c_entry_fp_address); 2392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rax, rsi); 2393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block store_rax(context_address); 2394bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 2395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2396bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid MacroAssembler::EnterExitFrameEpilogue(ExitFrame::Mode mode, 2397bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch int result_size, 2398bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch int argc) { 2399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT 2400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save the state of all registers to the stack from the memory 2401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // location. This is needed to allow nested break points. 2402d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (mode == ExitFrame::MODE_DEBUG) { 2403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // TODO(1243899): This should be symmetric to 2404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // CopyRegistersFromStackToMemory() but it isn't! esp is assumed 2405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // correct here, but computed for the other call. Very error 2406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // prone! FIX THIS. Actually there are deeper problems with 2407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // register saving than this asymmetry (see the bug report 2408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // associated with this issue). 2409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PushRegistersFromMemory(kJSCallerSaved); 2410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 2412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef _WIN64 2414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Reserve space on stack for result and argument structures, if necessary. 2415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result_stack_space = (result_size < 2) ? 0 : result_size * kPointerSize; 2416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Reserve space for the Arguments object. The Windows 64-bit ABI 2417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // requires us to pass this structure as a pointer to its location on 2418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the stack. The structure contains 2 values. 2419bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch int argument_stack_space = argc * kPointerSize; 2420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We also need backing space for 4 parameters, even though 2421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // we only pass one or two parameter, and it is in a register. 2422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int argument_mirror_space = 4 * kPointerSize; 2423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int total_stack_space = 2424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block argument_mirror_space + argument_stack_space + result_stack_space; 2425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block subq(rsp, Immediate(total_stack_space)); 2426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 2427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the required frame alignment for the OS. 2429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kFrameAlignment = OS::ActivationFrameAlignment(); 2430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (kFrameAlignment > 0) { 2431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(IsPowerOf2(kFrameAlignment)); 2432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, Immediate(-kFrameAlignment)); 2433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block and_(rsp, kScratchRegister); 2434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the saved entry sp. 2437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(Operand(rbp, ExitFrameConstants::kSPOffset), rsp); 2438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2441bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid MacroAssembler::EnterExitFrame(ExitFrame::Mode mode, int result_size) { 2442bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch EnterExitFramePrologue(mode, true); 2443bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 2444bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Setup argv in callee-saved register r12. It is reused in LeaveExitFrame, 2445bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // so it must be retained across the C-call. 2446bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; 2447bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch lea(r12, Operand(rbp, r14, times_pointer_size, offset)); 2448bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 2449bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch EnterExitFrameEpilogue(mode, result_size, 2); 2450bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 2451bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 2452bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 2453bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid MacroAssembler::EnterApiExitFrame(ExitFrame::Mode mode, 2454bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch int stack_space, 2455bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch int argc, 2456bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch int result_size) { 2457bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch EnterExitFramePrologue(mode, false); 2458bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 2459bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Setup argv in callee-saved register r12. It is reused in LeaveExitFrame, 2460bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // so it must be retained across the C-call. 2461bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; 2462bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch lea(r12, Operand(rbp, (stack_space * kPointerSize) + offset)); 2463bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 2464bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch EnterExitFrameEpilogue(mode, result_size, argc); 2465bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 2466bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 2467bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 2468d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::LeaveExitFrame(ExitFrame::Mode mode, int result_size) { 2469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Registers: 24708defd9ff6930b4e24729971a61cf7469daf119beSteve Block // r12 : argv 2471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT 2472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore the memory copy of the registers by digging them out from 2473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the stack. This is needed to allow nested break points. 2474d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (mode == ExitFrame::MODE_DEBUG) { 2475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // It's okay to clobber register rbx below because we don't need 2476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the function pointer after this. 2477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kCallerSavedSize = kNumJSCallerSaved * kPointerSize; 2478d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int kOffset = ExitFrameConstants::kCodeOffset - kCallerSavedSize; 2479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lea(rbx, Operand(rbp, kOffset)); 2480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CopyRegistersFromStackToMemory(rbx, rcx, kJSCallerSaved); 2481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 2483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the return address from the stack and restore the frame pointer. 2485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rcx, Operand(rbp, 1 * kPointerSize)); 2486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rbp, Operand(rbp, 0 * kPointerSize)); 2487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pop everything up to and including the arguments and the receiver 2489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // from the caller stack. 24908defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(rsp, Operand(r12, 1 * kPointerSize)); 2491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore current context from top and clear it in debug mode. 2493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference context_address(Top::k_context_address); 2494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, context_address); 2495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rsi, Operand(kScratchRegister, 0)); 2496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 2497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(Operand(kScratchRegister, 0), Immediate(0)); 2498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 2499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Push the return address to get ready to return. 2501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(rcx); 2502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Clear the top frame. 2504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address); 2505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, c_entry_fp_address); 2506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(Operand(kScratchRegister, 0), Immediate(0)); 2507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, 2511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 2512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 2513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label same_contexts; 2514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!holder_reg.is(scratch)); 2516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!scratch.is(kScratchRegister)); 2517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load current lexical context from the stack frame. 2518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(scratch, Operand(rbp, StandardFrameConstants::kContextOffset)); 2519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // When generating debug code, make sure the lexical context is set. 2521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_debug_code) { 2522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(scratch, Immediate(0)); 2523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(not_equal, "we should not have an empty lexical context"); 2524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the global context of the current context. 2526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; 2527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(scratch, FieldOperand(scratch, offset)); 2528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(scratch, FieldOperand(scratch, GlobalObject::kGlobalContextOffset)); 2529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check the context is a global context. 2531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_debug_code) { 2532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Cmp(FieldOperand(scratch, HeapObject::kMapOffset), 2533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Factory::global_context_map()); 2534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(equal, "JSGlobalObject::global_context should be a global context."); 2535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if both contexts are the same. 2538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(scratch, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); 2539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(equal, &same_contexts); 2540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compare security tokens. 2542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the security token in the calling global object is 2543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // compatible with the security token in the receiving global 2544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // object. 2545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check the context is a global context. 2547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_debug_code) { 2548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Preserve original value of holder_reg. 2549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(holder_reg); 2550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(holder_reg, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); 2551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CompareRoot(holder_reg, Heap::kNullValueRootIndex); 2552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(not_equal, "JSGlobalProxy::context() should not be null."); 2553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Read the first word and compare to global_context_map(), 2555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(holder_reg, FieldOperand(holder_reg, HeapObject::kMapOffset)); 2556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CompareRoot(holder_reg, Heap::kGlobalContextMapRootIndex); 2557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(equal, "JSGlobalObject::global_context should be a global context."); 2558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pop(holder_reg); 2559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, 2562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); 25633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int token_offset = 25643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Context::kHeaderSize + Context::SECURITY_TOKEN_INDEX * kPointerSize; 2565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(scratch, FieldOperand(scratch, token_offset)); 2566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(scratch, FieldOperand(kScratchRegister, token_offset)); 2567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(not_equal, miss); 2568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&same_contexts); 2570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LoadAllocationTopHelper(Register result, 2574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result_end, 2575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 2576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags) { 2577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_top = 2578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference::new_space_allocation_top_address(); 2579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Just return if allocation top is already known. 2581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((flags & RESULT_CONTAINS_TOP) != 0) { 2582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // No use of scratch if allocation top is provided. 25836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(!scratch.is_valid()); 2584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 2585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Assert that result actually contains top on entry. 2586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, new_space_allocation_top); 2587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(result, Operand(kScratchRegister, 0)); 2588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(equal, "Unexpected allocation top"); 2589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 2590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 2591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Move address of new object to result. Use scratch register if available, 25946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // and keep address in scratch until call to UpdateAllocationTopHelper. 25956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (scratch.is_valid()) { 2596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!scratch.is(result_end)); 2597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(scratch, new_space_allocation_top); 2598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(result, Operand(scratch, 0)); 25996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (result.is(rax)) { 26006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block load_rax(new_space_allocation_top); 26016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 26026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(kScratchRegister, new_space_allocation_top); 26036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(result, Operand(kScratchRegister, 0)); 2604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::UpdateAllocationTopHelper(Register result_end, 2609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch) { 2610d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (FLAG_debug_code) { 2611d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block testq(result_end, Immediate(kObjectAlignmentMask)); 2612d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Check(zero, "Unaligned allocation in new space"); 2613d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2614d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_top = 2616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference::new_space_allocation_top_address(); 2617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update new top. 2619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result_end.is(rax)) { 2620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rax can be stored directly to a memory location. 2621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block store_rax(new_space_allocation_top); 2622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 2623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Register required - use scratch provided if available. 26246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (scratch.is_valid()) { 26256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(Operand(scratch, 0), result_end); 26266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 2627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, new_space_allocation_top); 2628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(Operand(kScratchRegister, 0), result_end); 2629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(int object_size, 2635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 2636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result_end, 2637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 2638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required, 2639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags) { 2640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!result.is(result_end)); 2641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load address of new object into result. 2643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadAllocationTopHelper(result, result_end, scratch, flags); 2644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate new top and bail out if new space is exhausted. 2646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_limit = 2647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference::new_space_allocation_limit_address(); 26486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 26496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register top_reg = result_end.is_valid() ? result_end : result; 26506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 26516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (top_reg.is(result)) { 26526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block addq(top_reg, Immediate(object_size)); 26536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 26546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block lea(top_reg, Operand(result, object_size)); 26556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 2656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, new_space_allocation_limit); 26576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block cmpq(top_reg, Operand(kScratchRegister, 0)); 2658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(above, gc_required); 2659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update allocation top. 26616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block UpdateAllocationTopHelper(top_reg, scratch); 2662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 26636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (top_reg.is(result)) { 26646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if ((flags & TAG_OBJECT) != 0) { 26656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block subq(result, Immediate(object_size - kHeapObjectTag)); 26666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 26676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block subq(result, Immediate(object_size)); 26686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 26696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if ((flags & TAG_OBJECT) != 0) { 26706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Tag the result if requested. 2671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addq(result, Immediate(kHeapObjectTag)); 2672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(int header_size, 2677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ScaleFactor element_size, 2678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register element_count, 2679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 2680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result_end, 2681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 2682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required, 2683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags) { 2684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!result.is(result_end)); 2685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load address of new object into result. 2687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadAllocationTopHelper(result, result_end, scratch, flags); 2688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate new top and bail out if new space is exhausted. 2690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_limit = 2691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference::new_space_allocation_limit_address(); 2692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lea(result_end, Operand(result, element_count, element_size, header_size)); 2693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, new_space_allocation_limit); 2694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(result_end, Operand(kScratchRegister, 0)); 2695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(above, gc_required); 2696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update allocation top. 2698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UpdateAllocationTopHelper(result_end, scratch); 2699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Tag the result if requested. 2701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((flags & TAG_OBJECT) != 0) { 2702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addq(result, Immediate(kHeapObjectTag)); 2703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(Register object_size, 2708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 2709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result_end, 2710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 2711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required, 2712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags) { 2713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load address of new object into result. 2714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadAllocationTopHelper(result, result_end, scratch, flags); 2715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate new top and bail out if new space is exhausted. 2717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_limit = 2718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference::new_space_allocation_limit_address(); 2719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!object_size.is(result_end)) { 2720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(result_end, object_size); 2721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addq(result_end, result); 2723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, new_space_allocation_limit); 2724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(result_end, Operand(kScratchRegister, 0)); 2725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(above, gc_required); 2726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update allocation top. 2728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UpdateAllocationTopHelper(result_end, scratch); 2729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Tag the result if requested. 2731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((flags & TAG_OBJECT) != 0) { 2732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addq(result, Immediate(kHeapObjectTag)); 2733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::UndoAllocationInNewSpace(Register object) { 2738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_top = 2739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference::new_space_allocation_top_address(); 2740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure the object has no tag before resetting top. 2742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block and_(object, Immediate(~kHeapObjectTagMask)); 2743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, new_space_allocation_top); 2744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 2745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(object, Operand(kScratchRegister, 0)); 2746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(below, "Undo allocation of non allocated memory"); 2747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 2748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(Operand(kScratchRegister, 0), object); 2749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::AllocateHeapNumber(Register result, 27533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register scratch, 27543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label* gc_required) { 27553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Allocate heap number in new space. 27563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block AllocateInNewSpace(HeapNumber::kSize, 27573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block result, 27583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block scratch, 27593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block no_reg, 27603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block gc_required, 27613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block TAG_OBJECT); 27623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 27633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Set the map. 27643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block LoadRoot(kScratchRegister, Heap::kHeapNumberMapRootIndex); 27653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); 27663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 27673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 27683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2769e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::AllocateTwoByteString(Register result, 2770e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register length, 2771e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch1, 2772e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch2, 2773e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch3, 2774e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* gc_required) { 2775e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Calculate the number of bytes needed for the characters in the string while 2776e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // observing object alignment. 27776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int kHeaderAlignment = SeqTwoByteString::kHeaderSize & 27786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block kObjectAlignmentMask; 2779e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(kShortSize == 2); 2780e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // scratch1 = length * 2 + kObjectAlignmentMask. 27816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block lea(scratch1, Operand(length, length, times_1, kObjectAlignmentMask + 27826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block kHeaderAlignment)); 2783e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke and_(scratch1, Immediate(~kObjectAlignmentMask)); 27846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (kHeaderAlignment > 0) { 27856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block subq(scratch1, Immediate(kHeaderAlignment)); 27866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 2787e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2788e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Allocate two byte string in new space. 2789e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AllocateInNewSpace(SeqTwoByteString::kHeaderSize, 2790e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke times_1, 2791e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch1, 2792e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke result, 2793e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch2, 2794e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch3, 2795e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke gc_required, 2796e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke TAG_OBJECT); 2797e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2798e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Set the map, length and hash field. 2799e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke LoadRoot(kScratchRegister, Heap::kStringMapRootIndex); 2800e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); 28016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Integer32ToSmi(scratch1, length); 28026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(FieldOperand(result, String::kLengthOffset), scratch1); 28037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch movq(FieldOperand(result, String::kHashFieldOffset), 2804e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Immediate(String::kEmptyHashField)); 2805e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 2806e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2807e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2808e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::AllocateAsciiString(Register result, 2809e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register length, 2810e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch1, 2811e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch2, 2812e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch3, 2813e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* gc_required) { 2814e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Calculate the number of bytes needed for the characters in the string while 2815e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // observing object alignment. 28166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int kHeaderAlignment = SeqAsciiString::kHeaderSize & 28176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block kObjectAlignmentMask; 2818e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movl(scratch1, length); 2819e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(kCharSize == 1); 28206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block addq(scratch1, Immediate(kObjectAlignmentMask + kHeaderAlignment)); 2821e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke and_(scratch1, Immediate(~kObjectAlignmentMask)); 28226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (kHeaderAlignment > 0) { 28236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block subq(scratch1, Immediate(kHeaderAlignment)); 28246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 2825e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2826e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Allocate ascii string in new space. 2827e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AllocateInNewSpace(SeqAsciiString::kHeaderSize, 2828e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke times_1, 2829e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch1, 2830e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke result, 2831e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch2, 2832e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch3, 2833e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke gc_required, 2834e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke TAG_OBJECT); 2835e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2836e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Set the map, length and hash field. 2837e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke LoadRoot(kScratchRegister, Heap::kAsciiStringMapRootIndex); 2838e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); 28396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Integer32ToSmi(scratch1, length); 28406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(FieldOperand(result, String::kLengthOffset), scratch1); 28417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch movq(FieldOperand(result, String::kHashFieldOffset), 2842e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Immediate(String::kEmptyHashField)); 2843e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 2844e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2845e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2846e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::AllocateConsString(Register result, 2847e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch1, 2848e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch2, 2849e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* gc_required) { 2850e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Allocate heap number in new space. 2851e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AllocateInNewSpace(ConsString::kSize, 2852e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke result, 2853e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch1, 2854e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch2, 2855e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke gc_required, 2856e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke TAG_OBJECT); 2857e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2858e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Set the map. The other fields are left uninitialized. 2859e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke LoadRoot(kScratchRegister, Heap::kConsStringMapRootIndex); 2860e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); 2861e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 2862e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2863e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2864e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::AllocateAsciiConsString(Register result, 2865e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch1, 2866e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch2, 2867e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* gc_required) { 2868e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Allocate heap number in new space. 2869e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AllocateInNewSpace(ConsString::kSize, 2870e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke result, 2871e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch1, 2872e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch2, 2873e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke gc_required, 2874e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke TAG_OBJECT); 2875e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2876e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Set the map. The other fields are left uninitialized. 2877e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke LoadRoot(kScratchRegister, Heap::kConsAsciiStringMapRootIndex); 2878e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); 2879e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 2880e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2881e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2882d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::LoadContext(Register dst, int context_chain_length) { 2883d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (context_chain_length > 0) { 2884d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Move up the chain of contexts to the context containing the slot. 2885d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block movq(dst, Operand(rsi, Context::SlotOffset(Context::CLOSURE_INDEX))); 2886d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load the function context (which is the incoming, outer context). 2887e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movq(dst, FieldOperand(dst, JSFunction::kContextOffset)); 2888d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 1; i < context_chain_length; i++) { 2889d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block movq(dst, Operand(dst, Context::SlotOffset(Context::CLOSURE_INDEX))); 2890d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block movq(dst, FieldOperand(dst, JSFunction::kContextOffset)); 2891d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2892d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // The context may be an intermediate context, not a function context. 2893d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block movq(dst, Operand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX))); 2894d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { // context is the current function context. 2895d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // The context may be an intermediate context, not a function context. 2896d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block movq(dst, Operand(rsi, Context::SlotOffset(Context::FCONTEXT_INDEX))); 2897d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2898d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2899d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 29007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 29014515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkeint MacroAssembler::ArgumentStackSlotsForCFunctionCall(int num_arguments) { 29027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // On Windows 64 stack slots are reserved by the caller for all arguments 29037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // including the ones passed in registers, and space is always allocated for 29047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // the four register arguments even if the function takes fewer than four 29057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // arguments. 29067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // On AMD64 ABI (Linux/Mac) the first six arguments are passed in registers 29077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // and the caller does not reserve stack slots for them. 29084515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke ASSERT(num_arguments >= 0); 29094515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke#ifdef _WIN64 29107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch static const int kMinimumStackSlots = 4; 29117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (num_arguments < kMinimumStackSlots) return kMinimumStackSlots; 29127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch return num_arguments; 29134515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke#else 29147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch static const int kRegisterPassedArguments = 6; 29157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (num_arguments < kRegisterPassedArguments) return 0; 29167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch return num_arguments - kRegisterPassedArguments; 29174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke#endif 29184515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke} 29194515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 29207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 29214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid MacroAssembler::PrepareCallCFunction(int num_arguments) { 29224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke int frame_alignment = OS::ActivationFrameAlignment(); 29234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke ASSERT(frame_alignment != 0); 29244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke ASSERT(num_arguments >= 0); 29254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Make stack end at alignment and allocate space for arguments and old rsp. 29264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke movq(kScratchRegister, rsp); 29274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke ASSERT(IsPowerOf2(frame_alignment)); 29284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke int argument_slots_on_stack = 29294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke ArgumentStackSlotsForCFunctionCall(num_arguments); 29304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke subq(rsp, Immediate((argument_slots_on_stack + 1) * kPointerSize)); 29314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke and_(rsp, Immediate(-frame_alignment)); 29324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke movq(Operand(rsp, argument_slots_on_stack * kPointerSize), kScratchRegister); 29334515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke} 29344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 29354515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 29364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid MacroAssembler::CallCFunction(ExternalReference function, 29374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke int num_arguments) { 29384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke movq(rax, function); 29394515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke CallCFunction(rax, num_arguments); 29404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke} 29414515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 29424515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 29434515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid MacroAssembler::CallCFunction(Register function, int num_arguments) { 29446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check stack alignment. 29456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (FLAG_debug_code) { 29466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block CheckStackAlignment(); 29476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 29486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 29494515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke call(function); 29504515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke ASSERT(OS::ActivationFrameAlignment() != 0); 29514515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke ASSERT(num_arguments >= 0); 29524515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke int argument_slots_on_stack = 29534515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke ArgumentStackSlotsForCFunctionCall(num_arguments); 29544515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke movq(rsp, Operand(rsp, argument_slots_on_stack * kPointerSize)); 29554515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke} 29564515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 2957d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCodePatcher::CodePatcher(byte* address, int size) 2959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : address_(address), size_(size), masm_(address, size + Assembler::kGap) { 2960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Create a new macro assembler pointing to the address of the code to patch. 2961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The size is adjusted with kGap on order for the assembler to generate size 2962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // bytes of instructions without failing with buffer size constraints. 2963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); 2964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCodePatcher::~CodePatcher() { 2968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Indicate that code has changed. 2969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CPU::FlushICache(address_, size_); 2970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the code was patched as expected. 2972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(masm_.pc_ == address_ + size_); 2973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); 2974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 2977f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2978f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_X64 2979