macro-assembler-x64.cc revision 80d68eab642096c1a48b6474d6ec33064b0ad1f5
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 39480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::IndexFromHash(Register hash, Register index) { 39580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // The assert checks that the constants for the maximum number of digits 39680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // for an array index cached in the hash field and the number of bits 39780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // reserved for it does not conflict. 39880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < 39980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen (1 << String::kArrayIndexValueBits)); 40080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // We want the smi-tagged index in key. Even if we subsequently go to 40180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // the slow case, converting the key to a smi is always valid. 40280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // key: string key 40380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // hash: key's hash field, including its array index value. 40480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen and_(hash, Immediate(String::kArrayIndexValueMask)); 40580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen shr(hash, Immediate(String::kHashShift)); 40680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Here we actually clobber the key which will be used if calling into 40780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // runtime later. However as the new key is the numeric value of a string key 40880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // there is no difference in using either key. 40980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Integer32ToSmi(index, hash); 41080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 41180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 41280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CallRuntime(Runtime::FunctionId id, int num_arguments) { 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CallRuntime(Runtime::FunctionForId(id), num_arguments); 415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 418bb769b257e753aafcbd96767abb2abc645eaa20cBen MurdochObject* MacroAssembler::TryCallRuntime(Runtime::FunctionId id, 419bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch int num_arguments) { 420bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch return TryCallRuntime(Runtime::FunctionForId(id), num_arguments); 421bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 422bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 423bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) { 425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the expected number of arguments of the runtime function is 426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // constant, we check that the actual number of arguments match the 427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // expectation. 428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (f->nargs >= 0 && f->nargs != num_arguments) { 429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block IllegalOperation(num_arguments); 430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4334515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // TODO(1236192): Most runtime routines don't need the number of 4344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // arguments passed in because it is constant. At some point we 4354515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // should remove this need and make the runtime routine entry code 4364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // smarter. 4378defd9ff6930b4e24729971a61cf7469daf119beSteve Block Set(rax, num_arguments); 4384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke movq(rbx, ExternalReference(f)); 4394515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke CEntryStub ces(f->result_size); 4404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke CallStub(&ces); 441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 444bb769b257e753aafcbd96767abb2abc645eaa20cBen MurdochObject* MacroAssembler::TryCallRuntime(Runtime::Function* f, 445bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch int num_arguments) { 446bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if (f->nargs >= 0 && f->nargs != num_arguments) { 447bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch IllegalOperation(num_arguments); 448bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Since we did not call the stub, there was no allocation failure. 449bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Return some non-failure object. 450bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch return Heap::undefined_value(); 451bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } 452bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 453bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // TODO(1236192): Most runtime routines don't need the number of 454bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // arguments passed in because it is constant. At some point we 455bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // should remove this need and make the runtime routine entry code 456bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // smarter. 457bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Set(rax, num_arguments); 458bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch movq(rbx, ExternalReference(f)); 459bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch CEntryStub ces(f->result_size); 460bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch return TryCallStub(&ces); 461bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 462bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 463bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 464402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::CallExternalReference(const ExternalReference& ext, 465402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu int num_arguments) { 4668defd9ff6930b4e24729971a61cf7469daf119beSteve Block Set(rax, num_arguments); 467402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu movq(rbx, ext); 468402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 469402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu CEntryStub stub(1); 470402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu CallStub(&stub); 471402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 472402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 473402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 4746ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::TailCallExternalReference(const ExternalReference& ext, 4756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int num_arguments, 4766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int result_size) { 477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rsp[0] : return address 479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rsp[8] : argument num_arguments - 1 480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ... 481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rsp[8 * num_arguments] : argument 0 (receiver) 482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // TODO(1236192): Most runtime routines don't need the number of 485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // arguments passed in because it is constant. At some point we 486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // should remove this need and make the runtime routine entry code 487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // smarter. 4888defd9ff6930b4e24729971a61cf7469daf119beSteve Block Set(rax, num_arguments); 4896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JumpToExternalReference(ext, result_size); 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4936ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::TailCallRuntime(Runtime::FunctionId fid, 4946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int num_arguments, 4956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int result_size) { 4966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block TailCallExternalReference(ExternalReference(fid), num_arguments, result_size); 4976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 4986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 4996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 500bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochstatic int Offset(ExternalReference ref0, ExternalReference ref1) { 501bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch int64_t offset = (ref0.address() - ref1.address()); 502bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Check that fits into int. 503bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch ASSERT(static_cast<int>(offset) == offset); 504bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch return static_cast<int>(offset); 505bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 506bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 507bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 508bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid MacroAssembler::PushHandleScope(Register scratch) { 509bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch ExternalReference extensions_address = 510bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch ExternalReference::handle_scope_extensions_address(); 511bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch const int kExtensionsOffset = 0; 512bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch const int kNextOffset = Offset( 513bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch ExternalReference::handle_scope_next_address(), 514bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch extensions_address); 515bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch const int kLimitOffset = Offset( 516bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch ExternalReference::handle_scope_limit_address(), 517bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch extensions_address); 518bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 519bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Push the number of extensions, smi-tagged so the gc will ignore it. 520bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch movq(kScratchRegister, extensions_address); 521bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch movq(scratch, Operand(kScratchRegister, kExtensionsOffset)); 522bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch movq(Operand(kScratchRegister, kExtensionsOffset), Immediate(0)); 523bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Integer32ToSmi(scratch, scratch); 524bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch push(scratch); 525bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Push next and limit pointers which will be wordsize aligned and 526bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // hence automatically smi tagged. 527bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch push(Operand(kScratchRegister, kNextOffset)); 528bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch push(Operand(kScratchRegister, kLimitOffset)); 529bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 530bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 531bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 532bb769b257e753aafcbd96767abb2abc645eaa20cBen MurdochObject* MacroAssembler::PopHandleScopeHelper(Register saved, 533bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Register scratch, 534bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch bool gc_allowed) { 535bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch ExternalReference extensions_address = 536bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch ExternalReference::handle_scope_extensions_address(); 537bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch const int kExtensionsOffset = 0; 538bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch const int kNextOffset = Offset( 539bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch ExternalReference::handle_scope_next_address(), 540bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch extensions_address); 541bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch const int kLimitOffset = Offset( 542bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch ExternalReference::handle_scope_limit_address(), 543bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch extensions_address); 544bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 545bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Object* result = NULL; 546bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Label write_back; 547bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch movq(kScratchRegister, extensions_address); 548bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch cmpq(Operand(kScratchRegister, kExtensionsOffset), Immediate(0)); 549bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch j(equal, &write_back); 550bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch push(saved); 551bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if (gc_allowed) { 552bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch CallRuntime(Runtime::kDeleteHandleScopeExtensions, 0); 553bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } else { 554bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch result = TryCallRuntime(Runtime::kDeleteHandleScopeExtensions, 0); 555bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if (result->IsFailure()) return result; 556bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } 557bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch pop(saved); 558bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch movq(kScratchRegister, extensions_address); 559bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 560bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch bind(&write_back); 561bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch pop(Operand(kScratchRegister, kLimitOffset)); 562bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch pop(Operand(kScratchRegister, kNextOffset)); 563bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch pop(scratch); 564bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch SmiToInteger32(scratch, scratch); 565bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch movq(Operand(kScratchRegister, kExtensionsOffset), scratch); 566bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 567bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch return result; 568bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 569bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 570bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 571bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid MacroAssembler::PopHandleScope(Register saved, Register scratch) { 572bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch PopHandleScopeHelper(saved, scratch, true); 573bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 574bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 575bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 576bb769b257e753aafcbd96767abb2abc645eaa20cBen MurdochObject* MacroAssembler::TryPopHandleScope(Register saved, Register scratch) { 577bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch return PopHandleScopeHelper(saved, scratch, false); 578bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 579bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 580bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 5816ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::JumpToExternalReference(const ExternalReference& ext, 5826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int result_size) { 583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the entry point and jump to the C entry runtime stub. 584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rbx, ext); 585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CEntryStub ces(result_size); 5863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block jmp(ces.GetCode(), RelocInfo::CODE_TARGET); 587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 590402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag) { 591402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Calls are not allowed in some stubs. 592402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ASSERT(flag == JUMP_FUNCTION || allow_stub_calls()); 593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 594402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Rely on the assertion to check that the number of provided 595402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // arguments match the expected number of arguments. Fake a 596402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // parameter count to avoid emitting code to do the check. 597402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ParameterCount expected(0); 598402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GetBuiltinEntry(rdx, id); 599402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu InvokeCode(rdx, expected, expected, flag); 600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 602402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 603791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockvoid MacroAssembler::GetBuiltinFunction(Register target, 604791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block Builtins::JavaScript id) { 6056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Load the builtins object into target register. 6066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(target, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); 6076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(target, FieldOperand(target, GlobalObject::kBuiltinsOffset)); 608791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block movq(target, FieldOperand(target, 609791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block JSBuiltinsObject::OffsetOfFunctionWithId(id))); 610791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block} 6116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 6126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 613791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockvoid MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) { 614791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block ASSERT(!target.is(rdi)); 615791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block // Load the JavaScript builtin function from the builtins object. 616791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block GetBuiltinFunction(rdi, id); 617791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block movq(target, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); 618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Set(Register dst, int64_t x) { 622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (x == 0) { 6238defd9ff6930b4e24729971a61cf7469daf119beSteve Block xorl(dst, dst); 624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (is_int32(x)) { 625d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block movq(dst, Immediate(static_cast<int32_t>(x))); 626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (is_uint32(x)) { 627d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block movl(dst, Immediate(static_cast<uint32_t>(x))); 628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(dst, x, RelocInfo::NONE); 630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Set(const Operand& dst, int64_t x) { 6349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (is_int32(x)) { 635d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block movq(dst, Immediate(static_cast<int32_t>(x))); 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, x, RelocInfo::NONE); 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(dst, kScratchRegister); 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ---------------------------------------------------------------------------- 643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Smi tagging, untagging and tag detection. 644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockstatic int kSmiShift = kSmiTagSize + kSmiShiftSize; 646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6478defd9ff6930b4e24729971a61cf7469daf119beSteve BlockRegister MacroAssembler::GetSmiConstant(Smi* source) { 6488defd9ff6930b4e24729971a61cf7469daf119beSteve Block int value = source->value(); 6498defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (value == 0) { 6508defd9ff6930b4e24729971a61cf7469daf119beSteve Block xorl(kScratchRegister, kScratchRegister); 6518defd9ff6930b4e24729971a61cf7469daf119beSteve Block return kScratchRegister; 6528defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 6538defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (value == 1) { 6548defd9ff6930b4e24729971a61cf7469daf119beSteve Block return kSmiConstantRegister; 6558defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 6568defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(kScratchRegister, source); 6578defd9ff6930b4e24729971a61cf7469daf119beSteve Block return kScratchRegister; 6588defd9ff6930b4e24729971a61cf7469daf119beSteve Block} 6598defd9ff6930b4e24729971a61cf7469daf119beSteve Block 6608defd9ff6930b4e24729971a61cf7469daf119beSteve Blockvoid MacroAssembler::LoadSmiConstant(Register dst, Smi* source) { 6618defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (FLAG_debug_code) { 6628defd9ff6930b4e24729971a61cf7469daf119beSteve Block movq(dst, 6638defd9ff6930b4e24729971a61cf7469daf119beSteve Block reinterpret_cast<uint64_t>(Smi::FromInt(kSmiConstantRegisterValue)), 6648defd9ff6930b4e24729971a61cf7469daf119beSteve Block RelocInfo::NONE); 6658defd9ff6930b4e24729971a61cf7469daf119beSteve Block cmpq(dst, kSmiConstantRegister); 6668defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (allow_stub_calls()) { 6678defd9ff6930b4e24729971a61cf7469daf119beSteve Block Assert(equal, "Uninitialized kSmiConstantRegister"); 6688defd9ff6930b4e24729971a61cf7469daf119beSteve Block } else { 6698defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label ok; 6708defd9ff6930b4e24729971a61cf7469daf119beSteve Block j(equal, &ok); 6718defd9ff6930b4e24729971a61cf7469daf119beSteve Block int3(); 6728defd9ff6930b4e24729971a61cf7469daf119beSteve Block bind(&ok); 6738defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 6748defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 6758defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (source->value() == 0) { 6768defd9ff6930b4e24729971a61cf7469daf119beSteve Block xorl(dst, dst); 6778defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 6788defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 6798defd9ff6930b4e24729971a61cf7469daf119beSteve Block int value = source->value(); 6808defd9ff6930b4e24729971a61cf7469daf119beSteve Block bool negative = value < 0; 6818defd9ff6930b4e24729971a61cf7469daf119beSteve Block unsigned int uvalue = negative ? -value : value; 6828defd9ff6930b4e24729971a61cf7469daf119beSteve Block 6838defd9ff6930b4e24729971a61cf7469daf119beSteve Block switch (uvalue) { 6848defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 9: 6858defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_8, 0)); 6868defd9ff6930b4e24729971a61cf7469daf119beSteve Block break; 6878defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 8: 6888defd9ff6930b4e24729971a61cf7469daf119beSteve Block xorl(dst, dst); 6898defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(dst, kSmiConstantRegister, times_8, 0)); 6908defd9ff6930b4e24729971a61cf7469daf119beSteve Block break; 6918defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 4: 6928defd9ff6930b4e24729971a61cf7469daf119beSteve Block xorl(dst, dst); 6938defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(dst, kSmiConstantRegister, times_4, 0)); 6948defd9ff6930b4e24729971a61cf7469daf119beSteve Block break; 6958defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 5: 6968defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_4, 0)); 6978defd9ff6930b4e24729971a61cf7469daf119beSteve Block break; 6988defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 3: 6998defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_2, 0)); 7008defd9ff6930b4e24729971a61cf7469daf119beSteve Block break; 7018defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 2: 7028defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_1, 0)); 7038defd9ff6930b4e24729971a61cf7469daf119beSteve Block break; 7048defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 1: 7058defd9ff6930b4e24729971a61cf7469daf119beSteve Block movq(dst, kSmiConstantRegister); 7068defd9ff6930b4e24729971a61cf7469daf119beSteve Block break; 7078defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 0: 7088defd9ff6930b4e24729971a61cf7469daf119beSteve Block UNREACHABLE(); 7098defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 7108defd9ff6930b4e24729971a61cf7469daf119beSteve Block default: 7118defd9ff6930b4e24729971a61cf7469daf119beSteve Block movq(dst, reinterpret_cast<uint64_t>(source), RelocInfo::NONE); 7128defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 7138defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 7148defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (negative) { 7158defd9ff6930b4e24729971a61cf7469daf119beSteve Block neg(dst); 7168defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 7178defd9ff6930b4e24729971a61cf7469daf119beSteve Block} 7188defd9ff6930b4e24729971a61cf7469daf119beSteve Block 719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Integer32ToSmi(Register dst, Register src) { 720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, kSmiTag); 7213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src)) { 7223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movl(dst, src); 723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 7243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(kSmiShift)); 725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Integer32ToSmi(Register dst, 729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_overflow) { 731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, kSmiTag); 7323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // 32-bit integer always fits in a long smi. 733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!dst.is(src)) { 734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movl(dst, src); 735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 7363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(kSmiShift)); 737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7409dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::Integer32ToSmiField(const Operand& dst, Register src) { 7419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (FLAG_debug_code) { 7429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen testb(dst, Immediate(0x01)); 7439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Label ok; 7449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen j(zero, &ok); 7459dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (allow_stub_calls()) { 7469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Abort("Integer32ToSmiField writing to non-smi location"); 7479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } else { 7489dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen int3(); 7499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 7509dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen bind(&ok); 7519dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 7529dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen ASSERT(kSmiShift % kBitsPerByte == 0); 7539dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen movl(Operand(dst, kSmiShift / kBitsPerByte), src); 7549dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 7559dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 7569dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 7573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::Integer64PlusConstantToSmi(Register dst, 7583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register src, 7593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int constant) { 7603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (dst.is(src)) { 7613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block addq(dst, Immediate(constant)); 7623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 7633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block lea(dst, Operand(src, constant)); 7643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 7653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(kSmiShift)); 766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiToInteger32(Register dst, Register src) { 770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, kSmiTag); 771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!dst.is(src)) { 7723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 7743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shr(dst, Immediate(kSmiShift)); 775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid MacroAssembler::SmiToInteger32(Register dst, const Operand& src) { 7797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch movl(dst, Operand(src, kSmiShift / kBitsPerByte)); 7807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 7817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 7827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiToInteger64(Register dst, Register src) { 784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, kSmiTag); 7853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src)) { 7863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 7883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block sar(dst, Immediate(kSmiShift)); 789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7929dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::SmiToInteger64(Register dst, const Operand& src) { 7939dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen movsxlq(dst, Operand(src, kSmiShift / kBitsPerByte)); 7949dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 7959dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 7969dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 7973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiTest(Register src) { 7983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testq(src, src); 799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(Register dst, Register src) { 8033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block cmpq(dst, src); 804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(Register dst, Smi* src) { 8083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 8093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (src->value() == 0) { 8103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testq(dst, dst); 8113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 812756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Register constant_reg = GetSmiConstant(src); 813756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick cmpq(dst, constant_reg); 814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 818f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid MacroAssembler::SmiCompare(Register dst, const Operand& src) { 8196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block cmpq(dst, src); 8206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 8216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(const Operand& dst, Register src) { 8243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block cmpq(dst, src); 825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(const Operand& dst, Smi* src) { 8297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch cmpl(Operand(dst, kSmiShift / kBitsPerByte), Immediate(src->value())); 830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8339dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::SmiCompareInteger32(const Operand& dst, Register src) { 8349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen cmpl(Operand(dst, kSmiShift / kBitsPerByte), src); 8359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 8369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 8379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 8383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::PositiveSmiTimesPowerOfTwoToInteger64(Register dst, 8393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register src, 8403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int power) { 8413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(power >= 0); 8423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(power < 64); 8433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (power == 0) { 8443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiToInteger64(dst, src); 8453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block return; 8463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 8473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src)) { 8483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 8493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 8503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (power < kSmiShift) { 8513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block sar(dst, Immediate(kSmiShift - power)); 8523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (power > kSmiShift) { 8533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(power - kSmiShift)); 8543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid MacroAssembler::PositiveSmiDivPowerOfTwoToInteger32(Register dst, 8597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register src, 8607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch int power) { 8617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT((0 <= power) && (power < 32)); 8627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (dst.is(src)) { 8637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch shr(dst, Immediate(power + kSmiShift)); 8647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 8657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch UNIMPLEMENTED(); // Not used. 8667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 8677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 8687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 8697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 8703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockCondition MacroAssembler::CheckSmi(Register src) { 871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, kSmiTag); 872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block testb(src, Immediate(kSmiTagMask)); 8733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block return zero; 874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCondition MacroAssembler::CheckPositiveSmi(Register src) { 878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, kSmiTag); 8798defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Make mask 0x8000000000000001 and test that both bits are zero. 8803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(kScratchRegister, src); 8813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block rol(kScratchRegister, Immediate(1)); 8828defd9ff6930b4e24729971a61cf7469daf119beSteve Block testb(kScratchRegister, Immediate(3)); 883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return zero; 884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCondition MacroAssembler::CheckBothSmi(Register first, Register second) { 888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (first.is(second)) { 889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return CheckSmi(first); 890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 8918defd9ff6930b4e24729971a61cf7469daf119beSteve Block ASSERT(kSmiTag == 0 && kHeapObjectTag == 1 && kHeapObjectTagMask == 3); 8928defd9ff6930b4e24729971a61cf7469daf119beSteve Block leal(kScratchRegister, Operand(first, second, times_1, 0)); 8938defd9ff6930b4e24729971a61cf7469daf119beSteve Block testb(kScratchRegister, Immediate(0x03)); 8943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block return zero; 895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 898d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeCondition MacroAssembler::CheckBothPositiveSmi(Register first, 899d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Register second) { 900d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (first.is(second)) { 901d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return CheckPositiveSmi(first); 902d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 9038defd9ff6930b4e24729971a61cf7469daf119beSteve Block movq(kScratchRegister, first); 9048defd9ff6930b4e24729971a61cf7469daf119beSteve Block or_(kScratchRegister, second); 905d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke rol(kScratchRegister, Immediate(1)); 906d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke testl(kScratchRegister, Immediate(0x03)); 907d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return zero; 908d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 909d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 910d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 911bb769b257e753aafcbd96767abb2abc645eaa20cBen MurdochCondition MacroAssembler::CheckEitherSmi(Register first, 912bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Register second, 913bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Register scratch) { 914e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (first.is(second)) { 915e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return CheckSmi(first); 916e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 917bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if (scratch.is(second)) { 918bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch andl(scratch, first); 919bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } else { 920bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if (!scratch.is(first)) { 921bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch movl(scratch, first); 922bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } 923bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch andl(scratch, second); 924bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } 925bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch testb(scratch, Immediate(kSmiTagMask)); 926e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return zero; 927e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 928e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 929e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCondition MacroAssembler::CheckIsMinSmi(Register src) { 9318defd9ff6930b4e24729971a61cf7469daf119beSteve Block ASSERT(!src.is(kScratchRegister)); 9328defd9ff6930b4e24729971a61cf7469daf119beSteve Block // If we overflow by subtracting one, it's the minimal smi value. 9338defd9ff6930b4e24729971a61cf7469daf119beSteve Block cmpq(src, kSmiConstantRegister); 9348defd9ff6930b4e24729971a61cf7469daf119beSteve Block return overflow; 935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockCondition MacroAssembler::CheckInteger32ValidSmiValue(Register src) { 9393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // A 32-bit integer value can always be converted to a smi. 9403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block return always; 941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockCondition MacroAssembler::CheckUInteger32ValidSmiValue(Register src) { 9453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // An unsigned 32-bit integer value is valid as long as the high bit 9463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // is not set. 9478defd9ff6930b4e24729971a61cf7469daf119beSteve Block testl(src, src); 9488defd9ff6930b4e24729971a61cf7469daf119beSteve Block return positive; 949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiNeg(Register dst, Register src, Label* on_smi_result) { 9533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (dst.is(src)) { 9543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 9553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(kScratchRegister, src); 9563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block neg(dst); // Low 32 bits are retained as zero by negation. 9573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Test if result is zero or Smi::kMinValue. 9583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block cmpq(dst, kScratchRegister); 9593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(not_equal, on_smi_result); 9603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src, kScratchRegister); 9613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 9623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 9633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block neg(dst); 9643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block cmpq(dst, src); 9653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // If the result is zero or Smi::kMinValue, negation failed to create a smi. 9663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(not_equal, on_smi_result); 967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiAdd(Register dst, 972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2, 974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smi_result) { 975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(src2)); 9766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (on_not_smi_result == NULL) { 9776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // No overflow checking. Use only when it's known that 9786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // overflowing is impossible. 9796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (dst.is(src1)) { 9806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block addq(dst, src2); 9816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 9826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(dst, src1); 9836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block addq(dst, src2); 9846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 9859dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Assert(no_overflow, "Smi addition overflow"); 9866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (dst.is(src1)) { 9879dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen movq(kScratchRegister, src1); 9889dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen addq(kScratchRegister, src2); 9899dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen j(overflow, on_not_smi_result); 9909dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen movq(dst, kScratchRegister); 9913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 9923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src1); 9933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block addq(dst, src2); 9943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(overflow, on_not_smi_result); 995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiSub(Register dst, 1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2, 1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smi_result) { 1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(src2)); 1004d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (on_not_smi_result == NULL) { 1005d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // No overflow checking. Use only when it's known that 1006d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // overflowing is impossible (e.g., subtracting two positive smis). 1007d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (dst.is(src1)) { 1008d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke subq(dst, src2); 1009d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else { 1010d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke movq(dst, src1); 1011d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke subq(dst, src2); 1012d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 10139dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Assert(no_overflow, "Smi subtraction overflow"); 1014d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else if (dst.is(src1)) { 10159dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen cmpq(dst, src2); 10169dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen j(overflow, on_not_smi_result); 10173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block subq(dst, src2); 10183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 10193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src1); 10203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block subq(dst, src2); 10213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(overflow, on_not_smi_result); 1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10266ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::SmiSub(Register dst, 10276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register src1, 1028f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke const Operand& src2, 10296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label* on_not_smi_result) { 10306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (on_not_smi_result == NULL) { 10316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // No overflow checking. Use only when it's known that 10326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // overflowing is impossible (e.g., subtracting two positive smis). 10336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (dst.is(src1)) { 10346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block subq(dst, src2); 10356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 10366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(dst, src1); 10376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block subq(dst, src2); 10386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 10399dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Assert(no_overflow, "Smi subtraction overflow"); 10406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (dst.is(src1)) { 10418defd9ff6930b4e24729971a61cf7469daf119beSteve Block movq(kScratchRegister, src2); 10428defd9ff6930b4e24729971a61cf7469daf119beSteve Block cmpq(src1, kScratchRegister); 10439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen j(overflow, on_not_smi_result); 10448defd9ff6930b4e24729971a61cf7469daf119beSteve Block subq(src1, kScratchRegister); 10456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 10466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(dst, src1); 10476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block subq(dst, src2); 10486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block j(overflow, on_not_smi_result); 10496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 10506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 10516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiMul(Register dst, 1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2, 1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smi_result) { 1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(src2)); 10573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 10583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src1.is(kScratchRegister)); 10593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src2.is(kScratchRegister)); 1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (dst.is(src1)) { 10623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label failure, zero_correct_result; 10633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(kScratchRegister, src1); // Create backup for later testing. 10643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiToInteger64(dst, src1); 10653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block imul(dst, src2); 10663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(overflow, &failure); 10673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 10683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check for negative zero result. If product is zero, and one 10693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // argument is negative, go to slow case. 10703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label correct_result; 10713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testq(dst, dst); 10723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(not_zero, &correct_result); 1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, kScratchRegister); 10753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block xor_(dst, src2); 10763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(positive, &zero_correct_result); // Result was positive zero. 1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bind(&failure); // Reused failure exit, restores src1. 10793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src1, kScratchRegister); 10803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block jmp(on_not_smi_result); 1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bind(&zero_correct_result); 10833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block xor_(dst, dst); 10843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 10853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bind(&correct_result); 10863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 10873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiToInteger64(dst, src1); 10883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block imul(dst, src2); 10893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(overflow, on_not_smi_result); 10903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check for negative zero result. If product is zero, and one 10913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // argument is negative, go to slow case. 10923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label correct_result; 10933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testq(dst, dst); 10943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(not_zero, &correct_result); 10953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // One of src1 and src2 is zero, the check whether the other is 10963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // negative. 10973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(kScratchRegister, src1); 10983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block xor_(kScratchRegister, src2); 10993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(negative, on_not_smi_result); 11003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bind(&correct_result); 11013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiTryAddConstant(Register dst, 1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 11073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Smi* constant, 1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smi_result) { 1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Does not assume that src is a smi. 11103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT_EQ(static_cast<int>(1), static_cast<int>(kSmiTagMask)); 1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, kSmiTag); 11123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 11133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src.is(kScratchRegister)); 1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 11153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block JumpIfNotSmi(src, on_not_smi_result); 11163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register tmp = (dst.is(src) ? kScratchRegister : dst); 11178defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(tmp, constant); 11183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block addq(tmp, src); 11193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(overflow, on_not_smi_result); 11203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (dst.is(src)) { 11213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, tmp); 11223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 11233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 11243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 11253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 11263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiAddConstant(Register dst, Register src, Smi* constant) { 11273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (constant->value() == 0) { 11283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src)) { 11293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 11303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 11318defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 11323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (dst.is(src)) { 11333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 11348defd9ff6930b4e24729971a61cf7469daf119beSteve Block switch (constant->value()) { 11358defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 1: 11368defd9ff6930b4e24729971a61cf7469daf119beSteve Block addq(dst, kSmiConstantRegister); 11378defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 11388defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 2: 11398defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(src, kSmiConstantRegister, times_2, 0)); 11408defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 11418defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 4: 11428defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(src, kSmiConstantRegister, times_4, 0)); 11438defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 11448defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 8: 11458defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(src, kSmiConstantRegister, times_8, 0)); 11468defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 11478defd9ff6930b4e24729971a61cf7469daf119beSteve Block default: 11488defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register constant_reg = GetSmiConstant(constant); 11498defd9ff6930b4e24729971a61cf7469daf119beSteve Block addq(dst, constant_reg); 11508defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 11518defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 11538defd9ff6930b4e24729971a61cf7469daf119beSteve Block switch (constant->value()) { 11548defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 1: 11558defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(src, kSmiConstantRegister, times_1, 0)); 11568defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 11578defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 2: 11588defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(src, kSmiConstantRegister, times_2, 0)); 11598defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 11608defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 4: 11618defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(src, kSmiConstantRegister, times_4, 0)); 11628defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 11638defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 8: 11648defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(src, kSmiConstantRegister, times_8, 0)); 11658defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 11668defd9ff6930b4e24729971a61cf7469daf119beSteve Block default: 11678defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(dst, constant); 11688defd9ff6930b4e24729971a61cf7469daf119beSteve Block addq(dst, src); 11698defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 11708defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1175f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid MacroAssembler::SmiAddConstant(const Operand& dst, Smi* constant) { 1176f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (constant->value() != 0) { 11777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch addl(Operand(dst, kSmiShift / kBitsPerByte), Immediate(constant->value())); 1178f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1179f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1180f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1181f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiAddConstant(Register dst, 1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 11843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Smi* constant, 1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smi_result) { 11863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (constant->value() == 0) { 11873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src)) { 11883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 11903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (dst.is(src)) { 11913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 11923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 11938defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(kScratchRegister, constant); 11948defd9ff6930b4e24729971a61cf7469daf119beSteve Block addq(kScratchRegister, src); 11959dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen j(overflow, on_not_smi_result); 11969dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen movq(dst, kScratchRegister); 1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 11988defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(dst, constant); 11993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block addq(dst, src); 12003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(overflow, on_not_smi_result); 12013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 12023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 12033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiSubConstant(Register dst, Register src, Smi* constant) { 12063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (constant->value() == 0) { 1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!dst.is(src)) { 12083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 1209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 12103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (dst.is(src)) { 12113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 12128defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register constant_reg = GetSmiConstant(constant); 12138defd9ff6930b4e24729971a61cf7469daf119beSteve Block subq(dst, constant_reg); 12143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 12153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (constant->value() == Smi::kMinValue) { 12168defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(dst, constant); 12179dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Adding and subtracting the min-value gives the same result, it only 12189dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // differs on the overflow bit, which we don't check here. 12199dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen addq(dst, src); 1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 12219dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Subtract by adding the negation. 12228defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(dst, Smi::FromInt(-constant->value())); 12233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block addq(dst, src); 1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiSubConstant(Register dst, 1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 12313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Smi* constant, 1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smi_result) { 12333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (constant->value() == 0) { 12343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src)) { 12353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 12373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (dst.is(src)) { 12383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 12393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (constant->value() == Smi::kMinValue) { 12409dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Subtracting min-value from any non-negative value will overflow. 12419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // We test the non-negativeness before doing the subtraction. 12429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen testq(src, src); 12439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen j(not_sign, on_not_smi_result); 12448defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(kScratchRegister, constant); 12453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block subq(dst, kScratchRegister); 12469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } else { 12479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Subtract by adding the negation. 12488defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(kScratchRegister, Smi::FromInt(-constant->value())); 12499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen addq(kScratchRegister, dst); 12503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(overflow, on_not_smi_result); 12519dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen movq(dst, kScratchRegister); 12529dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 12539dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } else { 12549dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (constant->value() == Smi::kMinValue) { 12559dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Subtracting min-value from any non-negative value will overflow. 12569dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // We test the non-negativeness before doing the subtraction. 12579dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen testq(src, src); 12589dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen j(not_sign, on_not_smi_result); 12598defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(dst, constant); 12609dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Adding and subtracting the min-value gives the same result, it only 12619dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // differs on the overflow bit, which we don't check here. 12629dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen addq(dst, src); 12633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 12649dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Subtract by adding the negation. 12658defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(dst, Smi::FromInt(-(constant->value()))); 12663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block addq(dst, src); 12673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(overflow, on_not_smi_result); 12683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiDiv(Register dst, 1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2, 1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smi_result) { 12773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src1.is(kScratchRegister)); 12783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src2.is(kScratchRegister)); 12793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!src2.is(rax)); 1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!src2.is(rdx)); 1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!src1.is(rdx)); 1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for 0 divisor (result is +/-Infinity). 1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label positive_divisor; 12863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testq(src2, src2); 1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(zero, on_not_smi_result); 1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (src1.is(rax)) { 12903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(kScratchRegister, src1); 1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 12923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiToInteger32(rax, src1); 12933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // We need to rule out dividing Smi::kMinValue by -1, since that would 12943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // overflow in idiv and raise an exception. 12953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // We combine this with negative zero test (negative zero only happens 12963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // when dividing zero by a negative number). 12973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // We overshoot a little and go to slow case if we divide min-value 12993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // by any negative value, not just -1. 13003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label safe_div; 13013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testl(rax, Immediate(0x7fffffff)); 13023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(not_zero, &safe_div); 13033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testq(src2, src2); 13043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (src1.is(rax)) { 13053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(positive, &safe_div); 13063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src1, kScratchRegister); 13073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block jmp(on_not_smi_result); 13083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 13093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(negative, on_not_smi_result); 13103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 13113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bind(&safe_div); 1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiToInteger32(src2, src2); 13143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Sign extend src1 into edx:eax. 13153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block cdq(); 1316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block idivl(src2); 13173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Integer32ToSmi(src2, src2); 1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the remainder is zero. 1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block testl(rdx, rdx); 13203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (src1.is(rax)) { 13213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label smi_result; 13223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(zero, &smi_result); 13233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src1, kScratchRegister); 13243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block jmp(on_not_smi_result); 13253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bind(&smi_result); 13263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 13273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(not_zero, on_not_smi_result); 13283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 13293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src1) && src1.is(rax)) { 13303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src1, kScratchRegister); 13313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Integer32ToSmi(dst, rax); 1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiMod(Register dst, 1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2, 1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smi_result) { 1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(kScratchRegister)); 1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!src1.is(kScratchRegister)); 1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!src2.is(kScratchRegister)); 1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!src2.is(rax)); 1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!src2.is(rdx)); 1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!src1.is(rdx)); 13463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src1.is(src2)); 1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testq(src2, src2); 1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(zero, on_not_smi_result); 1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (src1.is(rax)) { 13523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(kScratchRegister, src1); 13533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 13543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiToInteger32(rax, src1); 13553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiToInteger32(src2, src2); 13563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Test for the edge case of dividing Smi::kMinValue by -1 (will overflow). 13583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label safe_div; 13593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block cmpl(rax, Immediate(Smi::kMinValue)); 13603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(not_equal, &safe_div); 13613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block cmpl(src2, Immediate(-1)); 13623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(not_equal, &safe_div); 13633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Retag inputs and go slow case. 13643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Integer32ToSmi(src2, src2); 13653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (src1.is(rax)) { 13663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src1, kScratchRegister); 1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 13683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block jmp(on_not_smi_result); 13693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bind(&safe_div); 13703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Sign extend eax into edx:eax. 1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cdq(); 1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block idivl(src2); 13743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Restore smi tags on inputs. 13753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Integer32ToSmi(src2, src2); 1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (src1.is(rax)) { 13773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src1, kScratchRegister); 1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 13793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check for a negative zero result. If the result is zero, and the 13803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // dividend is negative, go slow to return a floating point negative zero. 13813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label smi_result; 13823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testl(rdx, rdx); 13833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(not_zero, &smi_result); 13843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testq(src1, src1); 1385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(negative, on_not_smi_result); 13863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bind(&smi_result); 13873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Integer32ToSmi(dst, rdx); 1388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiNot(Register dst, Register src) { 13923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 13933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src.is(kScratchRegister)); 13943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Set tag and padding bits before negating, so that they are zero afterwards. 13953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movl(kScratchRegister, Immediate(~0)); 1396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (dst.is(src)) { 13973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block xor_(dst, kScratchRegister); 1398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 13993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block lea(dst, Operand(src, kScratchRegister, times_1, 0)); 1400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 14013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block not_(dst); 1402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiAnd(Register dst, Register src1, Register src2) { 14063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(src2)); 1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!dst.is(src1)) { 14083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src1); 1409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block and_(dst, src2); 1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 14143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiAndConstant(Register dst, Register src, Smi* constant) { 14153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (constant->value() == 0) { 14163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block xor_(dst, dst); 14173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (dst.is(src)) { 14183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 14198defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register constant_reg = GetSmiConstant(constant); 14208defd9ff6930b4e24729971a61cf7469daf119beSteve Block and_(dst, constant_reg); 14213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 14228defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(dst, constant); 14233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block and_(dst, src); 1424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiOr(Register dst, Register src1, Register src2) { 1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!dst.is(src1)) { 14303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src1); 1431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block or_(dst, src2); 1433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 14363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiOrConstant(Register dst, Register src, Smi* constant) { 14373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (dst.is(src)) { 14383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 14398defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register constant_reg = GetSmiConstant(constant); 14408defd9ff6930b4e24729971a61cf7469daf119beSteve Block or_(dst, constant_reg); 14413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 14428defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(dst, constant); 14433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block or_(dst, src); 1444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 14473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiXor(Register dst, Register src1, Register src2) { 1449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!dst.is(src1)) { 14503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src1); 1451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block xor_(dst, src2); 1453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 14563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiXorConstant(Register dst, Register src, Smi* constant) { 14573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (dst.is(src)) { 14583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 14598defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register constant_reg = GetSmiConstant(constant); 14608defd9ff6930b4e24729971a61cf7469daf119beSteve Block xor_(dst, constant_reg); 14613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 14628defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(dst, constant); 14633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block xor_(dst, src); 1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftArithmeticRightConstant(Register dst, 1469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int shift_value) { 14713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(is_uint5(shift_value)); 1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (shift_value > 0) { 1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (dst.is(src)) { 14743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block sar(dst, Immediate(shift_value + kSmiShift)); 14753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(kSmiShift)); 1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNIMPLEMENTED(); // Not used. 1478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftLogicalRightConstant(Register dst, 1484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 1485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int shift_value, 1486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smi_result) { 1487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Logic right shift interprets its result as an *unsigned* number. 1488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (dst.is(src)) { 1489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNIMPLEMENTED(); // Not used. 1490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 14913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 14923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (shift_value == 0) { 14933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testq(dst, dst); 1494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(negative, on_not_smi_result); 1495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 14963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shr(dst, Immediate(shift_value + kSmiShift)); 14973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(kSmiShift)); 1498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftLeftConstant(Register dst, 1503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 150425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen int shift_value) { 15053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src)) { 15063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 15073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 15083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (shift_value > 0) { 15093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(shift_value)); 1510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftLeft(Register dst, 1515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 151625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Register src2) { 1517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(rcx)); 1518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label result_ok; 15193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Untag shift amount. 15203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src1)) { 15213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src1); 1522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 15233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiToInteger32(rcx, src2); 15243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Shift amount specified by lower 5 bits, not six as the shl opcode. 15253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block and_(rcx, Immediate(0x1f)); 1526d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block shl_cl(dst); 1527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftLogicalRight(Register dst, 1531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 1532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2, 1533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smi_result) { 15343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 15353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src1.is(kScratchRegister)); 15363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src2.is(kScratchRegister)); 1537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(rcx)); 1538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label result_ok; 15393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (src1.is(rcx) || src2.is(rcx)) { 15403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(kScratchRegister, rcx); 15413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 15423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src1)) { 15433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src1); 15443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SmiToInteger32(rcx, src2); 15463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block orl(rcx, Immediate(kSmiShift)); 1547d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block shr_cl(dst); // Shift is rcx modulo 0x1f + 32. 15483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(kSmiShift)); 15493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testq(dst, dst); 15503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (src1.is(rcx) || src2.is(rcx)) { 15513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label positive_result; 15523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(positive, &positive_result); 15533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (src1.is(rcx)) { 15543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src1, kScratchRegister); 15553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 15563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src2, kScratchRegister); 15573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 15583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block jmp(on_not_smi_result); 15593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bind(&positive_result); 15603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 15613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(negative, on_not_smi_result); // src2 was zero and src1 negative. 1562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftArithmeticRight(Register dst, 1567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 1568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2) { 15693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 15703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src1.is(kScratchRegister)); 15713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src2.is(kScratchRegister)); 1572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(rcx)); 15733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (src1.is(rcx)) { 15743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(kScratchRegister, src1); 15753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (src2.is(rcx)) { 15763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(kScratchRegister, src2); 15773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 15783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src1)) { 15793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src1); 15803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SmiToInteger32(rcx, src2); 15823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block orl(rcx, Immediate(kSmiShift)); 1583d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block sar_cl(dst); // Shift 32 + original rcx & 0x1f. 15843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(kSmiShift)); 15853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (src1.is(rcx)) { 15863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src1, kScratchRegister); 15873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (src2.is(rcx)) { 15883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src2, kScratchRegister); 15893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SelectNonSmi(Register dst, 1594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 1595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2, 1596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_smis) { 15973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 15983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src1.is(kScratchRegister)); 15993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src2.is(kScratchRegister)); 1600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(src1)); 1601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(src2)); 1602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Both operands must not be smis. 1603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 16043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (allow_stub_calls()) { // Check contains a stub call. 16053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Condition not_both_smis = NegateCondition(CheckBothSmi(src1, src2)); 16063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Check(not_both_smis, "Both registers were smis in SelectNonSmi."); 16073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, kSmiTag); 1610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, Smi::FromInt(0)); 16113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movl(kScratchRegister, Immediate(kSmiTagMask)); 1612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block and_(kScratchRegister, src1); 1613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block testl(kScratchRegister, src2); 16143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // If non-zero then both are smis. 1615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(not_zero, on_not_smis); 1616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Exactly one operand is a smi. 1618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(1, static_cast<int>(kSmiTagMask)); 1619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // kScratchRegister still holds src1 & kSmiTag, which is either zero or one. 1620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block subq(kScratchRegister, Immediate(1)); 1621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If src1 is a smi, then scratch register all 1s, else it is all 0s. 1622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(dst, src1); 1623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block xor_(dst, src2); 1624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block and_(dst, kScratchRegister); 1625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If src1 is a smi, dst holds src1 ^ src2, else it is zero. 1626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block xor_(dst, src1); 16273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // If src1 is a smi, dst is src2, else it is src1, i.e., the non-smi. 1628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16308defd9ff6930b4e24729971a61cf7469daf119beSteve Block 16313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockSmiIndex MacroAssembler::SmiToIndex(Register dst, 16323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register src, 16333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int shift) { 1634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_uint6(shift)); 16353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // There is a possible optimization if shift is in the range 60-63, but that 16363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // will (and must) never happen. 16373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src)) { 16383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 16393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 16403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (shift < kSmiShift) { 16413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block sar(dst, Immediate(kSmiShift - shift)); 16423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 16433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(shift - kSmiShift)); 16443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return SmiIndex(dst, times_1); 1646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockSmiIndex MacroAssembler::SmiToNegativeIndex(Register dst, 1649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 1650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int shift) { 1651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Register src holds a positive smi. 1652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_uint6(shift)); 16533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src)) { 16543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 1655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block neg(dst); 16573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (shift < kSmiShift) { 16583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block sar(dst, Immediate(kSmiShift - shift)); 16593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 16603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(shift - kSmiShift)); 16613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return SmiIndex(dst, times_1); 1663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfSmi(Register src, Label* on_smi) { 16673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT_EQ(0, kSmiTag); 16683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Condition smi = CheckSmi(src); 16693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(smi, on_smi); 16703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 16713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfNotSmi(Register src, Label* on_not_smi) { 16743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Condition smi = CheckSmi(src); 16753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(NegateCondition(smi), on_not_smi); 1676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 16793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfNotPositiveSmi(Register src, 16803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label* on_not_positive_smi) { 16813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Condition positive_smi = CheckPositiveSmi(src); 16823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(NegateCondition(positive_smi), on_not_positive_smi); 16833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 16843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 16853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 16863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfSmiEqualsConstant(Register src, 16873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Smi* constant, 16883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label* on_equals) { 16893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiCompare(src, constant); 16903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(equal, on_equals); 16913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 16923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 16933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 16943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfNotValidSmiValue(Register src, Label* on_invalid) { 16953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Condition is_valid = CheckInteger32ValidSmiValue(src); 16963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(NegateCondition(is_valid), on_invalid); 16973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 16983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 16993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 17003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfUIntNotValidSmiValue(Register src, 17013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label* on_invalid) { 17023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Condition is_valid = CheckUInteger32ValidSmiValue(src); 17033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(NegateCondition(is_valid), on_invalid); 17043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 17053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 17063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 17073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfNotBothSmi(Register src1, Register src2, 17083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label* on_not_both_smi) { 17093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Condition both_smi = CheckBothSmi(src1, src2); 17103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block j(NegateCondition(both_smi), on_not_both_smi); 1711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1714d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid MacroAssembler::JumpIfNotBothPositiveSmi(Register src1, Register src2, 1715d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label* on_not_both_smi) { 1716d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Condition both_smi = CheckBothPositiveSmi(src1, src2); 1717d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke j(NegateCondition(both_smi), on_not_both_smi); 1718d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 1719d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1720d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1721d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1722e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register first_object, 1723e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register second_object, 1724e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch1, 1725e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch2, 1726e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* on_fail) { 1727e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that both objects are not smis. 1728e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Condition either_smi = CheckEitherSmi(first_object, second_object); 1729e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke j(either_smi, on_fail); 1730e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1731e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Load instance type for both strings. 1732e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movq(scratch1, FieldOperand(first_object, HeapObject::kMapOffset)); 1733e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movq(scratch2, FieldOperand(second_object, HeapObject::kMapOffset)); 1734e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movzxbl(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset)); 1735e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movzxbl(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset)); 1736e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1737e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that both are flat ascii strings. 1738e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(kNotStringTag != 0); 1739e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const int kFlatAsciiStringMask = 1740e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; 1741d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke const int kFlatAsciiStringTag = ASCII_STRING_TYPE; 1742e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1743e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke andl(scratch1, Immediate(kFlatAsciiStringMask)); 1744e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke andl(scratch2, Immediate(kFlatAsciiStringMask)); 1745e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Interleave the bits to check both scratch1 and scratch2 in one test. 1746e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3)); 1747e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke lea(scratch1, Operand(scratch1, scratch2, times_8, 0)); 1748e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke cmpl(scratch1, 1749d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Immediate(kFlatAsciiStringTag + (kFlatAsciiStringTag << 3))); 1750e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke j(not_equal, on_fail); 1751e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1752e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1753e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 17546ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii( 17556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register instance_type, 17566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch, 17576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label *failure) { 17586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (!scratch.is(instance_type)) { 17596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movl(scratch, instance_type); 17606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 17616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int kFlatAsciiStringMask = 17636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; 17646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block andl(scratch, Immediate(kFlatAsciiStringMask)); 17666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block cmpl(scratch, Immediate(kStringTag | kSeqStringTag | kAsciiStringTag)); 17676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block j(not_equal, failure); 17686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 17696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17716ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialAscii( 17726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register first_object_instance_type, 17736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register second_object_instance_type, 17746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch1, 17756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch2, 17766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label* on_fail) { 17776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Load instance type for both strings. 17786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(scratch1, first_object_instance_type); 17796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(scratch2, second_object_instance_type); 17806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that both are flat ascii strings. 17826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(kNotStringTag != 0); 17836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int kFlatAsciiStringMask = 17846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; 17856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int kFlatAsciiStringTag = ASCII_STRING_TYPE; 17866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block andl(scratch1, Immediate(kFlatAsciiStringMask)); 17886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block andl(scratch2, Immediate(kFlatAsciiStringMask)); 17896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Interleave the bits to check both scratch1 and scratch2 in one test. 17906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3)); 17916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block lea(scratch1, Operand(scratch1, scratch2, times_8, 0)); 17926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block cmpl(scratch1, 17936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Immediate(kFlatAsciiStringTag + (kFlatAsciiStringTag << 3))); 17946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block j(not_equal, on_fail); 17956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 17966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Move(Register dst, Handle<Object> source) { 1799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!source->IsFailure()); 1800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (source->IsSmi()) { 18013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(dst, Smi::cast(*source)); 1802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(dst, source, RelocInfo::EMBEDDED_OBJECT); 1804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Move(const Operand& dst, Handle<Object> source) { 18093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!source->IsFailure()); 1810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (source->IsSmi()) { 18113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(dst, Smi::cast(*source)); 1812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT); 1814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(dst, kScratchRegister); 1815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Cmp(Register dst, Handle<Object> source) { 18203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (source->IsSmi()) { 18213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiCompare(dst, Smi::cast(*source)); 18223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 18233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(kScratchRegister, source); 18243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block cmpq(dst, kScratchRegister); 18253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Cmp(const Operand& dst, Handle<Object> source) { 1830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (source->IsSmi()) { 18313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiCompare(dst, Smi::cast(*source)); 1832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(source->IsHeapObject()); 1834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT); 1835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(dst, kScratchRegister); 1836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Push(Handle<Object> source) { 1841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (source->IsSmi()) { 18423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Push(Smi::cast(*source)); 1843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(source->IsHeapObject()); 1845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT); 1846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(kScratchRegister); 1847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Push(Smi* source) { 18523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block intptr_t smi = reinterpret_cast<intptr_t>(source); 18533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (is_int32(smi)) { 18543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block push(Immediate(static_cast<int32_t>(smi))); 18553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 18568defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register constant = GetSmiConstant(source); 18578defd9ff6930b4e24729971a61cf7469daf119beSteve Block push(constant); 18583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 18593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 18603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 18613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1862e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::Drop(int stack_elements) { 1863e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (stack_elements > 0) { 1864e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke addq(rsp, Immediate(stack_elements * kPointerSize)); 1865e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1866e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1867e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1868e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 18693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::Test(const Operand& src, Smi* source) { 1870f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke testl(Operand(src, kIntSize), Immediate(source->value())); 1871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Jump(ExternalReference ext) { 1875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, ext); 1876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block jmp(kScratchRegister); 1877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Jump(Address destination, RelocInfo::Mode rmode) { 1881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, destination, rmode); 1882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block jmp(kScratchRegister); 1883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Jump(Handle<Code> code_object, RelocInfo::Mode rmode) { 18873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // TODO(X64): Inline this 18883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block jmp(code_object, rmode); 1889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Call(ExternalReference ext) { 1893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, ext); 1894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block call(kScratchRegister); 1895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Call(Address destination, RelocInfo::Mode rmode) { 1899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, destination, rmode); 1900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block call(kScratchRegister); 1901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Call(Handle<Code> code_object, RelocInfo::Mode rmode) { 1905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(RelocInfo::IsCodeTarget(rmode)); 1906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block WriteRecordedPositions(); 19073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block call(code_object, rmode); 1908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::PushTryHandler(CodeLocation try_location, 1912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HandlerType type) { 1913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Adjust this code if not the case. 1914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); 1915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The pc (return address) is already on TOS. This code pushes state, 1917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // frame pointer and current handler. Check that they are expected 1918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // next on the stack, in that order. 1919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(StackHandlerConstants::kStateOffset, 1920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StackHandlerConstants::kPCOffset - kPointerSize); 1921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(StackHandlerConstants::kFPOffset, 1922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StackHandlerConstants::kStateOffset - kPointerSize); 1923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(StackHandlerConstants::kNextOffset, 1924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StackHandlerConstants::kFPOffset - kPointerSize); 1925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (try_location == IN_JAVASCRIPT) { 1927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (type == TRY_CATCH_HANDLER) { 1928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Immediate(StackHandler::TRY_CATCH)); 1929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Immediate(StackHandler::TRY_FINALLY)); 1931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(rbp); 1933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(try_location == IN_JS_ENTRY); 1935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The frame pointer does not point to a JS frame so we save NULL 1936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // for rbp. We expect the code throwing an exception to check rbp 1937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // before dereferencing it to restore the context. 1938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Immediate(StackHandler::ENTRY)); 1939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Immediate(0)); // NULL frame pointer. 1940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save the current handler. 1942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, ExternalReference(Top::k_handler_address)); 1943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Operand(kScratchRegister, 0)); 1944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Link this handler. 1945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(Operand(kScratchRegister, 0), rsp); 1946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1949e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::PopTryHandler() { 1950e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(0, StackHandlerConstants::kNextOffset); 1951e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Unlink this handler. 1952e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movq(kScratchRegister, ExternalReference(Top::k_handler_address)); 1953e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke pop(Operand(kScratchRegister, 0)); 1954e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Remove the remaining fields. 1955e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke addq(rsp, Immediate(StackHandlerConstants::kSize - kPointerSize)); 1956e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1957e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1958e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Ret() { 1960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ret(0); 1961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::FCmp() { 19653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block fucomip(); 19668defd9ff6930b4e24729971a61cf7469daf119beSteve Block fstp(0); 1967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpObjectType(Register heap_object, 1971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstanceType type, 1972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register map) { 1973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(map, FieldOperand(heap_object, HeapObject::kMapOffset)); 1974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CmpInstanceType(map, type); 1975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpInstanceType(Register map, InstanceType type) { 1979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpb(FieldOperand(map, Map::kInstanceTypeOffset), 1980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(static_cast<int8_t>(type))); 1981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 19843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::CheckMap(Register obj, 19853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Handle<Map> map, 19863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Label* fail, 19873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu bool is_heap_object) { 19883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (!is_heap_object) { 19893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu JumpIfSmi(obj, fail); 19903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 19913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Cmp(FieldOperand(obj, HeapObject::kMapOffset), map); 19923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu j(not_equal, fail); 19933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 19943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 19953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid MacroAssembler::AbortIfNotNumber(Register object) { 1997402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Label ok; 1998402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Condition is_smi = CheckSmi(object); 1999402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu j(is_smi, &ok); 2000402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Cmp(FieldOperand(object, HeapObject::kMapOffset), 2001402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Factory::heap_number_map()); 2002f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Assert(equal, "Operand not a number"); 2003402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu bind(&ok); 2004402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 2005402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 2006402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 2007756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid MacroAssembler::AbortIfSmi(Register object) { 2008756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Label ok; 2009756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Condition is_smi = CheckSmi(object); 2010756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Assert(NegateCondition(is_smi), "Operand is a smi"); 2011756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick} 2012756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 2013756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 2014f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid MacroAssembler::AbortIfNotSmi(Register object) { 20156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label ok; 20166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Condition is_smi = CheckSmi(object); 2017756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Assert(is_smi, "Operand is not a smi"); 20186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 20196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 20206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 20219dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::AbortIfNotRootValue(Register src, 20229dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Heap::RootListIndex root_value_index, 20239dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const char* message) { 20249dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen ASSERT(!src.is(kScratchRegister)); 20259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen LoadRoot(kScratchRegister, root_value_index); 20269dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen cmpq(src, kScratchRegister); 20279dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Check(equal, message); 20289dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 20299dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 20309dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 20319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 2032d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeCondition MacroAssembler::IsObjectStringType(Register heap_object, 2033d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Register map, 2034d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Register instance_type) { 2035d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke movq(map, FieldOperand(heap_object, HeapObject::kMapOffset)); 20364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke movzxbl(instance_type, FieldOperand(map, Map::kInstanceTypeOffset)); 2037d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ASSERT(kNotStringTag != 0); 2038d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke testb(instance_type, Immediate(kIsNotStringMask)); 2039d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return zero; 2040d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 2041d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 2042d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 2043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::TryGetFunctionPrototype(Register function, 2044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 2045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 2046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 2047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block testl(function, Immediate(kSmiTagMask)); 2048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(zero, miss); 2049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the function really is a function. 2051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CmpObjectType(function, JS_FUNCTION_TYPE, result); 2052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(not_equal, miss); 2053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure that the function has an instance prototype. 2055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label non_instance; 2056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block testb(FieldOperand(result, Map::kBitFieldOffset), 2057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(1 << Map::kHasNonInstancePrototype)); 2058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(not_zero, &non_instance); 2059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the prototype or initial map from the function. 2061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(result, 2062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 2063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the prototype or initial map is the hole, don't return it and 2065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // simply miss the cache instead. This will allow us to allocate a 2066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // prototype object on-demand in the runtime system. 2067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CompareRoot(result, Heap::kTheHoleValueRootIndex); 2068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(equal, miss); 2069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the function does not have an initial map, we're done. 2071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label done; 2072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CmpObjectType(result, MAP_TYPE, kScratchRegister); 2073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(not_equal, &done); 2074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the prototype from the initial map. 2076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(result, FieldOperand(result, Map::kPrototypeOffset)); 2077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block jmp(&done); 2078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Non-instance prototype: Fetch prototype from constructor field 2080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // in initial map. 2081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&non_instance); 2082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(result, FieldOperand(result, Map::kConstructorOffset)); 2083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // All done. 2085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&done); 2086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SetCounter(StatsCounter* counter, int value) { 2090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_native_code_counters && counter->Enabled()) { 2091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, ExternalReference(counter)); 2092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movl(Operand(kScratchRegister, 0), Immediate(value)); 2093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::IncrementCounter(StatsCounter* counter, int value) { 2098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(value > 0); 2099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_native_code_counters && counter->Enabled()) { 2100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, ExternalReference(counter)); 2101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand operand(kScratchRegister, 0); 2102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (value == 1) { 2103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block incl(operand); 2104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 2105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addl(operand, Immediate(value)); 2106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::DecrementCounter(StatsCounter* counter, int value) { 2112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(value > 0); 2113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_native_code_counters && counter->Enabled()) { 2114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, ExternalReference(counter)); 2115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand operand(kScratchRegister, 0); 2116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (value == 1) { 2117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block decl(operand); 2118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 2119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block subl(operand, Immediate(value)); 2120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 212580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#ifdef ENABLE_DEBUGGER_SUPPORT 2126402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::DebugBreak() { 2127402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ASSERT(allow_stub_calls()); 2128402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu xor_(rax, rax); // no arguments 2129402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu movq(rbx, ExternalReference(Runtime::kDebugBreak)); 2130402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu CEntryStub ces(1); 2131402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Call(ces.GetCode(), RelocInfo::DEBUG_BREAK); 2132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2133402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#endif // ENABLE_DEBUGGER_SUPPORT 2134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokePrologue(const ParameterCount& expected, 2137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 2138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> code_constant, 2139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register code_register, 2140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* done, 2141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InvokeFlag flag) { 2142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool definitely_matches = false; 2143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label invoke; 2144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (expected.is_immediate()) { 2145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(actual.is_immediate()); 2146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (expected.immediate() == actual.immediate()) { 2147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block definitely_matches = true; 2148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 21498defd9ff6930b4e24729971a61cf7469daf119beSteve Block Set(rax, actual.immediate()); 2150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (expected.immediate() == 21513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SharedFunctionInfo::kDontAdaptArgumentsSentinel) { 2152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Don't worry about adapting arguments for built-ins that 2153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // don't want that done. Skip adaption code by making it look 2154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // like we have a match between expected and actual number of 2155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // arguments. 2156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block definitely_matches = true; 2157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 21588defd9ff6930b4e24729971a61cf7469daf119beSteve Block Set(rbx, expected.immediate()); 2159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 2162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (actual.is_immediate()) { 2163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Expected is in register, actual is immediate. This is the 2164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // case when we invoke function values without going through the 2165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // IC mechanism. 2166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(expected.reg(), Immediate(actual.immediate())); 2167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(equal, &invoke); 2168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(expected.reg().is(rbx)); 21698defd9ff6930b4e24729971a61cf7469daf119beSteve Block Set(rax, actual.immediate()); 2170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (!expected.reg().is(actual.reg())) { 2171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Both expected and actual are in (different) registers. This 2172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is the case when we invoke functions using call and apply. 2173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(expected.reg(), actual.reg()); 2174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(equal, &invoke); 2175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(actual.reg().is(rax)); 2176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(expected.reg().is(rbx)); 2177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!definitely_matches) { 2181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> adaptor = 2182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)); 2183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!code_constant.is_null()) { 2184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rdx, code_constant, RelocInfo::EMBEDDED_OBJECT); 2185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addq(rdx, Immediate(Code::kHeaderSize - kHeapObjectTag)); 2186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (!code_register.is(rdx)) { 2187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rdx, code_register); 2188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (flag == CALL_FUNCTION) { 2191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Call(adaptor, RelocInfo::CODE_TARGET); 2192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block jmp(done); 2193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 2194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Jump(adaptor, RelocInfo::CODE_TARGET); 2195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&invoke); 2197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeCode(Register code, 2202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& expected, 2203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 2204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InvokeFlag flag) { 2205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label done; 2206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InvokePrologue(expected, actual, Handle<Code>::null(), code, &done, flag); 2207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (flag == CALL_FUNCTION) { 2208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block call(code); 2209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 2210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(flag == JUMP_FUNCTION); 2211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block jmp(code); 2212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&done); 2214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeCode(Handle<Code> code, 2218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& expected, 2219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 2220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::Mode rmode, 2221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InvokeFlag flag) { 2222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label done; 2223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register dummy = rax; 2224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InvokePrologue(expected, actual, code, dummy, &done, flag); 2225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (flag == CALL_FUNCTION) { 2226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Call(code, rmode); 2227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 2228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(flag == JUMP_FUNCTION); 2229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Jump(code, rmode); 2230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&done); 2232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeFunction(Register function, 2236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 2237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InvokeFlag flag) { 2238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(function.is(rdi)); 2239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rdx, FieldOperand(function, JSFunction::kSharedFunctionInfoOffset)); 2240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rsi, FieldOperand(function, JSFunction::kContextOffset)); 2241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movsxlq(rbx, 2242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FieldOperand(rdx, SharedFunctionInfo::kFormalParameterCountOffset)); 2243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Advances rdx to the end of the Code object header, to the start of 2244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the executable code. 2245791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); 2246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ParameterCount expected(rbx); 2248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InvokeCode(rdx, expected, actual, flag); 2249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2252402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::InvokeFunction(JSFunction* function, 2253402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu const ParameterCount& actual, 2254402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu InvokeFlag flag) { 2255402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ASSERT(function->is_compiled()); 2256402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Get the function and setup the context. 2257402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Move(rdi, Handle<JSFunction>(function)); 2258402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); 2259402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 2260402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Invoke the cached code. 2261402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Handle<Code> code(function->code()); 2262402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ParameterCount expected(function->shared()->formal_parameter_count()); 2263402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu InvokeCode(code, expected, actual, RelocInfo::CODE_TARGET, flag); 2264402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 2265402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 2266402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 2267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::EnterFrame(StackFrame::Type type) { 2268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(rbp); 2269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rbp, rsp); 2270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(rsi); // Context. 22713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Push(Smi::FromInt(type)); 2272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT); 2273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(kScratchRegister); 2274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_debug_code) { 2275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, 2276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Factory::undefined_value(), 2277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::EMBEDDED_OBJECT); 2278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(Operand(rsp, 0), kScratchRegister); 2279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(not_equal, "code object not properly patched"); 2280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LeaveFrame(StackFrame::Type type) { 2285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_debug_code) { 22863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(kScratchRegister, Smi::FromInt(type)); 2287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(Operand(rbp, StandardFrameConstants::kMarkerOffset), kScratchRegister); 2288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(equal, "stack frame types must match"); 2289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rsp, rbp); 2291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pop(rbp); 2292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 229580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::EnterExitFramePrologue(bool save_rax) { 2296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Setup the frame structure on the stack. 2297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // All constants are relative to the frame pointer of the exit frame. 2298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize); 2299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize); 2300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize); 2301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(rbp); 2302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rbp, rsp); 2303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 230480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Reserve room for entry stack pointer and push the code object. 23053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize); 2306402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu push(Immediate(0)); // Saved entry sp, patched before call. 2307402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT); 2308402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu push(kScratchRegister); // Accessed from EditFrame::code_slot. 2309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save the frame pointer and the context in top. 2311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address); 2312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference context_address(Top::k_context_address); 2313bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if (save_rax) { 2314bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch movq(r14, rax); // Backup rax before we use it. 2315bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } 2316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rax, rbp); 2318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block store_rax(c_entry_fp_address); 2319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rax, rsi); 2320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block store_rax(context_address); 2321bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 2322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 232380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::EnterExitFrameEpilogue(int result_size, 2324bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch int argc) { 2325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef _WIN64 2326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Reserve space on stack for result and argument structures, if necessary. 2327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result_stack_space = (result_size < 2) ? 0 : result_size * kPointerSize; 2328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Reserve space for the Arguments object. The Windows 64-bit ABI 2329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // requires us to pass this structure as a pointer to its location on 2330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the stack. The structure contains 2 values. 2331bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch int argument_stack_space = argc * kPointerSize; 2332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We also need backing space for 4 parameters, even though 2333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // we only pass one or two parameter, and it is in a register. 2334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int argument_mirror_space = 4 * kPointerSize; 2335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int total_stack_space = 2336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block argument_mirror_space + argument_stack_space + result_stack_space; 2337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block subq(rsp, Immediate(total_stack_space)); 2338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 2339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the required frame alignment for the OS. 2341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kFrameAlignment = OS::ActivationFrameAlignment(); 2342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (kFrameAlignment > 0) { 2343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(IsPowerOf2(kFrameAlignment)); 2344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, Immediate(-kFrameAlignment)); 2345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block and_(rsp, kScratchRegister); 2346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the saved entry sp. 2349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(Operand(rbp, ExitFrameConstants::kSPOffset), rsp); 2350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 235380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::EnterExitFrame(int result_size) { 235480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen EnterExitFramePrologue(true); 2355bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 2356bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Setup argv in callee-saved register r12. It is reused in LeaveExitFrame, 2357bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // so it must be retained across the C-call. 2358bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; 2359bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch lea(r12, Operand(rbp, r14, times_pointer_size, offset)); 2360bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 236180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen EnterExitFrameEpilogue(result_size, 2); 2362bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 2363bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 2364bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 236580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::EnterApiExitFrame(int stack_space, 2366bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch int argc, 2367bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch int result_size) { 236880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen EnterExitFramePrologue(false); 2369bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 2370bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Setup argv in callee-saved register r12. It is reused in LeaveExitFrame, 2371bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // so it must be retained across the C-call. 2372bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; 2373bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch lea(r12, Operand(rbp, (stack_space * kPointerSize) + offset)); 2374bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 237580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen EnterExitFrameEpilogue(result_size, argc); 2376bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 2377bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 2378bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 237980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::LeaveExitFrame(int result_size) { 2380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Registers: 23818defd9ff6930b4e24729971a61cf7469daf119beSteve Block // r12 : argv 2382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the return address from the stack and restore the frame pointer. 2384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rcx, Operand(rbp, 1 * kPointerSize)); 2385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rbp, Operand(rbp, 0 * kPointerSize)); 2386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pop everything up to and including the arguments and the receiver 2388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // from the caller stack. 23898defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(rsp, Operand(r12, 1 * kPointerSize)); 2390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore current context from top and clear it in debug mode. 2392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference context_address(Top::k_context_address); 2393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, context_address); 2394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rsi, Operand(kScratchRegister, 0)); 2395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 2396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(Operand(kScratchRegister, 0), Immediate(0)); 2397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 2398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Push the return address to get ready to return. 2400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(rcx); 2401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Clear the top frame. 2403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address); 2404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, c_entry_fp_address); 2405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(Operand(kScratchRegister, 0), Immediate(0)); 2406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, 2410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 2411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 2412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label same_contexts; 2413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!holder_reg.is(scratch)); 2415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!scratch.is(kScratchRegister)); 2416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load current lexical context from the stack frame. 2417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(scratch, Operand(rbp, StandardFrameConstants::kContextOffset)); 2418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // When generating debug code, make sure the lexical context is set. 2420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_debug_code) { 2421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(scratch, Immediate(0)); 2422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(not_equal, "we should not have an empty lexical context"); 2423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the global context of the current context. 2425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; 2426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(scratch, FieldOperand(scratch, offset)); 2427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(scratch, FieldOperand(scratch, GlobalObject::kGlobalContextOffset)); 2428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check the context is a global context. 2430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_debug_code) { 2431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Cmp(FieldOperand(scratch, HeapObject::kMapOffset), 2432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Factory::global_context_map()); 2433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(equal, "JSGlobalObject::global_context should be a global context."); 2434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if both contexts are the same. 2437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(scratch, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); 2438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(equal, &same_contexts); 2439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compare security tokens. 2441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the security token in the calling global object is 2442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // compatible with the security token in the receiving global 2443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // object. 2444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check the context is a global context. 2446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_debug_code) { 2447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Preserve original value of holder_reg. 2448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(holder_reg); 2449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(holder_reg, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); 2450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CompareRoot(holder_reg, Heap::kNullValueRootIndex); 2451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(not_equal, "JSGlobalProxy::context() should not be null."); 2452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Read the first word and compare to global_context_map(), 2454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(holder_reg, FieldOperand(holder_reg, HeapObject::kMapOffset)); 2455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CompareRoot(holder_reg, Heap::kGlobalContextMapRootIndex); 2456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(equal, "JSGlobalObject::global_context should be a global context."); 2457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pop(holder_reg); 2458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, 2461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); 24623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int token_offset = 24633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Context::kHeaderSize + Context::SECURITY_TOKEN_INDEX * kPointerSize; 2464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(scratch, FieldOperand(scratch, token_offset)); 2465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(scratch, FieldOperand(kScratchRegister, token_offset)); 2466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(not_equal, miss); 2467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&same_contexts); 2469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LoadAllocationTopHelper(Register result, 2473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result_end, 2474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 2475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags) { 2476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_top = 2477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference::new_space_allocation_top_address(); 2478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Just return if allocation top is already known. 2480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((flags & RESULT_CONTAINS_TOP) != 0) { 2481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // No use of scratch if allocation top is provided. 24826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(!scratch.is_valid()); 2483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 2484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Assert that result actually contains top on entry. 2485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, new_space_allocation_top); 2486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(result, Operand(kScratchRegister, 0)); 2487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(equal, "Unexpected allocation top"); 2488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 2489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 2490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 24926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Move address of new object to result. Use scratch register if available, 24936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // and keep address in scratch until call to UpdateAllocationTopHelper. 24946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (scratch.is_valid()) { 2495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!scratch.is(result_end)); 2496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(scratch, new_space_allocation_top); 2497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(result, Operand(scratch, 0)); 24986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (result.is(rax)) { 24996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block load_rax(new_space_allocation_top); 25006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 25016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(kScratchRegister, new_space_allocation_top); 25026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(result, Operand(kScratchRegister, 0)); 2503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::UpdateAllocationTopHelper(Register result_end, 2508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch) { 2509d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (FLAG_debug_code) { 2510d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block testq(result_end, Immediate(kObjectAlignmentMask)); 2511d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Check(zero, "Unaligned allocation in new space"); 2512d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2513d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_top = 2515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference::new_space_allocation_top_address(); 2516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update new top. 2518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result_end.is(rax)) { 2519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rax can be stored directly to a memory location. 2520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block store_rax(new_space_allocation_top); 2521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 2522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Register required - use scratch provided if available. 25236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (scratch.is_valid()) { 25246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(Operand(scratch, 0), result_end); 25256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 2526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, new_space_allocation_top); 2527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(Operand(kScratchRegister, 0), result_end); 2528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(int object_size, 2534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 2535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result_end, 2536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 2537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required, 2538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags) { 2539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!result.is(result_end)); 2540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load address of new object into result. 2542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadAllocationTopHelper(result, result_end, scratch, flags); 2543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate new top and bail out if new space is exhausted. 2545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_limit = 2546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference::new_space_allocation_limit_address(); 25476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 25486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register top_reg = result_end.is_valid() ? result_end : result; 25496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 25506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (top_reg.is(result)) { 25516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block addq(top_reg, Immediate(object_size)); 25526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 25536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block lea(top_reg, Operand(result, object_size)); 25546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 2555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, new_space_allocation_limit); 25566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block cmpq(top_reg, Operand(kScratchRegister, 0)); 2557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(above, gc_required); 2558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update allocation top. 25606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block UpdateAllocationTopHelper(top_reg, scratch); 2561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (top_reg.is(result)) { 25636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if ((flags & TAG_OBJECT) != 0) { 25646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block subq(result, Immediate(object_size - kHeapObjectTag)); 25656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 25666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block subq(result, Immediate(object_size)); 25676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 25686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if ((flags & TAG_OBJECT) != 0) { 25696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Tag the result if requested. 2570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addq(result, Immediate(kHeapObjectTag)); 2571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(int header_size, 2576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ScaleFactor element_size, 2577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register element_count, 2578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 2579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result_end, 2580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 2581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required, 2582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags) { 2583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!result.is(result_end)); 2584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load address of new object into result. 2586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadAllocationTopHelper(result, result_end, scratch, flags); 2587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate new top and bail out if new space is exhausted. 2589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_limit = 2590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference::new_space_allocation_limit_address(); 2591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lea(result_end, Operand(result, element_count, element_size, header_size)); 2592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, new_space_allocation_limit); 2593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(result_end, Operand(kScratchRegister, 0)); 2594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(above, gc_required); 2595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update allocation top. 2597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UpdateAllocationTopHelper(result_end, scratch); 2598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Tag the result if requested. 2600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((flags & TAG_OBJECT) != 0) { 2601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addq(result, Immediate(kHeapObjectTag)); 2602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(Register object_size, 2607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 2608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result_end, 2609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 2610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required, 2611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags) { 2612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load address of new object into result. 2613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadAllocationTopHelper(result, result_end, scratch, flags); 2614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate new top and bail out if new space is exhausted. 2616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_limit = 2617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference::new_space_allocation_limit_address(); 2618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!object_size.is(result_end)) { 2619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(result_end, object_size); 2620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addq(result_end, result); 2622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, new_space_allocation_limit); 2623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(result_end, Operand(kScratchRegister, 0)); 2624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(above, gc_required); 2625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update allocation top. 2627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UpdateAllocationTopHelper(result_end, scratch); 2628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Tag the result if requested. 2630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((flags & TAG_OBJECT) != 0) { 2631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addq(result, Immediate(kHeapObjectTag)); 2632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::UndoAllocationInNewSpace(Register object) { 2637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_top = 2638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference::new_space_allocation_top_address(); 2639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure the object has no tag before resetting top. 2641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block and_(object, Immediate(~kHeapObjectTagMask)); 2642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, new_space_allocation_top); 2643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 2644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(object, Operand(kScratchRegister, 0)); 2645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(below, "Undo allocation of non allocated memory"); 2646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 2647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(Operand(kScratchRegister, 0), object); 2648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 26513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::AllocateHeapNumber(Register result, 26523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register scratch, 26533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label* gc_required) { 26543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Allocate heap number in new space. 26553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block AllocateInNewSpace(HeapNumber::kSize, 26563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block result, 26573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block scratch, 26583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block no_reg, 26593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block gc_required, 26603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block TAG_OBJECT); 26613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 26623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Set the map. 26633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block LoadRoot(kScratchRegister, Heap::kHeapNumberMapRootIndex); 26643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); 26653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 26663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 26673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2668e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::AllocateTwoByteString(Register result, 2669e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register length, 2670e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch1, 2671e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch2, 2672e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch3, 2673e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* gc_required) { 2674e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Calculate the number of bytes needed for the characters in the string while 2675e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // observing object alignment. 26766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int kHeaderAlignment = SeqTwoByteString::kHeaderSize & 26776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block kObjectAlignmentMask; 2678e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(kShortSize == 2); 2679e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // scratch1 = length * 2 + kObjectAlignmentMask. 26806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block lea(scratch1, Operand(length, length, times_1, kObjectAlignmentMask + 26816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block kHeaderAlignment)); 2682e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke and_(scratch1, Immediate(~kObjectAlignmentMask)); 26836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (kHeaderAlignment > 0) { 26846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block subq(scratch1, Immediate(kHeaderAlignment)); 26856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 2686e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2687e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Allocate two byte string in new space. 2688e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AllocateInNewSpace(SeqTwoByteString::kHeaderSize, 2689e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke times_1, 2690e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch1, 2691e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke result, 2692e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch2, 2693e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch3, 2694e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke gc_required, 2695e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke TAG_OBJECT); 2696e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2697e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Set the map, length and hash field. 2698e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke LoadRoot(kScratchRegister, Heap::kStringMapRootIndex); 2699e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); 27006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Integer32ToSmi(scratch1, length); 27016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(FieldOperand(result, String::kLengthOffset), scratch1); 27027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch movq(FieldOperand(result, String::kHashFieldOffset), 2703e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Immediate(String::kEmptyHashField)); 2704e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 2705e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2706e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2707e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::AllocateAsciiString(Register result, 2708e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register length, 2709e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch1, 2710e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch2, 2711e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch3, 2712e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* gc_required) { 2713e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Calculate the number of bytes needed for the characters in the string while 2714e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // observing object alignment. 27156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int kHeaderAlignment = SeqAsciiString::kHeaderSize & 27166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block kObjectAlignmentMask; 2717e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movl(scratch1, length); 2718e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(kCharSize == 1); 27196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block addq(scratch1, Immediate(kObjectAlignmentMask + kHeaderAlignment)); 2720e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke and_(scratch1, Immediate(~kObjectAlignmentMask)); 27216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (kHeaderAlignment > 0) { 27226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block subq(scratch1, Immediate(kHeaderAlignment)); 27236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 2724e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2725e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Allocate ascii string in new space. 2726e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AllocateInNewSpace(SeqAsciiString::kHeaderSize, 2727e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke times_1, 2728e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch1, 2729e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke result, 2730e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch2, 2731e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch3, 2732e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke gc_required, 2733e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke TAG_OBJECT); 2734e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2735e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Set the map, length and hash field. 2736e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke LoadRoot(kScratchRegister, Heap::kAsciiStringMapRootIndex); 2737e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); 27386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Integer32ToSmi(scratch1, length); 27396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(FieldOperand(result, String::kLengthOffset), scratch1); 27407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch movq(FieldOperand(result, String::kHashFieldOffset), 2741e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Immediate(String::kEmptyHashField)); 2742e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 2743e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2744e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2745e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::AllocateConsString(Register result, 2746e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch1, 2747e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch2, 2748e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* gc_required) { 2749e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Allocate heap number in new space. 2750e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AllocateInNewSpace(ConsString::kSize, 2751e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke result, 2752e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch1, 2753e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch2, 2754e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke gc_required, 2755e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke TAG_OBJECT); 2756e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2757e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Set the map. The other fields are left uninitialized. 2758e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke LoadRoot(kScratchRegister, Heap::kConsStringMapRootIndex); 2759e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); 2760e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 2761e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2762e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2763e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::AllocateAsciiConsString(Register result, 2764e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch1, 2765e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch2, 2766e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* gc_required) { 2767e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Allocate heap number in new space. 2768e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AllocateInNewSpace(ConsString::kSize, 2769e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke result, 2770e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch1, 2771e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch2, 2772e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke gc_required, 2773e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke TAG_OBJECT); 2774e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2775e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Set the map. The other fields are left uninitialized. 2776e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke LoadRoot(kScratchRegister, Heap::kConsAsciiStringMapRootIndex); 2777e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); 2778e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 2779e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2780e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2781d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::LoadContext(Register dst, int context_chain_length) { 2782d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (context_chain_length > 0) { 2783d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Move up the chain of contexts to the context containing the slot. 2784d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block movq(dst, Operand(rsi, Context::SlotOffset(Context::CLOSURE_INDEX))); 2785d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load the function context (which is the incoming, outer context). 2786e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movq(dst, FieldOperand(dst, JSFunction::kContextOffset)); 2787d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 1; i < context_chain_length; i++) { 2788d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block movq(dst, Operand(dst, Context::SlotOffset(Context::CLOSURE_INDEX))); 2789d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block movq(dst, FieldOperand(dst, JSFunction::kContextOffset)); 2790d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2791d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // The context may be an intermediate context, not a function context. 2792d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block movq(dst, Operand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX))); 2793d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { // context is the current function context. 2794d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // The context may be an intermediate context, not a function context. 2795d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block movq(dst, Operand(rsi, Context::SlotOffset(Context::FCONTEXT_INDEX))); 2796d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2797d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2798d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 27997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 28004515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkeint MacroAssembler::ArgumentStackSlotsForCFunctionCall(int num_arguments) { 28017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // On Windows 64 stack slots are reserved by the caller for all arguments 28027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // including the ones passed in registers, and space is always allocated for 28037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // the four register arguments even if the function takes fewer than four 28047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // arguments. 28057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // On AMD64 ABI (Linux/Mac) the first six arguments are passed in registers 28067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // and the caller does not reserve stack slots for them. 28074515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke ASSERT(num_arguments >= 0); 28084515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke#ifdef _WIN64 28097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch static const int kMinimumStackSlots = 4; 28107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (num_arguments < kMinimumStackSlots) return kMinimumStackSlots; 28117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch return num_arguments; 28124515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke#else 28137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch static const int kRegisterPassedArguments = 6; 28147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (num_arguments < kRegisterPassedArguments) return 0; 28157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch return num_arguments - kRegisterPassedArguments; 28164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke#endif 28174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke} 28184515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 28197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 28204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid MacroAssembler::PrepareCallCFunction(int num_arguments) { 28214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke int frame_alignment = OS::ActivationFrameAlignment(); 28224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke ASSERT(frame_alignment != 0); 28234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke ASSERT(num_arguments >= 0); 28244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Make stack end at alignment and allocate space for arguments and old rsp. 28254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke movq(kScratchRegister, rsp); 28264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke ASSERT(IsPowerOf2(frame_alignment)); 28274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke int argument_slots_on_stack = 28284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke ArgumentStackSlotsForCFunctionCall(num_arguments); 28294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke subq(rsp, Immediate((argument_slots_on_stack + 1) * kPointerSize)); 28304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke and_(rsp, Immediate(-frame_alignment)); 28314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke movq(Operand(rsp, argument_slots_on_stack * kPointerSize), kScratchRegister); 28324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke} 28334515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 28344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 28354515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid MacroAssembler::CallCFunction(ExternalReference function, 28364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke int num_arguments) { 28374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke movq(rax, function); 28384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke CallCFunction(rax, num_arguments); 28394515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke} 28404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 28414515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 28424515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid MacroAssembler::CallCFunction(Register function, int num_arguments) { 28436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check stack alignment. 28446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (FLAG_debug_code) { 28456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block CheckStackAlignment(); 28466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 28476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 28484515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke call(function); 28494515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke ASSERT(OS::ActivationFrameAlignment() != 0); 28504515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke ASSERT(num_arguments >= 0); 28514515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke int argument_slots_on_stack = 28524515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke ArgumentStackSlotsForCFunctionCall(num_arguments); 28534515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke movq(rsp, Operand(rsp, argument_slots_on_stack * kPointerSize)); 28544515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke} 28554515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 2856d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCodePatcher::CodePatcher(byte* address, int size) 2858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : address_(address), size_(size), masm_(address, size + Assembler::kGap) { 2859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Create a new macro assembler pointing to the address of the code to patch. 2860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The size is adjusted with kGap on order for the assembler to generate size 2861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // bytes of instructions without failing with buffer size constraints. 2862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); 2863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCodePatcher::~CodePatcher() { 2867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Indicate that code has changed. 2868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CPU::FlushICache(address_, size_); 2869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the code was patched as expected. 2871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(masm_.pc_ == address_ + size_); 2872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); 2873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 2876f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2877f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_X64 2878