macro-assembler-x64.cc revision 3ef787dbeca8a5fb1086949cda830dccee07bfbd
13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h" 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 30f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_X64) 31f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "bootstrapper.h" 338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "codegen.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 438b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochMacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size) 448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch : Assembler(arg_isolate, buffer, size), 453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block generating_stub_(false), 463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block allow_stub_calls_(true), 473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch has_frame_(false), 488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch root_array_available_(true) { 498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (isolate() != NULL) { 508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch code_object_ = Handle<Object>(isolate()->heap()->undefined_value(), 518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch isolate()); 528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 5344f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 5444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 5544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 5644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic intptr_t RootRegisterDelta(ExternalReference other, Isolate* isolate) { 5744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Address roots_register_value = kRootRegisterBias + 583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch reinterpret_cast<Address>(isolate->heap()->roots_array_start()); 5944f0eee88ff00398ff7f715fab053374d808c90dSteve Block intptr_t delta = other.address() - roots_register_value; 6044f0eee88ff00398ff7f715fab053374d808c90dSteve Block return delta; 6144f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 6244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 6344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 6444f0eee88ff00398ff7f715fab053374d808c90dSteve BlockOperand MacroAssembler::ExternalOperand(ExternalReference target, 6544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch) { 6644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (root_array_available_ && !Serializer::enabled()) { 6744f0eee88ff00398ff7f715fab053374d808c90dSteve Block intptr_t delta = RootRegisterDelta(target, isolate()); 6844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (is_int32(delta)) { 6944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Serializer::TooLateToEnableNow(); 7044f0eee88ff00398ff7f715fab053374d808c90dSteve Block return Operand(kRootRegister, static_cast<int32_t>(delta)); 7144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 7244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 7344f0eee88ff00398ff7f715fab053374d808c90dSteve Block movq(scratch, target); 7444f0eee88ff00398ff7f715fab053374d808c90dSteve Block return Operand(scratch, 0); 7544f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 7644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 7744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 7844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::Load(Register destination, ExternalReference source) { 7944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (root_array_available_ && !Serializer::enabled()) { 8044f0eee88ff00398ff7f715fab053374d808c90dSteve Block intptr_t delta = RootRegisterDelta(source, isolate()); 8144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (is_int32(delta)) { 8244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Serializer::TooLateToEnableNow(); 8344f0eee88ff00398ff7f715fab053374d808c90dSteve Block movq(destination, Operand(kRootRegister, static_cast<int32_t>(delta))); 8444f0eee88ff00398ff7f715fab053374d808c90dSteve Block return; 8544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 8644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 8744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Safe code. 8844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (destination.is(rax)) { 8944f0eee88ff00398ff7f715fab053374d808c90dSteve Block load_rax(source); 9044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 9144f0eee88ff00398ff7f715fab053374d808c90dSteve Block movq(kScratchRegister, source); 9244f0eee88ff00398ff7f715fab053374d808c90dSteve Block movq(destination, Operand(kScratchRegister, 0)); 9344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 9444f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 9544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 9644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 9744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::Store(ExternalReference destination, Register source) { 9844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (root_array_available_ && !Serializer::enabled()) { 9944f0eee88ff00398ff7f715fab053374d808c90dSteve Block intptr_t delta = RootRegisterDelta(destination, isolate()); 10044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (is_int32(delta)) { 10144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Serializer::TooLateToEnableNow(); 10244f0eee88ff00398ff7f715fab053374d808c90dSteve Block movq(Operand(kRootRegister, static_cast<int32_t>(delta)), source); 10344f0eee88ff00398ff7f715fab053374d808c90dSteve Block return; 10444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 10544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 10644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Safe code. 10744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (source.is(rax)) { 10844f0eee88ff00398ff7f715fab053374d808c90dSteve Block store_rax(destination); 10944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 11044f0eee88ff00398ff7f715fab053374d808c90dSteve Block movq(kScratchRegister, destination); 11144f0eee88ff00398ff7f715fab053374d808c90dSteve Block movq(Operand(kScratchRegister, 0), source); 11244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 11344f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 11444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 11544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 11644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::LoadAddress(Register destination, 11744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference source) { 11844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (root_array_available_ && !Serializer::enabled()) { 11944f0eee88ff00398ff7f715fab053374d808c90dSteve Block intptr_t delta = RootRegisterDelta(source, isolate()); 12044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (is_int32(delta)) { 12144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Serializer::TooLateToEnableNow(); 12244f0eee88ff00398ff7f715fab053374d808c90dSteve Block lea(destination, Operand(kRootRegister, static_cast<int32_t>(delta))); 12344f0eee88ff00398ff7f715fab053374d808c90dSteve Block return; 12444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 12544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 12644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Safe code. 12744f0eee88ff00398ff7f715fab053374d808c90dSteve Block movq(destination, source); 12844f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 12944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 13044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 13144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint MacroAssembler::LoadAddressSize(ExternalReference source) { 13244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (root_array_available_ && !Serializer::enabled()) { 13344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // This calculation depends on the internals of LoadAddress. 13444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // It's correctness is ensured by the asserts in the Call 13544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // instruction below. 13644f0eee88ff00398ff7f715fab053374d808c90dSteve Block intptr_t delta = RootRegisterDelta(source, isolate()); 13744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (is_int32(delta)) { 13844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Serializer::TooLateToEnableNow(); 13944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Operand is lea(scratch, Operand(kRootRegister, delta)); 14044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Opcodes : REX.W 8D ModRM Disp8/Disp32 - 4 or 7. 14144f0eee88ff00398ff7f715fab053374d808c90dSteve Block int size = 4; 14244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!is_int8(static_cast<int32_t>(delta))) { 14344f0eee88ff00398ff7f715fab053374d808c90dSteve Block size += 3; // Need full four-byte displacement in lea. 14444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 14544f0eee88ff00398ff7f715fab053374d808c90dSteve Block return size; 14644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 14744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 14844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Size of movq(destination, src); 14944f0eee88ff00398ff7f715fab053374d808c90dSteve Block return 10; 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index) { 15444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(root_array_available_); 155e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch movq(destination, Operand(kRootRegister, 156e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch (index << kPointerSizeLog2) - kRootRegisterBias)); 157e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 158e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 159e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 160e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::LoadRootIndexed(Register destination, 161e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register variable_offset, 162e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int fixed_offset) { 16344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(root_array_available_); 164e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch movq(destination, 165e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Operand(kRootRegister, 166e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch variable_offset, times_pointer_size, 167e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch (fixed_offset << kPointerSizeLog2) - kRootRegisterBias)); 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 17125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsenvoid MacroAssembler::StoreRoot(Register source, Heap::RootListIndex index) { 17244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(root_array_available_); 173e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch movq(Operand(kRootRegister, (index << kPointerSizeLog2) - kRootRegisterBias), 174e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch source); 17525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen} 17625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen 17725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::PushRoot(Heap::RootListIndex index) { 17944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(root_array_available_); 180e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch push(Operand(kRootRegister, (index << kPointerSizeLog2) - kRootRegisterBias)); 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) { 18544f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(root_array_available_); 186e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch cmpq(with, Operand(kRootRegister, 187e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch (index << kPointerSizeLog2) - kRootRegisterBias)); 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::CompareRoot(const Operand& with, 1921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Heap::RootListIndex index) { 19344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(root_array_available_); 1941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(!with.AddressUsesRegister(kScratchRegister)); 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadRoot(kScratchRegister, index); 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(with, kScratchRegister); 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::RememberedSetHelper(Register object, // For debug tests. 2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register addr, 2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 2033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SaveFPRegsMode save_fp, 2043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RememberedSetFinalAction and_then) { 2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_debug_code) { 2063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label ok; 2073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JumpIfNotInNewSpace(object, scratch, &ok, Label::kNear); 2083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int3(); 2093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&ok); 2103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load store buffer top. 2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LoadRoot(scratch, Heap::kStoreBufferTopRootIndex); 2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store pointer to buffer. 2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(Operand(scratch, 0), addr); 2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Increment buffer top. 2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch addq(scratch, Immediate(kPointerSize)); 2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Write back new top of buffer. 2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StoreRoot(scratch, Heap::kStoreBufferTopRootIndex); 2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Call stub on end of buffer. 2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label done; 2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for end of buffer. 2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch testq(scratch, Immediate(StoreBuffer::kStoreBufferOverflowBit)); 2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (and_then == kReturnAtEnd) { 2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label buffer_overflowed; 2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(not_equal, &buffer_overflowed, Label::kNear); 2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ret(0); 2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&buffer_overflowed); 2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 2293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(and_then == kFallThroughAtEnd); 2303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(equal, &done, Label::kNear); 2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StoreBufferOverflowStub store_buffer_overflow = 2333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StoreBufferOverflowStub(save_fp); 2343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallStub(&store_buffer_overflow); 2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (and_then == kReturnAtEnd) { 2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ret(0); 2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(and_then == kFallThroughAtEnd); 2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&done); 2406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 2417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 2427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 2437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::InNewSpace(Register object, 245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch, 246257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Condition cc, 247257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* branch, 2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance distance) { 249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (Serializer::enabled()) { 250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Can't do arithmetic on external references if it might get serialized. 251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The mask isn't really an address. We load it as an external reference in 252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // case the size of the new space is different between the snapshot maker 253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // and the running system. 254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (scratch.is(object)) { 255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(kScratchRegister, ExternalReference::new_space_mask(isolate())); 256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch and_(scratch, kScratchRegister); 257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(scratch, ExternalReference::new_space_mask(isolate())); 259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch and_(scratch, object); 260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(kScratchRegister, ExternalReference::new_space_start(isolate())); 262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cmpq(scratch, kScratchRegister); 2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(cc, branch, distance); 264257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 265257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(is_int32(static_cast<int64_t>(HEAP->NewSpaceMask()))); 266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch intptr_t new_space_start = 267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch reinterpret_cast<intptr_t>(HEAP->NewSpaceStart()); 268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(kScratchRegister, -new_space_start, RelocInfo::NONE); 269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (scratch.is(object)) { 270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch addq(scratch, kScratchRegister); 271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch lea(scratch, Operand(object, kScratchRegister, times_1, 0)); 273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch and_(scratch, Immediate(static_cast<int32_t>(HEAP->NewSpaceMask()))); 2753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(cc, branch, distance); 276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::RecordWriteField( 2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object, 2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int offset, 2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register value, 2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register dst, 2853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SaveFPRegsMode save_fp, 2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RememberedSetAction remembered_set_action, 2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiCheck smi_check) { 2884515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // The compiled code assumes that record write doesn't change the 2894515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // context register, so we check that none of the clobbered 2904515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // registers are rsi. 2913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!value.is(rsi) && !dst.is(rsi)); 2924515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 2937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // First, check if a write barrier is even needed. The tests below 2943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // catch stores of Smis. 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label done; 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Skip barrier if writing a smi. 2983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (smi_check == INLINE_SMI_CHECK) { 2993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JumpIfSmi(value, &done); 3003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Although the object register is tagged, the offset is relative to the start 3033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // of the object, so so offset must be a multiple of kPointerSize. 3043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(IsAligned(offset, kPointerSize)); 3053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lea(dst, FieldOperand(object, offset)); 3073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (emit_debug_code()) { 3083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label ok; 3093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch testb(dst, Immediate((1 << kPointerSizeLog2) - 1)); 3103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(zero, &ok, Label::kNear); 3113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int3(); 3123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&ok); 3133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RecordWrite( 3163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch object, dst, value, save_fp, remembered_set_action, OMIT_SMI_CHECK); 3173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bind(&done); 3194515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 3203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Clobber clobbered input registers when running with the debug-code flag 3213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // turned on to provoke errors. 32244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 3236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE); 3243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(dst, BitCast<int64_t>(kZapValue), RelocInfo::NONE); 3254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 3263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 3273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::RecordWriteArray(Register object, 3303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register value, 3313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register index, 3323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SaveFPRegsMode save_fp, 3333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RememberedSetAction remembered_set_action, 3343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiCheck smi_check) { 3358defd9ff6930b4e24729971a61cf7469daf119beSteve Block // First, check if a write barrier is even needed. The tests below 3363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // catch stores of Smis. 3378defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label done; 3388defd9ff6930b4e24729971a61cf7469daf119beSteve Block 3393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Skip barrier if writing a smi. 3403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (smi_check == INLINE_SMI_CHECK) { 3413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JumpIfSmi(value, &done); 3423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3438defd9ff6930b4e24729971a61cf7469daf119beSteve Block 3443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Array access: calculate the destination address. Index is not a smi. 3453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register dst = index; 3463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lea(dst, Operand(object, index, times_pointer_size, 3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArray::kHeaderSize - kHeapObjectTag)); 3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RecordWrite( 3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch object, dst, value, save_fp, remembered_set_action, OMIT_SMI_CHECK); 3518defd9ff6930b4e24729971a61cf7469daf119beSteve Block 3528defd9ff6930b4e24729971a61cf7469daf119beSteve Block bind(&done); 3538defd9ff6930b4e24729971a61cf7469daf119beSteve Block 3543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Clobber clobbered input registers when running with the debug-code flag 3558defd9ff6930b4e24729971a61cf7469daf119beSteve Block // turned on to provoke errors. 35644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 3578defd9ff6930b4e24729971a61cf7469daf119beSteve Block movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE); 3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(index, BitCast<int64_t>(kZapValue), RelocInfo::NONE); 3598defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 3608defd9ff6930b4e24729971a61cf7469daf119beSteve Block} 3618defd9ff6930b4e24729971a61cf7469daf119beSteve Block 3628defd9ff6930b4e24729971a61cf7469daf119beSteve Block 3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::RecordWrite(Register object, 3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register address, 3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register value, 3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SaveFPRegsMode fp_mode, 3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RememberedSetAction remembered_set_action, 3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiCheck smi_check) { 3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The compiled code assumes that record write doesn't change the 3703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // context register, so we check that none of the clobbered 3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // registers are rsi. 3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!value.is(rsi) && !address.is(rsi)); 3734515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 3743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!object.is(value)); 3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!object.is(address)); 3763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!value.is(address)); 37744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AbortIfSmi(object); 3794515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 3804515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 3813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (remembered_set_action == OMIT_REMEMBERED_SET && 3823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch !FLAG_incremental_marking) { 3833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return; 3843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_debug_code) { 3873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label ok; 3883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmpq(value, Operand(address, 0)); 3893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(equal, &ok, Label::kNear); 3903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int3(); 3913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&ok); 3923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // First, check if a write barrier is even needed. The tests below 3953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // catch stores of smis and stores into the young generation. 3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label done; 3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (smi_check == INLINE_SMI_CHECK) { 3993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Skip barrier if writing a smi. 4003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JumpIfSmi(value, &done); 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPageFlag(value, 4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value, // Used as scratch. 4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MemoryChunk::kPointersToHereAreInterestingMask, 4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch zero, 4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &done, 4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::kNear); 4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPageFlag(object, 4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value, // Used as scratch. 4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MemoryChunk::kPointersFromHereAreInterestingMask, 4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch zero, 4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &done, 4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::kNear); 4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RecordWriteStub stub(object, value, address, remembered_set_action, fp_mode); 4183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallStub(&stub); 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&done); 4214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Clobber clobbered registers when running with the debug-code flag 4234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // turned on to provoke errors. 42444f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 4253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(address, BitCast<int64_t>(kZapValue), RelocInfo::NONE); 4263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE); 4276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 4286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 4296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 4303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Assert(Condition cc, const char* msg) { 43244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) Check(cc, msg); 433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 436756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid MacroAssembler::AssertFastElements(Register elements) { 43744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label ok; 439756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CompareRoot(FieldOperand(elements, HeapObject::kMapOffset), 440756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Heap::kFixedArrayMapRootIndex); 441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(equal, &ok, Label::kNear); 442756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CompareRoot(FieldOperand(elements, HeapObject::kMapOffset), 4433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Heap::kFixedDoubleArrayMapRootIndex); 4443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch j(equal, &ok, Label::kNear); 4453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CompareRoot(FieldOperand(elements, HeapObject::kMapOffset), 446756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Heap::kFixedCOWArrayMapRootIndex); 447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(equal, &ok, Label::kNear); 448756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Abort("JSObject with fast elements map has slow elements"); 449756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick bind(&ok); 450756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 451756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick} 452756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 453756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Check(Condition cc, const char* msg) { 455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label L; 456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(cc, &L, Label::kNear); 457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Abort(msg); 4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Control will not return here. 459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&L); 460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4636ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::CheckStackAlignment() { 4646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int frame_alignment = OS::ActivationFrameAlignment(); 4656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int frame_alignment_mask = frame_alignment - 1; 4666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (frame_alignment > kPointerSize) { 4676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(IsPowerOf2(frame_alignment)); 468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label alignment_as_expected; 4696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block testq(rsp, Immediate(frame_alignment_mask)); 470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(zero, &alignment_as_expected, Label::kNear); 4716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Abort if stack is not aligned. 4726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int3(); 4736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block bind(&alignment_as_expected); 4746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 4756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 4766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 4776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::NegativeZeroTest(Register result, 479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register op, 480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* then_label) { 481257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label ok; 482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block testl(result, result); 483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(not_zero, &ok, Label::kNear); 484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block testl(op, op); 485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(sign, then_label); 486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&ok); 487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Abort(const char* msg) { 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We want to pass the msg string like a smi to avoid GC 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // problems, however msg is not guaranteed to be aligned 493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // properly. Instead, we pass an aligned pointer that is 494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // a proper v8 smi, but also pass the alignment difference 495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // from the real pointer as a smi. 496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block intptr_t p1 = reinterpret_cast<intptr_t>(msg); 497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block intptr_t p0 = (p1 & ~kSmiTagMask) + kSmiTag; 4983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Note: p0 might not be a valid Smi _value_, but it has a valid Smi tag. 499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(reinterpret_cast<Object*>(p0)->IsSmi()); 500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (msg != NULL) { 502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RecordComment("Abort message: "); 503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RecordComment(msg); 504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(rax); 507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, p0, RelocInfo::NONE); 508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(kScratchRegister); 509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, 510d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(p1 - p0))), 511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::NONE); 512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(kScratchRegister); 5133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!has_frame_) { 5153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We don't actually want to generate a pile of code for this, so just 5163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // claim there is a stack frame, without generating one. 5173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(this, StackFrame::NONE); 5183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallRuntime(Runtime::kAbort, 2); 5193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 5203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallRuntime(Runtime::kAbort, 2); 5213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 5223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Control will not return here. 523d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int3(); 524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 527257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::CallStub(CodeStub* stub, unsigned ast_id) { 5283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(AllowThisStubCall(stub)); // Calls are not allowed in some stubs 529257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id); 530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 533e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::TailCallStub(CodeStub* stub) { 5343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe()); 535e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Jump(stub->GetCode(), RelocInfo::CODE_TARGET); 536e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 537e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 538e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 53985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochvoid MacroAssembler::StubReturn(int argc) { 54085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch ASSERT(argc >= 1 && generating_stub()); 54185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch ret((argc - 1) * kPointerSize); 542592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch} 543592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 544592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 5453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool MacroAssembler::AllowThisStubCall(CodeStub* stub) { 5463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!has_frame_ && stub->SometimesSetsUpAFrame()) return false; 5473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe(); 5483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 5493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::IllegalOperation(int num_arguments) { 552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (num_arguments > 0) { 553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addq(rsp, Immediate(num_arguments * kPointerSize)); 554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadRoot(rax, Heap::kUndefinedValueRootIndex); 556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 55980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::IndexFromHash(Register hash, Register index) { 56080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // The assert checks that the constants for the maximum number of digits 56180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // for an array index cached in the hash field and the number of bits 56280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // reserved for it does not conflict. 56380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < 56480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen (1 << String::kArrayIndexValueBits)); 56580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // We want the smi-tagged index in key. Even if we subsequently go to 56680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // the slow case, converting the key to a smi is always valid. 56780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // key: string key 56880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // hash: key's hash field, including its array index value. 56980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen and_(hash, Immediate(String::kArrayIndexValueMask)); 57080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen shr(hash, Immediate(String::kHashShift)); 57180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Here we actually clobber the key which will be used if calling into 57280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // runtime later. However as the new key is the numeric value of a string key 57380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // there is no difference in using either key. 57480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Integer32ToSmi(index, hash); 57580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 57680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 57780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CallRuntime(Runtime::FunctionId id, int num_arguments) { 579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CallRuntime(Runtime::FunctionForId(id), num_arguments); 580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::CallRuntimeSaveDoubles(Runtime::FunctionId id) { 58444f0eee88ff00398ff7f715fab053374d808c90dSteve Block const Runtime::Function* function = Runtime::FunctionForId(id); 5851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Set(rax, function->nargs); 58644f0eee88ff00398ff7f715fab053374d808c90dSteve Block LoadAddress(rbx, ExternalReference(function, isolate())); 5873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CEntryStub ces(1, kSaveFPRegs); 5881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallStub(&ces); 5891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 5901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 5911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 59244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CallRuntime(const Runtime::Function* f, 59344f0eee88ff00398ff7f715fab053374d808c90dSteve Block int num_arguments) { 594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the expected number of arguments of the runtime function is 595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // constant, we check that the actual number of arguments match the 596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // expectation. 597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (f->nargs >= 0 && f->nargs != num_arguments) { 598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block IllegalOperation(num_arguments); 599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6024515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // TODO(1236192): Most runtime routines don't need the number of 6034515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // arguments passed in because it is constant. At some point we 6044515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // should remove this need and make the runtime routine entry code 6054515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // smarter. 6068defd9ff6930b4e24729971a61cf7469daf119beSteve Block Set(rax, num_arguments); 60744f0eee88ff00398ff7f715fab053374d808c90dSteve Block LoadAddress(rbx, ExternalReference(f, isolate())); 6084515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke CEntryStub ces(f->result_size); 6094515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke CallStub(&ces); 610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 613402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::CallExternalReference(const ExternalReference& ext, 614402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu int num_arguments) { 6158defd9ff6930b4e24729971a61cf7469daf119beSteve Block Set(rax, num_arguments); 61644f0eee88ff00398ff7f715fab053374d808c90dSteve Block LoadAddress(rbx, ext); 617402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 618402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu CEntryStub stub(1); 619402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu CallStub(&stub); 620402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 621402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 622402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 6236ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::TailCallExternalReference(const ExternalReference& ext, 6246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int num_arguments, 6256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int result_size) { 626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rsp[0] : return address 628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rsp[8] : argument num_arguments - 1 629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ... 630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rsp[8 * num_arguments] : argument 0 (receiver) 631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // TODO(1236192): Most runtime routines don't need the number of 634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // arguments passed in because it is constant. At some point we 635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // should remove this need and make the runtime routine entry code 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // smarter. 6378defd9ff6930b4e24729971a61cf7469daf119beSteve Block Set(rax, num_arguments); 6386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JumpToExternalReference(ext, result_size); 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6426ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::TailCallRuntime(Runtime::FunctionId fid, 6436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int num_arguments, 6446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int result_size) { 64544f0eee88ff00398ff7f715fab053374d808c90dSteve Block TailCallExternalReference(ExternalReference(fid, isolate()), 64644f0eee88ff00398ff7f715fab053374d808c90dSteve Block num_arguments, 64744f0eee88ff00398ff7f715fab053374d808c90dSteve Block result_size); 6486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 6496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 6506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 651bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochstatic int Offset(ExternalReference ref0, ExternalReference ref1) { 652bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch int64_t offset = (ref0.address() - ref1.address()); 653bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Check that fits into int. 654bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch ASSERT(static_cast<int>(offset) == offset); 655bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch return static_cast<int>(offset); 656bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 657bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 658bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 6598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid MacroAssembler::PrepareCallApiFunction(int arg_stack_space) { 6608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang#ifdef _WIN64 6618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // We need to prepare a slot for result handle on stack and put 6628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // a pointer to it into 1st arg register. 6638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang EnterApiExitFrame(arg_stack_space + 1); 6648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 6658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // rcx must be used to pass the pointer to the return value slot. 6668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang lea(rcx, StackSpaceOperand(arg_stack_space)); 6678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang#else 6688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang EnterApiExitFrame(arg_stack_space); 6698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang#endif 670bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 671bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 672bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 6733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CallApiFunctionAndReturn(Address function_address, 6743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int stack_space) { 6755913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Label empty_result; 6765913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Label prologue; 6775913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Label promote_scheduled_exception; 6785913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Label delete_allocated_handles; 6795913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Label leave_exit_frame; 680bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Label write_back; 681bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 682257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Factory* factory = isolate()->factory(); 6835913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck ExternalReference next_address = 6845913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck ExternalReference::handle_scope_next_address(); 6855913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck const int kNextOffset = 0; 6865913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck const int kLimitOffset = Offset( 6875913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck ExternalReference::handle_scope_limit_address(), 6885913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck next_address); 6895913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck const int kLevelOffset = Offset( 6905913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck ExternalReference::handle_scope_level_address(), 6915913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck next_address); 6925913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck ExternalReference scheduled_exception_address = 69344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::scheduled_exception_address(isolate()); 6945913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck 6955913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // Allocate HandleScope in callee-save registers. 6965913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Register prev_next_address_reg = r14; 6975913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Register prev_limit_reg = rbx; 69844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register base_reg = r15; 6995913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck movq(base_reg, next_address); 7005913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck movq(prev_next_address_reg, Operand(base_reg, kNextOffset)); 7015913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck movq(prev_limit_reg, Operand(base_reg, kLimitOffset)); 7025913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck addl(Operand(base_reg, kLevelOffset), Immediate(1)); 7035913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // Call the api function! 7043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(rax, reinterpret_cast<int64_t>(function_address), 7055913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck RelocInfo::RUNTIME_ENTRY); 7065913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck call(rax); 707bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 7085913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck#ifdef _WIN64 7095913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // rax keeps a pointer to v8::Handle, unpack it. 7105913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck movq(rax, Operand(rax, 0)); 7115913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck#endif 7125913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // Check if the result handle holds 0. 7135913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck testq(rax, rax); 7145913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck j(zero, &empty_result); 7155913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // It was non-zero. Dereference to get the result value. 7165913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck movq(rax, Operand(rax, 0)); 7175913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck bind(&prologue); 7185913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck 7195913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // No more valid handles (the result handle was the last one). Restore 7205913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // previous handle scope. 7215913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck subl(Operand(base_reg, kLevelOffset), Immediate(1)); 7225913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck movq(Operand(base_reg, kNextOffset), prev_next_address_reg); 7235913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck cmpq(prev_limit_reg, Operand(base_reg, kLimitOffset)); 7245913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck j(not_equal, &delete_allocated_handles); 7255913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck bind(&leave_exit_frame); 7265913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck 7275913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // Check if the function scheduled an exception. 7285913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck movq(rsi, scheduled_exception_address); 729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Cmp(Operand(rsi, 0), factory->the_hole_value()); 7305913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck j(not_equal, &promote_scheduled_exception); 7315913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck 7328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang LeaveApiExitFrame(); 7338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang ret(stack_space * kPointerSize); 734bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 7355913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck bind(&promote_scheduled_exception); 7363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TailCallRuntime(Runtime::kPromoteScheduledException, 0, 1); 737bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 7385913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck bind(&empty_result); 7395913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // It was zero; the result is undefined. 740257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Move(rax, factory->undefined_value()); 7415913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck jmp(&prologue); 742bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 7435913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // HandleScope limit has changed. Delete allocated extensions. 7445913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck bind(&delete_allocated_handles); 7455913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck movq(Operand(base_reg, kLimitOffset), prev_limit_reg); 7465913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck movq(prev_limit_reg, rax); 74744f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef _WIN64 74844f0eee88ff00398ff7f715fab053374d808c90dSteve Block LoadAddress(rcx, ExternalReference::isolate_address()); 74944f0eee88ff00398ff7f715fab053374d808c90dSteve Block#else 75044f0eee88ff00398ff7f715fab053374d808c90dSteve Block LoadAddress(rdi, ExternalReference::isolate_address()); 75144f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif 75244f0eee88ff00398ff7f715fab053374d808c90dSteve Block LoadAddress(rax, 75344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::delete_handle_scope_extensions(isolate())); 7545913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck call(rax); 7555913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck movq(rax, prev_limit_reg); 7565913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck jmp(&leave_exit_frame); 757bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 758bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 759bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 7606ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::JumpToExternalReference(const ExternalReference& ext, 7616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int result_size) { 762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the entry point and jump to the C entry runtime stub. 76344f0eee88ff00398ff7f715fab053374d808c90dSteve Block LoadAddress(rbx, ext); 764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CEntryStub ces(result_size); 7653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block jmp(ces.GetCode(), RelocInfo::CODE_TARGET); 766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 769e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, 770e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch InvokeFlag flag, 771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const CallWrapper& call_wrapper) { 7723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // You can't call a builtin without a valid frame. 7733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(flag == JUMP_FUNCTION || has_frame()); 774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 775402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Rely on the assertion to check that the number of provided 776402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // arguments match the expected number of arguments. Fake a 777402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // parameter count to avoid emitting code to do the check. 778402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ParameterCount expected(0); 779402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GetBuiltinEntry(rdx, id); 780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch InvokeCode(rdx, expected, expected, flag, call_wrapper, CALL_AS_METHOD); 781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 783402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 784791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockvoid MacroAssembler::GetBuiltinFunction(Register target, 785791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block Builtins::JavaScript id) { 7866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Load the builtins object into target register. 7876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(target, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); 7886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(target, FieldOperand(target, GlobalObject::kBuiltinsOffset)); 789791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block movq(target, FieldOperand(target, 790791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block JSBuiltinsObject::OffsetOfFunctionWithId(id))); 791791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block} 7926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 7936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 794791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockvoid MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) { 795791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block ASSERT(!target.is(rdi)); 796791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block // Load the JavaScript builtin function from the builtins object. 797791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block GetBuiltinFunction(rdi, id); 798791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block movq(target, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); 799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#define REG(Name) { kRegister_ ## Name ## _Code } 8033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const Register saved_regs[] = { 8053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch REG(rax), REG(rcx), REG(rdx), REG(rbx), REG(rbp), REG(rsi), REG(rdi), REG(r8), 8063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch REG(r9), REG(r10), REG(r11) 8073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}; 8083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#undef REG 8103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const int kNumberOfSavedRegs = sizeof(saved_regs) / sizeof(Register); 8123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::PushCallerSaved(SaveFPRegsMode fp_mode, 8153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register exclusion1, 8163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register exclusion2, 8173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register exclusion3) { 8183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We don't allow a GC during a store buffer overflow so there is no need to 8193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // store the registers in any particular way, but we do have to store and 8203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // restore them. 8213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < kNumberOfSavedRegs; i++) { 8223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register reg = saved_regs[i]; 8233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!reg.is(exclusion1) && !reg.is(exclusion2) && !reg.is(exclusion3)) { 8243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch push(reg); 8253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 8263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 8273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // R12 to r15 are callee save on all platforms. 8283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (fp_mode == kSaveFPRegs) { 8293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CpuFeatures::Scope scope(SSE2); 8303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch subq(rsp, Immediate(kDoubleSize * XMMRegister::kNumRegisters)); 8313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < XMMRegister::kNumRegisters; i++) { 8323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch XMMRegister reg = XMMRegister::from_code(i); 8333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movsd(Operand(rsp, i * kDoubleSize), reg); 8343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 8353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 8363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 8373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, 8403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register exclusion1, 8413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register exclusion2, 8423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register exclusion3) { 8433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (fp_mode == kSaveFPRegs) { 8443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CpuFeatures::Scope scope(SSE2); 8453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < XMMRegister::kNumRegisters; i++) { 8463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch XMMRegister reg = XMMRegister::from_code(i); 8473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movsd(reg, Operand(rsp, i * kDoubleSize)); 8483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 8493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch addq(rsp, Immediate(kDoubleSize * XMMRegister::kNumRegisters)); 8503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 8513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = kNumberOfSavedRegs - 1; i >= 0; i--) { 8523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register reg = saved_regs[i]; 8533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!reg.is(exclusion1) && !reg.is(exclusion2) && !reg.is(exclusion3)) { 8543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch pop(reg); 8553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 8563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 8573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 8583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Set(Register dst, int64_t x) { 861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (x == 0) { 8628defd9ff6930b4e24729971a61cf7469daf119beSteve Block xorl(dst, dst); 863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (is_uint32(x)) { 864d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block movl(dst, Immediate(static_cast<uint32_t>(x))); 8658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else if (is_int32(x)) { 8668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch movq(dst, Immediate(static_cast<int32_t>(x))); 867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(dst, x, RelocInfo::NONE); 869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Set(const Operand& dst, int64_t x) { 8739dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (is_int32(x)) { 874d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block movq(dst, Immediate(static_cast<int32_t>(x))); 875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 8768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Set(kScratchRegister, x); 877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(dst, kScratchRegister); 878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ---------------------------------------------------------------------------- 882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Smi tagging, untagging and tag detection. 883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8848defd9ff6930b4e24729971a61cf7469daf119beSteve BlockRegister MacroAssembler::GetSmiConstant(Smi* source) { 8858defd9ff6930b4e24729971a61cf7469daf119beSteve Block int value = source->value(); 8868defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (value == 0) { 8878defd9ff6930b4e24729971a61cf7469daf119beSteve Block xorl(kScratchRegister, kScratchRegister); 8888defd9ff6930b4e24729971a61cf7469daf119beSteve Block return kScratchRegister; 8898defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 8908defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (value == 1) { 8918defd9ff6930b4e24729971a61cf7469daf119beSteve Block return kSmiConstantRegister; 8928defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 8938defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(kScratchRegister, source); 8948defd9ff6930b4e24729971a61cf7469daf119beSteve Block return kScratchRegister; 8958defd9ff6930b4e24729971a61cf7469daf119beSteve Block} 8968defd9ff6930b4e24729971a61cf7469daf119beSteve Block 8978defd9ff6930b4e24729971a61cf7469daf119beSteve Blockvoid MacroAssembler::LoadSmiConstant(Register dst, Smi* source) { 89844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 8998defd9ff6930b4e24729971a61cf7469daf119beSteve Block movq(dst, 9008defd9ff6930b4e24729971a61cf7469daf119beSteve Block reinterpret_cast<uint64_t>(Smi::FromInt(kSmiConstantRegisterValue)), 9018defd9ff6930b4e24729971a61cf7469daf119beSteve Block RelocInfo::NONE); 9028defd9ff6930b4e24729971a61cf7469daf119beSteve Block cmpq(dst, kSmiConstantRegister); 9038defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (allow_stub_calls()) { 9048defd9ff6930b4e24729971a61cf7469daf119beSteve Block Assert(equal, "Uninitialized kSmiConstantRegister"); 9058defd9ff6930b4e24729971a61cf7469daf119beSteve Block } else { 906257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label ok; 907257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(equal, &ok, Label::kNear); 9088defd9ff6930b4e24729971a61cf7469daf119beSteve Block int3(); 9098defd9ff6930b4e24729971a61cf7469daf119beSteve Block bind(&ok); 9108defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 9118defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 91244f0eee88ff00398ff7f715fab053374d808c90dSteve Block int value = source->value(); 91344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (value == 0) { 9148defd9ff6930b4e24729971a61cf7469daf119beSteve Block xorl(dst, dst); 9158defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 9168defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 9178defd9ff6930b4e24729971a61cf7469daf119beSteve Block bool negative = value < 0; 9188defd9ff6930b4e24729971a61cf7469daf119beSteve Block unsigned int uvalue = negative ? -value : value; 9198defd9ff6930b4e24729971a61cf7469daf119beSteve Block 9208defd9ff6930b4e24729971a61cf7469daf119beSteve Block switch (uvalue) { 9218defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 9: 9228defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_8, 0)); 9238defd9ff6930b4e24729971a61cf7469daf119beSteve Block break; 9248defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 8: 9258defd9ff6930b4e24729971a61cf7469daf119beSteve Block xorl(dst, dst); 9268defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(dst, kSmiConstantRegister, times_8, 0)); 9278defd9ff6930b4e24729971a61cf7469daf119beSteve Block break; 9288defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 4: 9298defd9ff6930b4e24729971a61cf7469daf119beSteve Block xorl(dst, dst); 9308defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(dst, kSmiConstantRegister, times_4, 0)); 9318defd9ff6930b4e24729971a61cf7469daf119beSteve Block break; 9328defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 5: 9338defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_4, 0)); 9348defd9ff6930b4e24729971a61cf7469daf119beSteve Block break; 9358defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 3: 9368defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_2, 0)); 9378defd9ff6930b4e24729971a61cf7469daf119beSteve Block break; 9388defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 2: 9398defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_1, 0)); 9408defd9ff6930b4e24729971a61cf7469daf119beSteve Block break; 9418defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 1: 9428defd9ff6930b4e24729971a61cf7469daf119beSteve Block movq(dst, kSmiConstantRegister); 9438defd9ff6930b4e24729971a61cf7469daf119beSteve Block break; 9448defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 0: 9458defd9ff6930b4e24729971a61cf7469daf119beSteve Block UNREACHABLE(); 9468defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 9478defd9ff6930b4e24729971a61cf7469daf119beSteve Block default: 9488defd9ff6930b4e24729971a61cf7469daf119beSteve Block movq(dst, reinterpret_cast<uint64_t>(source), RelocInfo::NONE); 9498defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 9508defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 9518defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (negative) { 9528defd9ff6930b4e24729971a61cf7469daf119beSteve Block neg(dst); 9538defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 9548defd9ff6930b4e24729971a61cf7469daf119beSteve Block} 9558defd9ff6930b4e24729971a61cf7469daf119beSteve Block 956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9570d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::Integer32ToSmi(Register dst, Register src) { 95869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!dst.is(src)) { 960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movl(dst, src); 961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 9623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(kSmiShift)); 963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9669dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::Integer32ToSmiField(const Operand& dst, Register src) { 96744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 9689dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen testb(dst, Immediate(0x01)); 969257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label ok; 970257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(zero, &ok, Label::kNear); 9719dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (allow_stub_calls()) { 9729dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Abort("Integer32ToSmiField writing to non-smi location"); 9739dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } else { 9749dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen int3(); 9759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 9769dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen bind(&ok); 9779dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 9789dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen ASSERT(kSmiShift % kBitsPerByte == 0); 9799dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen movl(Operand(dst, kSmiShift / kBitsPerByte), src); 9809dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 9819dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 9829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 9833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::Integer64PlusConstantToSmi(Register dst, 9843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register src, 9853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int constant) { 9863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (dst.is(src)) { 98744f0eee88ff00398ff7f715fab053374d808c90dSteve Block addl(dst, Immediate(constant)); 9883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 98944f0eee88ff00398ff7f715fab053374d808c90dSteve Block leal(dst, Operand(src, constant)); 9903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 9913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(kSmiShift)); 992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiToInteger32(Register dst, Register src) { 99669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!dst.is(src)) { 9983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 10003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shr(dst, Immediate(kSmiShift)); 1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid MacroAssembler::SmiToInteger32(Register dst, const Operand& src) { 10057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch movl(dst, Operand(src, kSmiShift / kBitsPerByte)); 10067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 10077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 10087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiToInteger64(Register dst, Register src) { 101069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 10113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src)) { 10123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 10143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block sar(dst, Immediate(kSmiShift)); 1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10189dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::SmiToInteger64(Register dst, const Operand& src) { 10199dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen movsxlq(dst, Operand(src, kSmiShift / kBitsPerByte)); 10209dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 10219dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 10229dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 10233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiTest(Register src) { 10243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testq(src, src); 1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 102844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::SmiCompare(Register smi1, Register smi2) { 102944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 103044f0eee88ff00398ff7f715fab053374d808c90dSteve Block AbortIfNotSmi(smi1); 103144f0eee88ff00398ff7f715fab053374d808c90dSteve Block AbortIfNotSmi(smi2); 103244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 103344f0eee88ff00398ff7f715fab053374d808c90dSteve Block cmpq(smi1, smi2); 1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(Register dst, Smi* src) { 103844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 103944f0eee88ff00398ff7f715fab053374d808c90dSteve Block AbortIfNotSmi(dst); 104044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 104144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Cmp(dst, src); 104244f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 104344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 104444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 104544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::Cmp(Register dst, Smi* src) { 10463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 10473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (src->value() == 0) { 10483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block testq(dst, dst); 10493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 1050756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Register constant_reg = GetSmiConstant(src); 1051756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick cmpq(dst, constant_reg); 1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1056f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid MacroAssembler::SmiCompare(Register dst, const Operand& src) { 105744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 105844f0eee88ff00398ff7f715fab053374d808c90dSteve Block AbortIfNotSmi(dst); 105944f0eee88ff00398ff7f715fab053374d808c90dSteve Block AbortIfNotSmi(src); 106044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 10616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block cmpq(dst, src); 10626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 10636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(const Operand& dst, Register src) { 106644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 106744f0eee88ff00398ff7f715fab053374d808c90dSteve Block AbortIfNotSmi(dst); 106844f0eee88ff00398ff7f715fab053374d808c90dSteve Block AbortIfNotSmi(src); 106944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 10703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block cmpq(dst, src); 1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(const Operand& dst, Smi* src) { 107544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 107644f0eee88ff00398ff7f715fab053374d808c90dSteve Block AbortIfNotSmi(dst); 107744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 10787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch cmpl(Operand(dst, kSmiShift / kBitsPerByte), Immediate(src->value())); 1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 108244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::Cmp(const Operand& dst, Smi* src) { 108344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // The Operand cannot use the smi register. 108444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register smi_reg = GetSmiConstant(src); 108544f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(!dst.AddressUsesRegister(smi_reg)); 108644f0eee88ff00398ff7f715fab053374d808c90dSteve Block cmpq(dst, smi_reg); 108744f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 108844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 108944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 10909dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::SmiCompareInteger32(const Operand& dst, Register src) { 10919dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen cmpl(Operand(dst, kSmiShift / kBitsPerByte), src); 10929dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 10939dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 10949dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 10953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::PositiveSmiTimesPowerOfTwoToInteger64(Register dst, 10963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register src, 10973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int power) { 10983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(power >= 0); 10993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(power < 64); 11003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (power == 0) { 11013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiToInteger64(dst, src); 11023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block return; 11033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 11043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src)) { 11053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 11063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 11073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (power < kSmiShift) { 11083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block sar(dst, Immediate(kSmiShift - power)); 11093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (power > kSmiShift) { 11103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(power - kSmiShift)); 11113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 11157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid MacroAssembler::PositiveSmiDivPowerOfTwoToInteger32(Register dst, 11167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register src, 11177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch int power) { 11187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT((0 <= power) && (power < 32)); 11197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (dst.is(src)) { 11207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch shr(dst, Immediate(power + kSmiShift)); 11217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 11227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch UNIMPLEMENTED(); // Not used. 11237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 11247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 11257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiOrIfSmis(Register dst, Register src1, Register src2, 1128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_smis, 1129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump) { 1130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (dst.is(src1) || dst.is(src2)) { 1131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!src1.is(kScratchRegister)); 1132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!src2.is(kScratchRegister)); 1133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(kScratchRegister, src1); 1134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch or_(kScratchRegister, src2); 1135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch JumpIfNotSmi(kScratchRegister, on_not_smis, near_jump); 1136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(dst, kScratchRegister); 1137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(dst, src1); 1139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch or_(dst, src2); 1140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch JumpIfNotSmi(dst, on_not_smis, near_jump); 1141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 11453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockCondition MacroAssembler::CheckSmi(Register src) { 114669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block testb(src, Immediate(kSmiTagMask)); 11483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block return zero; 1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 11521e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockCondition MacroAssembler::CheckSmi(const Operand& src) { 115369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 11541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block testb(src, Immediate(kSmiTagMask)); 11551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return zero; 11561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 11571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 11581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1159f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochCondition MacroAssembler::CheckNonNegativeSmi(Register src) { 116069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 1161e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Test that both bits of the mask 0x8000000000000001 are zero. 11623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(kScratchRegister, src); 11633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block rol(kScratchRegister, Immediate(1)); 11648defd9ff6930b4e24729971a61cf7469daf119beSteve Block testb(kScratchRegister, Immediate(3)); 1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return zero; 1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCondition MacroAssembler::CheckBothSmi(Register first, Register second) { 1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (first.is(second)) { 1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return CheckSmi(first); 1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 117369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTag == 0 && kHeapObjectTag == 1 && kHeapObjectTagMask == 3); 11748defd9ff6930b4e24729971a61cf7469daf119beSteve Block leal(kScratchRegister, Operand(first, second, times_1, 0)); 11758defd9ff6930b4e24729971a61cf7469daf119beSteve Block testb(kScratchRegister, Immediate(0x03)); 11763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block return zero; 1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1180f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochCondition MacroAssembler::CheckBothNonNegativeSmi(Register first, 1181f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Register second) { 1182d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (first.is(second)) { 1183f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return CheckNonNegativeSmi(first); 1184d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 11858defd9ff6930b4e24729971a61cf7469daf119beSteve Block movq(kScratchRegister, first); 11868defd9ff6930b4e24729971a61cf7469daf119beSteve Block or_(kScratchRegister, second); 1187d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke rol(kScratchRegister, Immediate(1)); 1188f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch testl(kScratchRegister, Immediate(3)); 1189d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return zero; 1190d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 1191d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1192d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1193bb769b257e753aafcbd96767abb2abc645eaa20cBen MurdochCondition MacroAssembler::CheckEitherSmi(Register first, 1194bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Register second, 1195bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Register scratch) { 1196e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (first.is(second)) { 1197e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return CheckSmi(first); 1198e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1199bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if (scratch.is(second)) { 1200bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch andl(scratch, first); 1201bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } else { 1202bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if (!scratch.is(first)) { 1203bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch movl(scratch, first); 1204bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } 1205bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch andl(scratch, second); 1206bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } 1207bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch testb(scratch, Immediate(kSmiTagMask)); 1208e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return zero; 1209e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1210e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1211e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCondition MacroAssembler::CheckIsMinSmi(Register src) { 12138defd9ff6930b4e24729971a61cf7469daf119beSteve Block ASSERT(!src.is(kScratchRegister)); 12148defd9ff6930b4e24729971a61cf7469daf119beSteve Block // If we overflow by subtracting one, it's the minimal smi value. 12158defd9ff6930b4e24729971a61cf7469daf119beSteve Block cmpq(src, kSmiConstantRegister); 12168defd9ff6930b4e24729971a61cf7469daf119beSteve Block return overflow; 1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockCondition MacroAssembler::CheckInteger32ValidSmiValue(Register src) { 12213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // A 32-bit integer value can always be converted to a smi. 12223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block return always; 1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockCondition MacroAssembler::CheckUInteger32ValidSmiValue(Register src) { 12273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // An unsigned 32-bit integer value is valid as long as the high bit 12283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // is not set. 12298defd9ff6930b4e24729971a61cf7469daf119beSteve Block testl(src, src); 12308defd9ff6930b4e24729971a61cf7469daf119beSteve Block return positive; 1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::CheckSmiToIndicator(Register dst, Register src) { 12351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (dst.is(src)) { 12361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block andl(dst, Immediate(kSmiTagMask)); 12371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 12381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block movl(dst, Immediate(kSmiTagMask)); 12391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block andl(dst, src); 12401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 12411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 12421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 12431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 12441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::CheckSmiToIndicator(Register dst, const Operand& src) { 12451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (!(src.AddressUsesRegister(dst))) { 12461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block movl(dst, Immediate(kSmiTagMask)); 12471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block andl(dst, src); 12481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 12491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block movl(dst, src); 12501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block andl(dst, Immediate(kSmiTagMask)); 12511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 12521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 12531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 12541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfNotValidSmiValue(Register src, 1256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_invalid, 1257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump) { 1258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Condition is_valid = CheckInteger32ValidSmiValue(src); 1259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(NegateCondition(is_valid), on_invalid, near_jump); 1260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfUIntNotValidSmiValue(Register src, 1264257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_invalid, 1265257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump) { 1266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Condition is_valid = CheckUInteger32ValidSmiValue(src); 1267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(NegateCondition(is_valid), on_invalid, near_jump); 1268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfSmi(Register src, 1272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_smi, 1273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump) { 1274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Condition smi = CheckSmi(src); 1275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(smi, on_smi, near_jump); 1276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfNotSmi(Register src, 1280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_smi, 1281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump) { 1282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Condition smi = CheckSmi(src); 1283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(NegateCondition(smi), on_not_smi, near_jump); 1284257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1285257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1286257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpUnlessNonNegativeSmi( 1288257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register src, Label* on_not_smi_or_negative, 1289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump) { 1290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Condition non_negative_smi = CheckNonNegativeSmi(src); 1291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(NegateCondition(non_negative_smi), on_not_smi_or_negative, near_jump); 1292257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1293257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfSmiEqualsConstant(Register src, 1296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Smi* constant, 1297257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_equals, 1298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump) { 1299257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SmiCompare(src, constant); 1300257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(equal, on_equals, near_jump); 1301257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1302257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1303257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1304257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfNotBothSmi(Register src1, 1305257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register src2, 1306257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_both_smi, 1307257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump) { 1308257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Condition both_smi = CheckBothSmi(src1, src2); 1309257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(NegateCondition(both_smi), on_not_both_smi, near_jump); 1310257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1311257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpUnlessBothNonNegativeSmi(Register src1, 1314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register src2, 1315257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_both_smi, 1316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump) { 1317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Condition both_smi = CheckBothNonNegativeSmi(src1, src2); 1318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(NegateCondition(both_smi), on_not_both_smi, near_jump); 1319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1322257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiTryAddConstant(Register dst, 1323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register src, 1324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Smi* constant, 1325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_smi_result, 1326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump) { 1327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Does not assume that src is a smi. 1328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT_EQ(static_cast<int>(1), static_cast<int>(kSmiTagMask)); 132969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 1330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!dst.is(kScratchRegister)); 1331257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!src.is(kScratchRegister)); 1332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch JumpIfNotSmi(src, on_not_smi_result, near_jump); 1334257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register tmp = (dst.is(src) ? kScratchRegister : dst); 1335257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch LoadSmiConstant(tmp, constant); 1336257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch addq(tmp, src); 1337257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(overflow, on_not_smi_result, near_jump); 1338257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (dst.is(src)) { 1339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(dst, tmp); 1340257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1342257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1343257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 13443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiAddConstant(Register dst, Register src, Smi* constant) { 13453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (constant->value() == 0) { 13463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src)) { 13473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 13483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 13498defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 13503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (dst.is(src)) { 13513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 13528defd9ff6930b4e24729971a61cf7469daf119beSteve Block switch (constant->value()) { 13538defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 1: 13548defd9ff6930b4e24729971a61cf7469daf119beSteve Block addq(dst, kSmiConstantRegister); 13558defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 13568defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 2: 13578defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(src, kSmiConstantRegister, times_2, 0)); 13588defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 13598defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 4: 13608defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(src, kSmiConstantRegister, times_4, 0)); 13618defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 13628defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 8: 13638defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(src, kSmiConstantRegister, times_8, 0)); 13648defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 13658defd9ff6930b4e24729971a61cf7469daf119beSteve Block default: 13668defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register constant_reg = GetSmiConstant(constant); 13678defd9ff6930b4e24729971a61cf7469daf119beSteve Block addq(dst, constant_reg); 13688defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 13698defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 13718defd9ff6930b4e24729971a61cf7469daf119beSteve Block switch (constant->value()) { 13728defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 1: 13738defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(src, kSmiConstantRegister, times_1, 0)); 13748defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 13758defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 2: 13768defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(src, kSmiConstantRegister, times_2, 0)); 13778defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 13788defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 4: 13798defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(src, kSmiConstantRegister, times_4, 0)); 13808defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 13818defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 8: 13828defd9ff6930b4e24729971a61cf7469daf119beSteve Block lea(dst, Operand(src, kSmiConstantRegister, times_8, 0)); 13838defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 13848defd9ff6930b4e24729971a61cf7469daf119beSteve Block default: 13858defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(dst, constant); 13868defd9ff6930b4e24729971a61cf7469daf119beSteve Block addq(dst, src); 13878defd9ff6930b4e24729971a61cf7469daf119beSteve Block return; 13888defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 1389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1393f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid MacroAssembler::SmiAddConstant(const Operand& dst, Smi* constant) { 1394f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (constant->value() != 0) { 13957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch addl(Operand(dst, kSmiShift / kBitsPerByte), Immediate(constant->value())); 1396f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1397f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1398f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1399f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiAddConstant(Register dst, 1401257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register src, 1402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Smi* constant, 1403257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_smi_result, 1404257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump) { 1405257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (constant->value() == 0) { 1406257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!dst.is(src)) { 1407257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(dst, src); 1408257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else if (dst.is(src)) { 1410257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!dst.is(kScratchRegister)); 1411257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1412257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch LoadSmiConstant(kScratchRegister, constant); 1413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch addq(kScratchRegister, src); 1414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(overflow, on_not_smi_result, near_jump); 1415257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(dst, kScratchRegister); 1416257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1417257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch LoadSmiConstant(dst, constant); 1418257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch addq(dst, src); 1419257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(overflow, on_not_smi_result, near_jump); 1420257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1421257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1422257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1423257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 14243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiSubConstant(Register dst, Register src, Smi* constant) { 14253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (constant->value() == 0) { 1426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!dst.is(src)) { 14273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 1428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 14293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (dst.is(src)) { 14303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 14318defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register constant_reg = GetSmiConstant(constant); 14328defd9ff6930b4e24729971a61cf7469daf119beSteve Block subq(dst, constant_reg); 14333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 14343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (constant->value() == Smi::kMinValue) { 14358defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(dst, constant); 14369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Adding and subtracting the min-value gives the same result, it only 14379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // differs on the overflow bit, which we don't check here. 14389dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen addq(dst, src); 1439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 14409dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Subtract by adding the negation. 14418defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(dst, Smi::FromInt(-constant->value())); 14423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block addq(dst, src); 1443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiSubConstant(Register dst, 1449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register src, 1450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Smi* constant, 1451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_smi_result, 1452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump) { 1453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (constant->value() == 0) { 1454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!dst.is(src)) { 1455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(dst, src); 1456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else if (dst.is(src)) { 1458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!dst.is(kScratchRegister)); 1459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (constant->value() == Smi::kMinValue) { 1460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Subtracting min-value from any non-negative value will overflow. 1461257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We test the non-negativeness before doing the subtraction. 1462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch testq(src, src); 1463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(not_sign, on_not_smi_result, near_jump); 1464257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch LoadSmiConstant(kScratchRegister, constant); 1465257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch subq(dst, kScratchRegister); 1466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Subtract by adding the negation. 1468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch LoadSmiConstant(kScratchRegister, Smi::FromInt(-constant->value())); 1469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch addq(kScratchRegister, dst); 1470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(overflow, on_not_smi_result, near_jump); 1471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(dst, kScratchRegister); 1472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (constant->value() == Smi::kMinValue) { 1475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Subtracting min-value from any non-negative value will overflow. 1476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We test the non-negativeness before doing the subtraction. 1477257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch testq(src, src); 1478257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(not_sign, on_not_smi_result, near_jump); 1479257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch LoadSmiConstant(dst, constant); 1480257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Adding and subtracting the min-value gives the same result, it only 1481257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // differs on the overflow bit, which we don't check here. 1482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch addq(dst, src); 1483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1484257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Subtract by adding the negation. 1485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch LoadSmiConstant(dst, Smi::FromInt(-(constant->value()))); 1486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch addq(dst, src); 1487257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(overflow, on_not_smi_result, near_jump); 1488257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1489257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1490257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1491257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1492257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1493257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiNeg(Register dst, 1494257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register src, 1495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_smi_result, 1496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump) { 1497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (dst.is(src)) { 1498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!dst.is(kScratchRegister)); 1499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(kScratchRegister, src); 1500257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch neg(dst); // Low 32 bits are retained as zero by negation. 1501257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Test if result is zero or Smi::kMinValue. 1502257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cmpq(dst, kScratchRegister); 1503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(not_equal, on_smi_result, near_jump); 1504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(src, kScratchRegister); 1505257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(dst, src); 1507257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch neg(dst); 1508257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cmpq(dst, src); 1509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If the result is zero or Smi::kMinValue, negation failed to create a smi. 1510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(not_equal, on_smi_result, near_jump); 1511257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1512257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1513257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiAdd(Register dst, 1516257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register src1, 1517257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register src2, 1518257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_smi_result, 1519257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump) { 1520257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT_NOT_NULL(on_not_smi_result); 1521257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!dst.is(src2)); 1522257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (dst.is(src1)) { 1523257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(kScratchRegister, src1); 1524257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch addq(kScratchRegister, src2); 1525257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(overflow, on_not_smi_result, near_jump); 1526257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(dst, kScratchRegister); 1527257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1528257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(dst, src1); 1529257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch addq(dst, src2); 1530257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(overflow, on_not_smi_result, near_jump); 1531257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1532257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1533257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1535257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiAdd(Register dst, 1536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register src1, 1537257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const Operand& src2, 1538257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_smi_result, 1539257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump) { 1540257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT_NOT_NULL(on_not_smi_result); 1541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (dst.is(src1)) { 1542257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(kScratchRegister, src1); 1543257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch addq(kScratchRegister, src2); 1544257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(overflow, on_not_smi_result, near_jump); 1545257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(dst, kScratchRegister); 1546257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1547257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!src2.AddressUsesRegister(dst)); 1548257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(dst, src1); 1549257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch addq(dst, src2); 1550257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(overflow, on_not_smi_result, near_jump); 1551257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1552257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1554257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 15550d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::SmiAdd(Register dst, 15560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register src1, 15570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register src2) { 15580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // No overflow checking. Use only when it's known that 15590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // overflowing is impossible. 156044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!dst.is(src1)) { 1561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (emit_debug_code()) { 1562257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(kScratchRegister, src1); 1563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch addq(kScratchRegister, src2); 1564257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Check(no_overflow, "Smi addition overflow"); 1565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch lea(dst, Operand(src1, src2, times_1, 0)); 1567257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1568257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch addq(dst, src2); 1569257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Assert(no_overflow, "Smi addition overflow"); 1570257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1571257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1572257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1573257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1574257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiSub(Register dst, 1575257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register src1, 1576257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register src2, 1577257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_smi_result, 1578257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump) { 1579257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT_NOT_NULL(on_not_smi_result); 1580257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!dst.is(src2)); 1581257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (dst.is(src1)) { 1582257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cmpq(dst, src2); 1583257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(overflow, on_not_smi_result, near_jump); 1584257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch subq(dst, src2); 1585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1586053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block movq(dst, src1); 1587257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch subq(dst, src2); 1588257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(overflow, on_not_smi_result, near_jump); 1589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 15930d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::SmiSub(Register dst, Register src1, Register src2) { 15940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // No overflow checking. Use only when it's known that 15950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // overflowing is impossible (e.g., subtracting two positive smis). 15960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(!dst.is(src2)); 159744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!dst.is(src1)) { 15980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen movq(dst, src1); 15993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 160044f0eee88ff00398ff7f715fab053374d808c90dSteve Block subq(dst, src2); 16010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Assert(no_overflow, "Smi subtraction overflow"); 1602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16050d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::SmiSub(Register dst, 1606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 1607257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const Operand& src2, 1608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_smi_result, 1609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump) { 1610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT_NOT_NULL(on_not_smi_result); 1611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (dst.is(src1)) { 1612257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(kScratchRegister, src2); 1613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cmpq(src1, kScratchRegister); 1614257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(overflow, on_not_smi_result, near_jump); 1615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch subq(src1, kScratchRegister); 1616257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1617257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(dst, src1); 1618257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch subq(dst, src2); 1619257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(overflow, on_not_smi_result, near_jump); 1620257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1621257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1622257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1623257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiSub(Register dst, 1625257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register src1, 16260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen const Operand& src2) { 16270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // No overflow checking. Use only when it's known that 16280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // overflowing is impossible (e.g., subtracting two positive smis). 162944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!dst.is(src1)) { 16300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen movq(dst, src1); 1631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 163244f0eee88ff00398ff7f715fab053374d808c90dSteve Block subq(dst, src2); 16330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Assert(no_overflow, "Smi subtraction overflow"); 1634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1637257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiMul(Register dst, 1638257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register src1, 1639257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register src2, 1640257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_smi_result, 1641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump) { 1642257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!dst.is(src2)); 1643257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!dst.is(kScratchRegister)); 1644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!src1.is(kScratchRegister)); 1645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!src2.is(kScratchRegister)); 1646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (dst.is(src1)) { 1648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label failure, zero_correct_result; 1649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(kScratchRegister, src1); // Create backup for later testing. 1650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SmiToInteger64(dst, src1); 1651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch imul(dst, src2); 1652257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(overflow, &failure, Label::kNear); 1653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check for negative zero result. If product is zero, and one 1655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // argument is negative, go to slow case. 1656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label correct_result; 1657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch testq(dst, dst); 1658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(not_zero, &correct_result, Label::kNear); 1659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(dst, kScratchRegister); 1661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch xor_(dst, src2); 1662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Result was positive zero. 1663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(positive, &zero_correct_result, Label::kNear); 1664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bind(&failure); // Reused failure exit, restores src1. 1666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(src1, kScratchRegister); 1667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch jmp(on_not_smi_result, near_jump); 1668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bind(&zero_correct_result); 1670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Set(dst, 0); 1671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bind(&correct_result); 1673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SmiToInteger64(dst, src1); 1675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch imul(dst, src2); 1676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(overflow, on_not_smi_result, near_jump); 1677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check for negative zero result. If product is zero, and one 1678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // argument is negative, go to slow case. 1679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label correct_result; 1680257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch testq(dst, dst); 1681257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(not_zero, &correct_result, Label::kNear); 1682257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // One of src1 and src2 is zero, the check whether the other is 1683257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // negative. 1684257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(kScratchRegister, src1); 1685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch xor_(kScratchRegister, src2); 1686257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(negative, on_not_smi_result, near_jump); 1687257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bind(&correct_result); 1688257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1689257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1690257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1691257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiDiv(Register dst, 1693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register src1, 1694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register src2, 1695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_smi_result, 1696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump) { 1697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!src1.is(kScratchRegister)); 1698257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!src2.is(kScratchRegister)); 1699257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!dst.is(kScratchRegister)); 1700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!src2.is(rax)); 1701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!src2.is(rdx)); 1702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!src1.is(rdx)); 1703257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1704257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check for 0 divisor (result is +/-Infinity). 1705257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch testq(src2, src2); 1706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(zero, on_not_smi_result, near_jump); 1707257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1708257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (src1.is(rax)) { 1709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(kScratchRegister, src1); 1710257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1711257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SmiToInteger32(rax, src1); 1712257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We need to rule out dividing Smi::kMinValue by -1, since that would 1713257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // overflow in idiv and raise an exception. 1714257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We combine this with negative zero test (negative zero only happens 1715257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // when dividing zero by a negative number). 1716257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1717257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We overshoot a little and go to slow case if we divide min-value 1718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // by any negative value, not just -1. 1719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label safe_div; 1720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch testl(rax, Immediate(0x7fffffff)); 1721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(not_zero, &safe_div, Label::kNear); 1722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch testq(src2, src2); 1723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (src1.is(rax)) { 1724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(positive, &safe_div, Label::kNear); 1725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(src1, kScratchRegister); 1726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch jmp(on_not_smi_result, near_jump); 1727257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(negative, on_not_smi_result, near_jump); 1729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bind(&safe_div); 1731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SmiToInteger32(src2, src2); 1733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Sign extend src1 into edx:eax. 1734257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cdq(); 1735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch idivl(src2); 1736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Integer32ToSmi(src2, src2); 1737257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the remainder is zero. 1738257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch testl(rdx, rdx); 1739257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (src1.is(rax)) { 1740257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label smi_result; 1741257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(zero, &smi_result, Label::kNear); 1742257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(src1, kScratchRegister); 1743257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch jmp(on_not_smi_result, near_jump); 1744257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bind(&smi_result); 1745257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1746257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(not_zero, on_not_smi_result, near_jump); 1747257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!dst.is(src1) && src1.is(rax)) { 1749257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(src1, kScratchRegister); 1750257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Integer32ToSmi(dst, rax); 1752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1754257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1755257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiMod(Register dst, 1756257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register src1, 1757257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register src2, 1758257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_smi_result, 1759257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump) { 1760257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!dst.is(kScratchRegister)); 1761257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!src1.is(kScratchRegister)); 1762257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!src2.is(kScratchRegister)); 1763257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!src2.is(rax)); 1764257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!src2.is(rdx)); 1765257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!src1.is(rdx)); 1766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!src1.is(src2)); 1767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1768257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch testq(src2, src2); 1769257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(zero, on_not_smi_result, near_jump); 1770257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (src1.is(rax)) { 1772257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(kScratchRegister, src1); 1773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SmiToInteger32(rax, src1); 1775257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SmiToInteger32(src2, src2); 1776257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1777257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Test for the edge case of dividing Smi::kMinValue by -1 (will overflow). 1778257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label safe_div; 1779257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cmpl(rax, Immediate(Smi::kMinValue)); 1780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(not_equal, &safe_div, Label::kNear); 1781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cmpl(src2, Immediate(-1)); 1782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(not_equal, &safe_div, Label::kNear); 1783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Retag inputs and go slow case. 1784257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Integer32ToSmi(src2, src2); 1785257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (src1.is(rax)) { 1786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(src1, kScratchRegister); 1787257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1788257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch jmp(on_not_smi_result, near_jump); 1789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bind(&safe_div); 1790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Sign extend eax into edx:eax. 1792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cdq(); 1793257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch idivl(src2); 1794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Restore smi tags on inputs. 1795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Integer32ToSmi(src2, src2); 1796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (src1.is(rax)) { 1797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(src1, kScratchRegister); 1798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1799257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check for a negative zero result. If the result is zero, and the 1800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // dividend is negative, go slow to return a floating point negative zero. 1801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label smi_result; 1802257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch testl(rdx, rdx); 1803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(not_zero, &smi_result, Label::kNear); 1804257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch testq(src1, src1); 1805257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(negative, on_not_smi_result, near_jump); 1806257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bind(&smi_result); 1807257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Integer32ToSmi(dst, rdx); 1808257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1809257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1810257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiNot(Register dst, Register src) { 18123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 18133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src.is(kScratchRegister)); 18143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Set tag and padding bits before negating, so that they are zero afterwards. 18153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movl(kScratchRegister, Immediate(~0)); 1816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (dst.is(src)) { 18173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block xor_(dst, kScratchRegister); 1818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 18193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block lea(dst, Operand(src, kScratchRegister, times_1, 0)); 1820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 18213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block not_(dst); 1822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiAnd(Register dst, Register src1, Register src2) { 18263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(src2)); 1827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!dst.is(src1)) { 18283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src1); 1829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block and_(dst, src2); 1831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 18343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiAndConstant(Register dst, Register src, Smi* constant) { 18353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (constant->value() == 0) { 18369fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Set(dst, 0); 18373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (dst.is(src)) { 18383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 18398defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register constant_reg = GetSmiConstant(constant); 18408defd9ff6930b4e24729971a61cf7469daf119beSteve Block and_(dst, constant_reg); 18413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 18428defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(dst, constant); 18433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block and_(dst, src); 1844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiOr(Register dst, Register src1, Register src2) { 1849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!dst.is(src1)) { 18508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!src1.is(src2)); 18513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src1); 1852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block or_(dst, src2); 1854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 18573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiOrConstant(Register dst, Register src, Smi* constant) { 18583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (dst.is(src)) { 18593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 18608defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register constant_reg = GetSmiConstant(constant); 18618defd9ff6930b4e24729971a61cf7469daf119beSteve Block or_(dst, constant_reg); 18623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 18638defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(dst, constant); 18643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block or_(dst, src); 1865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 18683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiXor(Register dst, Register src1, Register src2) { 1870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!dst.is(src1)) { 18718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!src1.is(src2)); 18723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src1); 1873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block xor_(dst, src2); 1875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 18783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiXorConstant(Register dst, Register src, Smi* constant) { 18793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (dst.is(src)) { 18803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 18818defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register constant_reg = GetSmiConstant(constant); 18828defd9ff6930b4e24729971a61cf7469daf119beSteve Block xor_(dst, constant_reg); 18833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 18848defd9ff6930b4e24729971a61cf7469daf119beSteve Block LoadSmiConstant(dst, constant); 18853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block xor_(dst, src); 1886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftArithmeticRightConstant(Register dst, 1891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 1892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int shift_value) { 18933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(is_uint5(shift_value)); 1894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (shift_value > 0) { 1895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (dst.is(src)) { 18963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block sar(dst, Immediate(shift_value + kSmiShift)); 18973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(kSmiShift)); 1898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNIMPLEMENTED(); // Not used. 1900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftLeftConstant(Register dst, 1906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 190725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen int shift_value) { 19083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src)) { 19093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 19103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 19113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (shift_value > 0) { 19123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(shift_value)); 1913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiShiftLogicalRightConstant( 1918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register dst, Register src, int shift_value, 1919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_smi_result, Label::Distance near_jump) { 1920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Logic right shift interprets its result as an *unsigned* number. 1921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (dst.is(src)) { 1922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch UNIMPLEMENTED(); // Not used. 1923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(dst, src); 1925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (shift_value == 0) { 1926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch testq(dst, dst); 1927257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(negative, on_not_smi_result, near_jump); 1928257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1929257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch shr(dst, Immediate(shift_value + kSmiShift)); 1930257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch shl(dst, Immediate(kSmiShift)); 1931257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1932257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1933257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1934257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftLeft(Register dst, 1936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 193725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Register src2) { 1938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(rcx)); 19393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Untag shift amount. 19403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src1)) { 19413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src1); 1942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 19433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SmiToInteger32(rcx, src2); 19443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Shift amount specified by lower 5 bits, not six as the shl opcode. 19453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block and_(rcx, Immediate(0x1f)); 1946d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block shl_cl(dst); 1947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1950257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiShiftLogicalRight(Register dst, 1951257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register src1, 1952257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register src2, 1953257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_smi_result, 1954257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump) { 1955257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!dst.is(kScratchRegister)); 1956257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!src1.is(kScratchRegister)); 1957257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!src2.is(kScratchRegister)); 1958257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!dst.is(rcx)); 1959257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // dst and src1 can be the same, because the one case that bails out 1960257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // is a shift by 0, which leaves dst, and therefore src1, unchanged. 1961257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (src1.is(rcx) || src2.is(rcx)) { 1962257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(kScratchRegister, rcx); 1963257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1964257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!dst.is(src1)) { 1965257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(dst, src1); 1966257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1967257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SmiToInteger32(rcx, src2); 1968257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch orl(rcx, Immediate(kSmiShift)); 1969257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch shr_cl(dst); // Shift is rcx modulo 0x1f + 32. 1970257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch shl(dst, Immediate(kSmiShift)); 1971257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch testq(dst, dst); 1972257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (src1.is(rcx) || src2.is(rcx)) { 1973257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label positive_result; 1974257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(positive, &positive_result, Label::kNear); 1975257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (src1.is(rcx)) { 1976257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(src1, kScratchRegister); 1977257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1978257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(src2, kScratchRegister); 1979257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1980257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch jmp(on_not_smi_result, near_jump); 1981257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bind(&positive_result); 1982257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1983257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // src2 was zero and src1 negative. 1984257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(negative, on_not_smi_result, near_jump); 1985257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1986257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1987257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1988257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftArithmeticRight(Register dst, 1990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 1991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2) { 19923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!dst.is(kScratchRegister)); 19933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src1.is(kScratchRegister)); 19943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!src2.is(kScratchRegister)); 1995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(rcx)); 19963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (src1.is(rcx)) { 19973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(kScratchRegister, src1); 19983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (src2.is(rcx)) { 19993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(kScratchRegister, src2); 20003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 20013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src1)) { 20023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src1); 20033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SmiToInteger32(rcx, src2); 20053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block orl(rcx, Immediate(kSmiShift)); 2006d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block sar_cl(dst); // Shift 32 + original rcx & 0x1f. 20073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(kSmiShift)); 20083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (src1.is(rcx)) { 20093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src1, kScratchRegister); 20103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (src2.is(rcx)) { 20113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(src2, kScratchRegister); 20123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2016257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SelectNonSmi(Register dst, 2017257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register src1, 2018257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register src2, 2019257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_not_smis, 2020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump) { 2021257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!dst.is(kScratchRegister)); 2022257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!src1.is(kScratchRegister)); 2023257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!src2.is(kScratchRegister)); 2024257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!dst.is(src1)); 2025257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!dst.is(src2)); 2026257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Both operands must not be smis. 2027257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#ifdef DEBUG 2028257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (allow_stub_calls()) { // Check contains a stub call. 2029257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Condition not_both_smis = NegateCondition(CheckBothSmi(src1, src2)); 2030257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Check(not_both_smis, "Both registers were smis in SelectNonSmi."); 2031257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2032257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif 203369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 2034257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT_EQ(0, Smi::FromInt(0)); 2035257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movl(kScratchRegister, Immediate(kSmiTagMask)); 2036257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch and_(kScratchRegister, src1); 2037257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch testl(kScratchRegister, src2); 2038257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If non-zero then both are smis. 2039257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(not_zero, on_not_smis, near_jump); 2040257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2041257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Exactly one operand is a smi. 2042257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT_EQ(1, static_cast<int>(kSmiTagMask)); 2043257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // kScratchRegister still holds src1 & kSmiTag, which is either zero or one. 2044257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch subq(kScratchRegister, Immediate(1)); 2045257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If src1 is a smi, then scratch register all 1s, else it is all 0s. 2046257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(dst, src1); 2047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch xor_(dst, src2); 2048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch and_(dst, kScratchRegister); 2049257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If src1 is a smi, dst holds src1 ^ src2, else it is zero. 2050257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch xor_(dst, src1); 2051257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If src1 is a smi, dst is src2, else it is src1, i.e., the non-smi. 2052257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 2053257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2054257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 20553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockSmiIndex MacroAssembler::SmiToIndex(Register dst, 20563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register src, 20573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int shift) { 2058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_uint6(shift)); 20593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // There is a possible optimization if shift is in the range 60-63, but that 20603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // will (and must) never happen. 20613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src)) { 20623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 20633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 20643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (shift < kSmiShift) { 20653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block sar(dst, Immediate(kSmiShift - shift)); 20663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 20673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(shift - kSmiShift)); 20683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return SmiIndex(dst, times_1); 2070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockSmiIndex MacroAssembler::SmiToNegativeIndex(Register dst, 2073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 2074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int shift) { 2075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Register src holds a positive smi. 2076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_uint6(shift)); 20773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!dst.is(src)) { 20783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(dst, src); 2079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block neg(dst); 20813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (shift < kSmiShift) { 20823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block sar(dst, Immediate(kSmiShift - shift)); 20833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 20843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shl(dst, Immediate(shift - kSmiShift)); 20853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return SmiIndex(dst, times_1); 2087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 209044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::AddSmiField(Register dst, const Operand& src) { 209144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT_EQ(0, kSmiShift % kBitsPerByte); 209244f0eee88ff00398ff7f715fab053374d808c90dSteve Block addl(dst, Operand(src, kSmiShift / kBitsPerByte)); 209344f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 209444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 209544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 2096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfNotString(Register object, 2097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register object_map, 2098257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* not_string, 2099257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump) { 2100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Condition is_smi = CheckSmi(object); 2101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(is_smi, not_string, near_jump); 2102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CmpObjectType(object, FIRST_NONSTRING_TYPE, object_map); 2103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(above_equal, not_string, near_jump); 2104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 2105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfNotBothSequentialAsciiStrings( 2108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register first_object, 2109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register second_object, 2110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch1, 2111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch2, 2112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_fail, 2113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump) { 2114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that both objects are not smis. 2115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Condition either_smi = CheckEitherSmi(first_object, second_object); 2116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(either_smi, on_fail, near_jump); 2117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load instance type for both strings. 2119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(scratch1, FieldOperand(first_object, HeapObject::kMapOffset)); 2120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(scratch2, FieldOperand(second_object, HeapObject::kMapOffset)); 2121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movzxbl(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset)); 2122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movzxbl(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset)); 2123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 21243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that both are flat ASCII strings. 2125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(kNotStringTag != 0); 2126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int kFlatAsciiStringMask = 2127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; 2128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int kFlatAsciiStringTag = ASCII_STRING_TYPE; 2129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch andl(scratch1, Immediate(kFlatAsciiStringMask)); 2131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch andl(scratch2, Immediate(kFlatAsciiStringMask)); 2132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Interleave the bits to check both scratch1 and scratch2 in one test. 2133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3)); 2134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch lea(scratch1, Operand(scratch1, scratch2, times_8, 0)); 2135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cmpl(scratch1, 2136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Immediate(kFlatAsciiStringTag + (kFlatAsciiStringTag << 3))); 2137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(not_equal, on_fail, near_jump); 2138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 2139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii( 2142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register instance_type, 2143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch, 2144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* failure, 2145257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump) { 2146257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!scratch.is(instance_type)) { 2147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movl(scratch, instance_type); 2148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int kFlatAsciiStringMask = 2151257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; 2152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch andl(scratch, Immediate(kFlatAsciiStringMask)); 2154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cmpl(scratch, Immediate(kStringTag | kSeqStringTag | kAsciiStringTag)); 2155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(not_equal, failure, near_jump); 2156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 2157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialAscii( 2160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register first_object_instance_type, 2161257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register second_object_instance_type, 2162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch1, 2163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch2, 2164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* on_fail, 2165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump) { 2166257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load instance type for both strings. 2167257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(scratch1, first_object_instance_type); 2168257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(scratch2, second_object_instance_type); 2169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 21703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that both are flat ASCII strings. 2171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(kNotStringTag != 0); 2172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int kFlatAsciiStringMask = 2173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; 2174257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int kFlatAsciiStringTag = ASCII_STRING_TYPE; 2175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2176257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch andl(scratch1, Immediate(kFlatAsciiStringMask)); 2177257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch andl(scratch2, Immediate(kFlatAsciiStringMask)); 2178257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Interleave the bits to check both scratch1 and scratch2 in one test. 2179257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3)); 2180257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch lea(scratch1, Operand(scratch1, scratch2, times_8, 0)); 2181257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cmpl(scratch1, 2182257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Immediate(kFlatAsciiStringTag + (kFlatAsciiStringTag << 3))); 2183257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(not_equal, on_fail, near_jump); 2184257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 2185257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2186257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 218744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 21880d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::Move(Register dst, Register src) { 21890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!dst.is(src)) { 21900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen movq(dst, src); 21916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 21926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 21936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 21946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Move(Register dst, Handle<Object> source) { 2196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!source->IsFailure()); 2197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (source->IsSmi()) { 21983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(dst, Smi::cast(*source)); 2199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 2200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(dst, source, RelocInfo::EMBEDDED_OBJECT); 2201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Move(const Operand& dst, Handle<Object> source) { 22063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(!source->IsFailure()); 2207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (source->IsSmi()) { 22083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(dst, Smi::cast(*source)); 2209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 2210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT); 2211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(dst, kScratchRegister); 2212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Cmp(Register dst, Handle<Object> source) { 22173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (source->IsSmi()) { 221844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Cmp(dst, Smi::cast(*source)); 22193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 22203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(kScratchRegister, source); 22213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block cmpq(dst, kScratchRegister); 22223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Cmp(const Operand& dst, Handle<Object> source) { 2227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (source->IsSmi()) { 222844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Cmp(dst, Smi::cast(*source)); 2229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 2230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(source->IsHeapObject()); 2231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT); 2232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(dst, kScratchRegister); 2233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Push(Handle<Object> source) { 2238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (source->IsSmi()) { 22393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Push(Smi::cast(*source)); 2240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 2241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(source->IsHeapObject()); 2242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT); 2243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(kScratchRegister); 2244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 22483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::LoadHeapObject(Register result, 22493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<HeapObject> object) { 22503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (isolate()->heap()->InNewSpace(*object)) { 22513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell = 22523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate()->factory()->NewJSGlobalPropertyCell(object); 22533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(result, cell, RelocInfo::GLOBAL_PROPERTY_CELL); 22543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(result, Operand(result, 0)); 22553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 22563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Move(result, object); 22573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 22583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 22593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 22603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 22613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::PushHeapObject(Handle<HeapObject> object) { 22623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (isolate()->heap()->InNewSpace(*object)) { 22633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell = 22643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate()->factory()->NewJSGlobalPropertyCell(object); 22653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(kScratchRegister, cell, RelocInfo::GLOBAL_PROPERTY_CELL); 22663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(kScratchRegister, Operand(kScratchRegister, 0)); 22673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch push(kScratchRegister); 22683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 22693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Push(object); 22703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 22713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 22723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 22733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 22743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::LoadGlobalCell(Register dst, 22753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell) { 22763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (dst.is(rax)) { 22773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch load_rax(cell.location(), RelocInfo::GLOBAL_PROPERTY_CELL); 22783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 22793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(dst, cell, RelocInfo::GLOBAL_PROPERTY_CELL); 22803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(dst, Operand(dst, 0)); 22813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 22823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 22833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 22843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Push(Smi* source) { 22863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block intptr_t smi = reinterpret_cast<intptr_t>(source); 22873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (is_int32(smi)) { 22883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block push(Immediate(static_cast<int32_t>(smi))); 22893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 22908defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register constant = GetSmiConstant(source); 22918defd9ff6930b4e24729971a61cf7469daf119beSteve Block push(constant); 22923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 22933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 22943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 22953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2296e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::Drop(int stack_elements) { 2297e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (stack_elements > 0) { 2298e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke addq(rsp, Immediate(stack_elements * kPointerSize)); 2299e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2300e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 2301e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2302e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 23033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::Test(const Operand& src, Smi* source) { 2304f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke testl(Operand(src, kIntSize), Immediate(source->value())); 2305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 23083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::TestBit(const Operand& src, int bits) { 23093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int byte_offset = bits / kBitsPerByte; 23103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int bit_in_byte = bits & (kBitsPerByte - 1); 23113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch testb(Operand(src, byte_offset), Immediate(1 << bit_in_byte)); 23123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 23133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 23143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Jump(ExternalReference ext) { 231644f0eee88ff00398ff7f715fab053374d808c90dSteve Block LoadAddress(kScratchRegister, ext); 2317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block jmp(kScratchRegister); 2318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Jump(Address destination, RelocInfo::Mode rmode) { 2322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, destination, rmode); 2323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block jmp(kScratchRegister); 2324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Jump(Handle<Code> code_object, RelocInfo::Mode rmode) { 23283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // TODO(X64): Inline this 23293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block jmp(code_object, rmode); 2330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 233344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint MacroAssembler::CallSize(ExternalReference ext) { 233444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Opcode for call kScratchRegister is: Rex.B FF D4 (three bytes). 233544f0eee88ff00398ff7f715fab053374d808c90dSteve Block const int kCallInstructionSize = 3; 233644f0eee88ff00398ff7f715fab053374d808c90dSteve Block return LoadAddressSize(ext) + kCallInstructionSize; 233744f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 233844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 233944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 2340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Call(ExternalReference ext) { 234144f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG 234244f0eee88ff00398ff7f715fab053374d808c90dSteve Block int end_position = pc_offset() + CallSize(ext); 234344f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif 234444f0eee88ff00398ff7f715fab053374d808c90dSteve Block LoadAddress(kScratchRegister, ext); 2345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block call(kScratchRegister); 234644f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG 234744f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_EQ(end_position, pc_offset()); 234844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif 2349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Call(Address destination, RelocInfo::Mode rmode) { 235344f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG 235444f0eee88ff00398ff7f715fab053374d808c90dSteve Block int end_position = pc_offset() + CallSize(destination, rmode); 235544f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif 2356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, destination, rmode); 2357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block call(kScratchRegister); 235844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG 235944f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_EQ(pc_offset(), end_position); 236044f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif 2361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2364257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::Call(Handle<Code> code_object, 2365257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch RelocInfo::Mode rmode, 2366257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch unsigned ast_id) { 236744f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG 236844f0eee88ff00398ff7f715fab053374d808c90dSteve Block int end_position = pc_offset() + CallSize(code_object); 236944f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif 2370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(RelocInfo::IsCodeTarget(rmode)); 2371257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch call(code_object, rmode, ast_id); 237244f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG 237344f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_EQ(end_position, pc_offset()); 237444f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif 2375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 23781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::Pushad() { 23791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block push(rax); 23801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block push(rcx); 23811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block push(rdx); 23821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block push(rbx); 23831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Not pushing rsp or rbp. 23841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block push(rsi); 23851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block push(rdi); 23861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block push(r8); 23871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block push(r9); 23881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // r10 is kScratchRegister. 23891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block push(r11); 239044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // r12 is kSmiConstantRegister. 23911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // r13 is kRootRegister. 23921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block push(r14); 239344f0eee88ff00398ff7f715fab053374d808c90dSteve Block push(r15); 2394e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch STATIC_ASSERT(11 == kNumSafepointSavedRegisters); 2395e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Use lea for symmetry with Popad. 2396e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int sp_delta = 2397e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch (kNumSafepointRegisters - kNumSafepointSavedRegisters) * kPointerSize; 2398e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch lea(rsp, Operand(rsp, -sp_delta)); 23991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 24001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 24011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 24021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::Popad() { 2403e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Popad must not change the flags, so use lea instead of addq. 2404e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int sp_delta = 2405e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch (kNumSafepointRegisters - kNumSafepointSavedRegisters) * kPointerSize; 2406e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch lea(rsp, Operand(rsp, sp_delta)); 240744f0eee88ff00398ff7f715fab053374d808c90dSteve Block pop(r15); 24081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block pop(r14); 24091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block pop(r11); 24101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block pop(r9); 24111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block pop(r8); 24121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block pop(rdi); 24131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block pop(rsi); 24141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block pop(rbx); 24151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block pop(rdx); 24161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block pop(rcx); 24171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block pop(rax); 24181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 24191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 24201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 24211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::Dropad() { 2422e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch addq(rsp, Immediate(kNumSafepointRegisters * kPointerSize)); 24231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 24241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 24251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 24261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Order general registers are pushed by Pushad: 242744f0eee88ff00398ff7f715fab053374d808c90dSteve Block// rax, rcx, rdx, rbx, rsi, rdi, r8, r9, r11, r14, r15. 24283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int 24293ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochMacroAssembler::kSafepointPushRegisterIndices[Register::kNumRegisters] = { 24301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 0, 24311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1, 24321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2, 24331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3, 24341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block -1, 24351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block -1, 24361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 4, 24371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 5, 24381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 6, 24391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 7, 24401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block -1, 24411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 8, 24421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block -1, 244344f0eee88ff00398ff7f715fab053374d808c90dSteve Block -1, 244444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 9, 244544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 10 24461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}; 24471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 24481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2449e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Register src) { 2450e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch movq(SafepointRegisterSlot(dst), src); 2451e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2452e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2453e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2454e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) { 2455e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch movq(dst, SafepointRegisterSlot(src)); 2456e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2457e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2458e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2459e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochOperand MacroAssembler::SafepointRegisterSlot(Register reg) { 2460e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return Operand(rsp, SafepointRegisterStackIndex(reg.code()) * kPointerSize); 2461e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2462e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2463e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 24643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::PushTryHandler(StackHandler::Kind kind, 24653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int handler_index) { 2466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Adjust this code if not the case. 246769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); 24683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); 24693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); 24703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); 24713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); 24723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); 24733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 24743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We will build up the handler from the bottom by pushing on the stack. 24753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // First push the frame pointer and context. 24763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (kind == StackHandler::JS_ENTRY) { 24773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The frame pointer does not point to a JS frame so we save NULL for 24783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rbp. We expect the code throwing an exception to check rbp before 24793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // dereferencing it to restore the context. 248085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch push(Immediate(0)); // NULL frame pointer. 248185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch Push(Smi::FromInt(0)); // No context. 24823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 24833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch push(rbp); 24843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch push(rsi); 2485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 24863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 24873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Push the state and the code object. 24883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch unsigned state = 24893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StackHandler::IndexField::encode(handler_index) | 24903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StackHandler::KindField::encode(kind); 24913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch push(Immediate(state)); 24923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Push(CodeObject()); 24933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 24943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Link the current handler as the next handler. 24953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference handler_address(Isolate::kHandlerAddress, isolate()); 24963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch push(ExternalOperand(handler_address)); 24973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set this new handler as the current one. 24983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(ExternalOperand(handler_address), rsp); 2499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2502e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::PopTryHandler() { 25033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); 25043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference handler_address(Isolate::kHandlerAddress, isolate()); 25053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch pop(ExternalOperand(handler_address)); 2506e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke addq(rsp, Immediate(StackHandlerConstants::kSize - kPointerSize)); 2507e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 2508e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2509e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 25103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::JumpToHandlerEntry() { 25113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Compute the handler entry address and jump to it. The handler table is 25123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a fixed array of (smi-tagged) code offsets. 25133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rax = exception, rdi = code object, rdx = state. 25143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(rbx, FieldOperand(rdi, Code::kHandlerTableOffset)); 25153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch shr(rdx, Immediate(StackHandler::kKindWidth)); 25163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(rdx, FieldOperand(rbx, rdx, times_8, FixedArray::kHeaderSize)); 25173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiToInteger64(rdx, rdx); 25183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lea(rdi, FieldOperand(rdi, rdx, times_1, Code::kHeaderSize)); 25193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch jmp(rdi); 25203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 25213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 25223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2523e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::Throw(Register value) { 252469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Adjust this code if not the case. 252569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); 25263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); 25273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); 25283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); 25293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); 25303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); 25313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 25323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The exception is expected in rax. 2533e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!value.is(rax)) { 2534e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch movq(rax, value); 2535e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 25363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Drop the stack pointer to the top of the top handler. 253785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch ExternalReference handler_address(Isolate::kHandlerAddress, isolate()); 25383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(rsp, ExternalOperand(handler_address)); 25393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Restore the next handler. 25403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch pop(ExternalOperand(handler_address)); 25413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 25423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Remove the code object and state, compute the handler address in rdi. 25433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch pop(rdi); // Code object. 25443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch pop(rdx); // Offset and state. 25453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 25463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Restore the context and frame pointer. 254769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch pop(rsi); // Context. 254869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch pop(rbp); // Frame pointer. 2549e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 255069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // If the handler is a JS frame, restore the context to the frame. 25513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // (kind == ENTRY) == (rbp == 0) == (rsi == 0), so we could test either 25523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rbp or rsi. 2553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label skip; 25543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch testq(rsi, rsi); 25553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(zero, &skip, Label::kNear); 255669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi); 2557e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch bind(&skip); 255869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 25593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JumpToHandlerEntry(); 2560e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2561e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2562e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 25633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::ThrowUncatchable(Register value) { 256469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Adjust this code if not the case. 256569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); 25663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); 25673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); 25683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); 25693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); 25703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); 25713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 25723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The exception is expected in rax. 25735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (!value.is(rax)) { 2574592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch movq(rax, value); 2575e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 25763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Drop the stack pointer to the top of the top stack handler. 2577592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ExternalReference handler_address(Isolate::kHandlerAddress, isolate()); 2578592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Load(rsp, handler_address); 2579e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 25803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Unwind the handlers until the top ENTRY handler is found. 25813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label fetch_next, check_kind; 25823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch jmp(&check_kind, Label::kNear); 25833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&fetch_next); 25843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(rsp, Operand(rsp, StackHandlerConstants::kNextOffset)); 2585e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 25863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&check_kind); 25873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(StackHandler::JS_ENTRY == 0); 25883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch testl(Operand(rsp, StackHandlerConstants::kStateOffset), 25893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(StackHandler::KindField::kMask)); 25903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(not_zero, &fetch_next); 2591592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 25923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set the top handler address to next handler past the top ENTRY handler. 25933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch pop(ExternalOperand(handler_address)); 2594592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 25953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Remove the code object and state, compute the handler address in rdi. 25963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch pop(rdi); // Code object. 25973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch pop(rdx); // Offset and state. 2598592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 25993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Clear the context pointer and frame pointer (0 was saved in the handler). 26003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch pop(rsi); 26013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch pop(rbp); 2602592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 26033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JumpToHandlerEntry(); 2604e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2605e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2606e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Ret() { 2608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ret(0); 2609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 26121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::Ret(int bytes_dropped, Register scratch) { 26131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (is_uint16(bytes_dropped)) { 26141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ret(bytes_dropped); 26151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 26161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block pop(scratch); 26171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block addq(rsp, Immediate(bytes_dropped)); 26181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block push(scratch); 26191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ret(0); 26201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 26211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 26221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 26231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::FCmp() { 26253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block fucomip(); 26268defd9ff6930b4e24729971a61cf7469daf119beSteve Block fstp(0); 2627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpObjectType(Register heap_object, 2631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstanceType type, 2632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register map) { 2633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(map, FieldOperand(heap_object, HeapObject::kMapOffset)); 2634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CmpInstanceType(map, type); 2635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpInstanceType(Register map, InstanceType type) { 2639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpb(FieldOperand(map, Map::kInstanceTypeOffset), 2640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(static_cast<int8_t>(type))); 2641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 26443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::CheckFastElements(Register map, 26453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label* fail, 26463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label::Distance distance) { 26473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS == 0); 26483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(FAST_ELEMENTS == 1); 26493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmpb(FieldOperand(map, Map::kBitField2Offset), 26503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(Map::kMaximumBitField2FastElementValue)); 26513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(above, fail, distance); 26523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 26533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 26543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 26553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckFastObjectElements(Register map, 26563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* fail, 26573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance distance) { 26583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS == 0); 26593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(FAST_ELEMENTS == 1); 26603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmpb(FieldOperand(map, Map::kBitField2Offset), 26613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(Map::kMaximumBitField2FastSmiOnlyElementValue)); 26623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(below_equal, fail, distance); 2663592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch cmpb(FieldOperand(map, Map::kBitField2Offset), 2664592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Immediate(Map::kMaximumBitField2FastElementValue)); 2665592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch j(above, fail, distance); 2666592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch} 2667592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 2668592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 26693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckFastSmiOnlyElements(Register map, 26703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* fail, 26713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance distance) { 26723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS == 0); 26733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmpb(FieldOperand(map, Map::kBitField2Offset), 26743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(Map::kMaximumBitField2FastSmiOnlyElementValue)); 26753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(above, fail, distance); 26763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 26773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 26783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 26793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::StoreNumberToDoubleElements( 26803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register maybe_number, 26813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register elements, 26823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register index, 26833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch XMMRegister xmm_scratch, 26843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* fail) { 26853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label smi_value, is_nan, maybe_nan, not_nan, have_double_value, done; 26863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 26873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JumpIfSmi(maybe_number, &smi_value, Label::kNear); 26883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 26893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckMap(maybe_number, 26903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate()->factory()->heap_number_map(), 26913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch fail, 26923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DONT_DO_SMI_CHECK); 26933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 26943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Double value, canonicalize NaN. 26953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uint32_t offset = HeapNumber::kValueOffset + sizeof(kHoleNanLower32); 26963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmpl(FieldOperand(maybe_number, offset), 26973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(kNaNOrInfinityLowerBoundUpper32)); 26983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(greater_equal, &maybe_nan, Label::kNear); 26993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(¬_nan); 27013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movsd(xmm_scratch, FieldOperand(maybe_number, HeapNumber::kValueOffset)); 27023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&have_double_value); 27033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movsd(FieldOperand(elements, index, times_8, FixedDoubleArray::kHeaderSize), 27043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch xmm_scratch); 27053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch jmp(&done); 27063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&maybe_nan); 27083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise 27093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // it's an Infinity, and the non-NaN code path applies. 27103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(greater, &is_nan, Label::kNear); 27113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmpl(FieldOperand(maybe_number, HeapNumber::kValueOffset), Immediate(0)); 27123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(zero, ¬_nan); 27133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&is_nan); 27143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Convert all NaNs to the same canonical NaN value when they are stored in 27153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the double array. 27163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Set(kScratchRegister, BitCast<uint64_t>( 27173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedDoubleArray::canonical_not_the_hole_nan_as_double())); 27183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(xmm_scratch, kScratchRegister); 27193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch jmp(&have_double_value, Label::kNear); 27203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&smi_value); 27223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Value is a smi. convert to a double and store. 27233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Preserve original value. 27243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiToInteger32(kScratchRegister, maybe_number); 27253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cvtlsi2sd(xmm_scratch, kScratchRegister); 27263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movsd(FieldOperand(elements, index, times_8, FixedDoubleArray::kHeaderSize), 27273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch xmm_scratch); 27283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&done); 27293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 27303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CompareMap(Register obj, 27333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> map, 27343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* early_success, 27353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompareMapMode mode) { 27363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Cmp(FieldOperand(obj, HeapObject::kMapOffset), map); 27373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (mode == ALLOW_ELEMENT_TRANSITION_MAPS) { 27383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Map* transitioned_fast_element_map( 27393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch map->LookupElementsTransitionMap(FAST_ELEMENTS, NULL)); 27403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(transitioned_fast_element_map == NULL || 27413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch map->elements_kind() != FAST_ELEMENTS); 27423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (transitioned_fast_element_map != NULL) { 27433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(equal, early_success, Label::kNear); 27443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Cmp(FieldOperand(obj, HeapObject::kMapOffset), 27453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map>(transitioned_fast_element_map)); 27463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 27473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Map* transitioned_double_map( 27493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch map->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, NULL)); 27503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(transitioned_double_map == NULL || 27513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch map->elements_kind() == FAST_SMI_ONLY_ELEMENTS); 27523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (transitioned_double_map != NULL) { 27533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(equal, early_success, Label::kNear); 27543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Cmp(FieldOperand(obj, HeapObject::kMapOffset), 27553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map>(transitioned_double_map)); 27563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 27573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 27583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 27593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::CheckMap(Register obj, 27623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Handle<Map> map, 27633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Label* fail, 27643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiCheckType smi_check_type, 27653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompareMapMode mode) { 2766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (smi_check_type == DO_SMI_CHECK) { 27673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu JumpIfSmi(obj, fail); 27683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 27693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label success; 27713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompareMap(obj, map, &success, mode); 27723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu j(not_equal, fail); 27733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&success); 27743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 27753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 27763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2777257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::ClampUint8(Register reg) { 2778257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 2779257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch testl(reg, Immediate(0xFFFFFF00)); 2780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(zero, &done, Label::kNear); 2781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch setcc(negative, reg); // 1 if negative, 0 if positive. 2782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch decb(reg); // 0 if negative, 255 if positive. 2783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bind(&done); 2784257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 2785257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2787257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::ClampDoubleToUint8(XMMRegister input_reg, 2788257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch XMMRegister temp_xmm_reg, 2789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register result_reg, 2790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register temp_reg) { 2791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 2792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Set(result_reg, 0); 2793257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch xorps(temp_xmm_reg, temp_xmm_reg); 2794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ucomisd(input_reg, temp_xmm_reg); 2795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(below, &done, Label::kNear); 2796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch uint64_t one_half = BitCast<uint64_t, double>(0.5); 2797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Set(temp_reg, one_half); 2798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(temp_xmm_reg, temp_reg); 2799257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch addsd(temp_xmm_reg, input_reg); 2800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cvttsd2si(result_reg, temp_xmm_reg); 2801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch testl(result_reg, Immediate(0xFFFFFF00)); 2802257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(zero, &done, Label::kNear); 2803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Set(result_reg, 255); 2804257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bind(&done); 2805257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 2806257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2807257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2808257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::LoadInstanceDescriptors(Register map, 2809257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register descriptors) { 2810257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(descriptors, FieldOperand(map, 2811257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Map::kInstanceDescriptorsOrBitField3Offset)); 2812257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label not_smi; 2813257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch JumpIfNotSmi(descriptors, ¬_smi, Label::kNear); 2814257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Move(descriptors, isolate()->factory()->empty_descriptor_array()); 2815257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bind(¬_smi); 2816257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 2817257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2818257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2819257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::DispatchMap(Register obj, 2820257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Map> map, 2821257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> success, 2822257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SmiCheckType smi_check_type) { 2823257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label fail; 2824257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (smi_check_type == DO_SMI_CHECK) { 2825257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch JumpIfSmi(obj, &fail); 2826257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2827257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Cmp(FieldOperand(obj, HeapObject::kMapOffset), map); 2828257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(equal, success, RelocInfo::CODE_TARGET); 2829257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2830257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bind(&fail); 2831257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 2832257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2833257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid MacroAssembler::AbortIfNotNumber(Register object) { 2835257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label ok; 2836402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Condition is_smi = CheckSmi(object); 2837257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(is_smi, &ok, Label::kNear); 2838402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Cmp(FieldOperand(object, HeapObject::kMapOffset), 2839257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch isolate()->factory()->heap_number_map()); 2840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Assert(equal, "Operand not a number"); 2841402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu bind(&ok); 2842402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 2843402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 2844402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 2845756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid MacroAssembler::AbortIfSmi(Register object) { 2846756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Condition is_smi = CheckSmi(object); 2847756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Assert(NegateCondition(is_smi), "Operand is a smi"); 2848756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick} 2849756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 2850756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 2851f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid MacroAssembler::AbortIfNotSmi(Register object) { 285244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Condition is_smi = CheckSmi(object); 285344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Assert(is_smi, "Operand is not a smi"); 285444f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 285544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 285644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 285744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::AbortIfNotSmi(const Operand& object) { 28586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Condition is_smi = CheckSmi(object); 2859756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Assert(is_smi, "Operand is not a smi"); 28606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 28616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 28626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 28633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::AbortIfNotZeroExtended(Register int32_register) { 28643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!int32_register.is(kScratchRegister)); 28653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(kScratchRegister, 0x100000000l, RelocInfo::NONE); 28663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmpq(kScratchRegister, int32_register); 28673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Assert(above_equal, "32 bit value in register is not zero-extended"); 28683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 28693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 28703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2871e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::AbortIfNotString(Register object) { 2872e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch testb(object, Immediate(kSmiTagMask)); 2873e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Assert(not_equal, "Operand is not a string"); 2874e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch push(object); 2875e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch movq(object, FieldOperand(object, HeapObject::kMapOffset)); 2876e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CmpInstanceType(object, FIRST_NONSTRING_TYPE); 2877e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch pop(object); 2878e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Assert(below, "Operand is not a string"); 2879e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2880e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2881e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 28829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::AbortIfNotRootValue(Register src, 28839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Heap::RootListIndex root_value_index, 28849dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const char* message) { 28859dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen ASSERT(!src.is(kScratchRegister)); 28869dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen LoadRoot(kScratchRegister, root_value_index); 28879dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen cmpq(src, kScratchRegister); 28889dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Check(equal, message); 28899dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 28909dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 28919dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 28929dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 2893d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeCondition MacroAssembler::IsObjectStringType(Register heap_object, 2894d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Register map, 2895d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Register instance_type) { 2896d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke movq(map, FieldOperand(heap_object, HeapObject::kMapOffset)); 28974515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke movzxbl(instance_type, FieldOperand(map, Map::kInstanceTypeOffset)); 289869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kNotStringTag != 0); 2899d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke testb(instance_type, Immediate(kIsNotStringMask)); 2900d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return zero; 2901d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 2902d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 2903d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 2904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::TryGetFunctionPrototype(Register function, 2905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 29063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss, 29073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool miss_on_bound_function) { 2908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 2909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block testl(function, Immediate(kSmiTagMask)); 2910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(zero, miss); 2911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the function really is a function. 2913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CmpObjectType(function, JS_FUNCTION_TYPE, result); 2914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(not_equal, miss); 2915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (miss_on_bound_function) { 29173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(kScratchRegister, 29183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldOperand(function, JSFunction::kSharedFunctionInfoOffset)); 29193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // It's not smi-tagged (stored in the top half of a smi-tagged 8-byte 29203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // field). 29213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TestBit(FieldOperand(kScratchRegister, 29223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SharedFunctionInfo::kCompilerHintsOffset), 29233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SharedFunctionInfo::kBoundFunction); 29243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(not_zero, miss); 29253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 29263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure that the function has an instance prototype. 2928257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label non_instance; 2929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block testb(FieldOperand(result, Map::kBitFieldOffset), 2930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(1 << Map::kHasNonInstancePrototype)); 2931257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(not_zero, &non_instance, Label::kNear); 2932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the prototype or initial map from the function. 2934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(result, 2935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 2936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the prototype or initial map is the hole, don't return it and 2938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // simply miss the cache instead. This will allow us to allocate a 2939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // prototype object on-demand in the runtime system. 2940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CompareRoot(result, Heap::kTheHoleValueRootIndex); 2941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(equal, miss); 2942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the function does not have an initial map, we're done. 2944257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 2945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CmpObjectType(result, MAP_TYPE, kScratchRegister); 2946257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(not_equal, &done, Label::kNear); 2947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the prototype from the initial map. 2949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(result, FieldOperand(result, Map::kPrototypeOffset)); 2950257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch jmp(&done, Label::kNear); 2951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Non-instance prototype: Fetch prototype from constructor field 2953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // in initial map. 2954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&non_instance); 2955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(result, FieldOperand(result, Map::kConstructorOffset)); 2956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // All done. 2958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&done); 2959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SetCounter(StatsCounter* counter, int value) { 2963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_native_code_counters && counter->Enabled()) { 296444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Operand counter_operand = ExternalOperand(ExternalReference(counter)); 29658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch movl(counter_operand, Immediate(value)); 2966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::IncrementCounter(StatsCounter* counter, int value) { 2971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(value > 0); 2972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_native_code_counters && counter->Enabled()) { 297344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Operand counter_operand = ExternalOperand(ExternalReference(counter)); 2974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (value == 1) { 297544f0eee88ff00398ff7f715fab053374d808c90dSteve Block incl(counter_operand); 2976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 297744f0eee88ff00398ff7f715fab053374d808c90dSteve Block addl(counter_operand, Immediate(value)); 2978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::DecrementCounter(StatsCounter* counter, int value) { 2984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(value > 0); 2985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_native_code_counters && counter->Enabled()) { 298644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Operand counter_operand = ExternalOperand(ExternalReference(counter)); 2987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (value == 1) { 298844f0eee88ff00398ff7f715fab053374d808c90dSteve Block decl(counter_operand); 2989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 299044f0eee88ff00398ff7f715fab053374d808c90dSteve Block subl(counter_operand, Immediate(value)); 2991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 299680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#ifdef ENABLE_DEBUGGER_SUPPORT 2997402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::DebugBreak() { 29989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Set(rax, 0); // No arguments. 299944f0eee88ff00398ff7f715fab053374d808c90dSteve Block LoadAddress(rbx, ExternalReference(Runtime::kDebugBreak, isolate())); 3000402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu CEntryStub ces(1); 30013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(AllowThisStubCall(&ces)); 3002402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Call(ces.GetCode(), RelocInfo::DEBUG_BREAK); 3003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3004402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#endif // ENABLE_DEBUGGER_SUPPORT 3005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3007257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SetCallKind(Register dst, CallKind call_kind) { 3008257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This macro takes the dst register to make the code more readable 3009257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // at the call sites. However, the dst register has to be rcx to 3010257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // follow the calling convention which requires the call type to be 3011257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // in rcx. 3012257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(dst.is(rcx)); 3013257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (call_kind == CALL_AS_FUNCTION) { 3014257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch LoadSmiConstant(dst, Smi::FromInt(1)); 3015257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3016257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch LoadSmiConstant(dst, Smi::FromInt(0)); 3017257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3018257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3019257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeCode(Register code, 3022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& expected, 3023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 3024e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch InvokeFlag flag, 3025257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const CallWrapper& call_wrapper, 3026257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKind call_kind) { 30273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // You can't call a function without a valid frame. 30283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(flag == JUMP_FUNCTION || has_frame()); 30293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3030257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 30313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool definitely_mismatches = false; 3032e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch InvokePrologue(expected, 3033e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch actual, 3034e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Handle<Code>::null(), 3035e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch code, 3036e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch &done, 30373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &definitely_mismatches, 3038e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch flag, 3039257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::kNear, 3040257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch call_wrapper, 3041257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch call_kind); 30423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!definitely_mismatches) { 30433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (flag == CALL_FUNCTION) { 30443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch call_wrapper.BeforeCall(CallSize(code)); 30453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SetCallKind(rcx, call_kind); 30463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch call(code); 30473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch call_wrapper.AfterCall(); 30483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 30493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(flag == JUMP_FUNCTION); 30503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SetCallKind(rcx, call_kind); 30513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch jmp(code); 30523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 30533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&done); 3054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeCode(Handle<Code> code, 3059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& expected, 3060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 3061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::Mode rmode, 3062e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch InvokeFlag flag, 3063257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const CallWrapper& call_wrapper, 3064257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKind call_kind) { 30653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // You can't call a function without a valid frame. 30663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(flag == JUMP_FUNCTION || has_frame()); 30673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3068257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 30693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool definitely_mismatches = false; 3070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register dummy = rax; 3071e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch InvokePrologue(expected, 3072e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch actual, 3073e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch code, 3074e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch dummy, 3075e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch &done, 30763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &definitely_mismatches, 3077e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch flag, 3078257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::kNear, 3079257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch call_wrapper, 3080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch call_kind); 30813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!definitely_mismatches) { 30823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (flag == CALL_FUNCTION) { 30833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch call_wrapper.BeforeCall(CallSize(code)); 30843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SetCallKind(rcx, call_kind); 30853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Call(code, rmode); 30863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch call_wrapper.AfterCall(); 30873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 30883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(flag == JUMP_FUNCTION); 30893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SetCallKind(rcx, call_kind); 30903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Jump(code, rmode); 30913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 30923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&done); 3093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeFunction(Register function, 3098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 3099e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch InvokeFlag flag, 3100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const CallWrapper& call_wrapper, 3101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKind call_kind) { 31023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // You can't call a function without a valid frame. 31033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(flag == JUMP_FUNCTION || has_frame()); 31043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(function.is(rdi)); 3106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rdx, FieldOperand(function, JSFunction::kSharedFunctionInfoOffset)); 3107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rsi, FieldOperand(function, JSFunction::kContextOffset)); 3108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movsxlq(rbx, 3109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FieldOperand(rdx, SharedFunctionInfo::kFormalParameterCountOffset)); 3110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Advances rdx to the end of the Code object header, to the start of 3111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the executable code. 3112791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); 3113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ParameterCount expected(rbx); 3115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch InvokeCode(rdx, expected, actual, flag, call_wrapper, call_kind); 3116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 31193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::InvokeFunction(Handle<JSFunction> function, 3120402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu const ParameterCount& actual, 3121e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch InvokeFlag flag, 3122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const CallWrapper& call_wrapper, 3123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKind call_kind) { 31243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // You can't call a function without a valid frame. 31253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(flag == JUMP_FUNCTION || has_frame()); 31263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3127402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Get the function and setup the context. 31283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LoadHeapObject(rdi, function); 3129402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); 3130402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 31313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We call indirectly through the code field in the function to 31323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // allow recompilation to take effect without changing any of the 31333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // call sites. 31343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); 31353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ParameterCount expected(function->shared()->formal_parameter_count()); 31363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch InvokeCode(rdx, expected, actual, flag, call_wrapper, call_kind); 3137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::InvokePrologue(const ParameterCount& expected, 3141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const ParameterCount& actual, 3142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> code_constant, 3143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register code_register, 3144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* done, 31453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool* definitely_mismatches, 3146257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch InvokeFlag flag, 3147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump, 3148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const CallWrapper& call_wrapper, 3149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKind call_kind) { 3150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool definitely_matches = false; 31513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *definitely_mismatches = false; 3152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label invoke; 3153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (expected.is_immediate()) { 3154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(actual.is_immediate()); 3155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (expected.immediate() == actual.immediate()) { 3156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch definitely_matches = true; 3157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Set(rax, actual.immediate()); 3159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (expected.immediate() == 3160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SharedFunctionInfo::kDontAdaptArgumentsSentinel) { 3161257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Don't worry about adapting arguments for built-ins that 3162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // don't want that done. Skip adaption code by making it look 3163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // like we have a match between expected and actual number of 3164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // arguments. 3165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch definitely_matches = true; 3166257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 31673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *definitely_mismatches = true; 3168257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Set(rbx, expected.immediate()); 3169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (actual.is_immediate()) { 3173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Expected is in register, actual is immediate. This is the 3174257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // case when we invoke function values without going through the 3175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // IC mechanism. 3176257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cmpq(expected.reg(), Immediate(actual.immediate())); 3177257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(equal, &invoke, Label::kNear); 3178257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(expected.reg().is(rbx)); 3179257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Set(rax, actual.immediate()); 3180257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else if (!expected.reg().is(actual.reg())) { 3181257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Both expected and actual are in (different) registers. This 3182257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // is the case when we invoke functions using call and apply. 3183257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cmpq(expected.reg(), actual.reg()); 3184257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(equal, &invoke, Label::kNear); 3185257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(actual.reg().is(rax)); 3186257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(expected.reg().is(rbx)); 3187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3188257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3189257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3190257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!definitely_matches) { 3191257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> adaptor = isolate()->builtins()->ArgumentsAdaptorTrampoline(); 3192257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!code_constant.is_null()) { 3193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(rdx, code_constant, RelocInfo::EMBEDDED_OBJECT); 3194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch addq(rdx, Immediate(Code::kHeaderSize - kHeapObjectTag)); 3195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else if (!code_register.is(rdx)) { 3196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movq(rdx, code_register); 3197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3199257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (flag == CALL_FUNCTION) { 3200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch call_wrapper.BeforeCall(CallSize(adaptor)); 3201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SetCallKind(rcx, call_kind); 3202257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Call(adaptor, RelocInfo::CODE_TARGET); 3203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch call_wrapper.AfterCall(); 32043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!*definitely_mismatches) { 32053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch jmp(done, near_jump); 32063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3207257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3208257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SetCallKind(rcx, call_kind); 3209257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Jump(adaptor, RelocInfo::CODE_TARGET); 3210257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3211257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bind(&invoke); 32121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 3213402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 3214402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 3215402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 3216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::EnterFrame(StackFrame::Type type) { 3217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(rbp); 3218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rbp, rsp); 3219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(rsi); // Context. 32203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Push(Smi::FromInt(type)); 3221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT); 3222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(kScratchRegister); 322344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 3224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, 3225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch isolate()->factory()->undefined_value(), 3226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::EMBEDDED_OBJECT); 3227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(Operand(rsp, 0), kScratchRegister); 3228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(not_equal, "code object not properly patched"); 3229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LeaveFrame(StackFrame::Type type) { 323444f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 32353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Move(kScratchRegister, Smi::FromInt(type)); 3236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(Operand(rbp, StandardFrameConstants::kMarkerOffset), kScratchRegister); 3237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(equal, "stack frame types must match"); 3238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rsp, rbp); 3240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pop(rbp); 3241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 324480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::EnterExitFramePrologue(bool save_rax) { 32453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the frame structure on the stack. 3246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // All constants are relative to the frame pointer of the exit frame. 3247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize); 3248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize); 3249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize); 3250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(rbp); 3251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rbp, rsp); 3252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 325380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Reserve room for entry stack pointer and push the code object. 32543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize); 3255402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu push(Immediate(0)); // Saved entry sp, patched before call. 3256402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT); 3257402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu push(kScratchRegister); // Accessed from EditFrame::code_slot. 3258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save the frame pointer and the context in top. 3260bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if (save_rax) { 326144f0eee88ff00398ff7f715fab053374d808c90dSteve Block movq(r14, rax); // Backup rax in callee-save register. 3262bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } 3263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3264589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Store(ExternalReference(Isolate::kCEntryFPAddress, isolate()), rbp); 3265589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Store(ExternalReference(Isolate::kContextAddress, isolate()), rsi); 3266bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 3267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 32688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 32691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::EnterExitFrameEpilogue(int arg_stack_space, 32701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block bool save_doubles) { 3271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef _WIN64 32721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block const int kShadowSpace = 4; 32731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block arg_stack_space += kShadowSpace; 3274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 32751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Optionally save all XMM registers. 32761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (save_doubles) { 32771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int space = XMMRegister::kNumRegisters * kDoubleSize + 32781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block arg_stack_space * kPointerSize; 32791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block subq(rsp, Immediate(space)); 32801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int offset = -2 * kPointerSize; 32811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; i++) { 32821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block XMMRegister reg = XMMRegister::FromAllocationIndex(i); 32831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block movsd(Operand(rbp, offset - ((i + 1) * kDoubleSize)), reg); 32841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 32851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (arg_stack_space > 0) { 32868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang subq(rsp, Immediate(arg_stack_space * kPointerSize)); 32878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 3288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the required frame alignment for the OS. 329044f0eee88ff00398ff7f715fab053374d808c90dSteve Block const int kFrameAlignment = OS::ActivationFrameAlignment(); 3291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (kFrameAlignment > 0) { 3292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(IsPowerOf2(kFrameAlignment)); 32938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(is_int8(kFrameAlignment)); 32948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch and_(rsp, Immediate(-kFrameAlignment)); 3295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the saved entry sp. 3298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(Operand(rbp, ExitFrameConstants::kSPOffset), rsp); 3299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 33021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::EnterExitFrame(int arg_stack_space, bool save_doubles) { 330380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen EnterExitFramePrologue(true); 3304bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 33053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up argv in callee-saved register r15. It is reused in LeaveExitFrame, 3306bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // so it must be retained across the C-call. 3307bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; 330844f0eee88ff00398ff7f715fab053374d808c90dSteve Block lea(r15, Operand(rbp, r14, times_pointer_size, offset)); 3309bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 33101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EnterExitFrameEpilogue(arg_stack_space, save_doubles); 3311bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 3312bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 3313bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 33148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid MacroAssembler::EnterApiExitFrame(int arg_stack_space) { 331580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen EnterExitFramePrologue(false); 33161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EnterExitFrameEpilogue(arg_stack_space, false); 3317bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 3318bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 3319bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 33201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::LeaveExitFrame(bool save_doubles) { 3321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Registers: 332244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // r15 : argv 33231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (save_doubles) { 33241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int offset = -2 * kPointerSize; 33251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; i++) { 33261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block XMMRegister reg = XMMRegister::FromAllocationIndex(i); 33271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block movsd(reg, Operand(rbp, offset - ((i + 1) * kDoubleSize))); 33281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 33291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 3330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the return address from the stack and restore the frame pointer. 3331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rcx, Operand(rbp, 1 * kPointerSize)); 3332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(rbp, Operand(rbp, 0 * kPointerSize)); 3333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 33341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Drop everything up to and including the arguments and the receiver 3335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // from the caller stack. 333644f0eee88ff00398ff7f715fab053374d808c90dSteve Block lea(rsp, Operand(r15, 1 * kPointerSize)); 3337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 33388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Push the return address to get ready to return. 33398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang push(rcx); 33408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 33418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang LeaveExitFrameEpilogue(); 33428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang} 33438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 33448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 33458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid MacroAssembler::LeaveApiExitFrame() { 33468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang movq(rsp, rbp); 33478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang pop(rbp); 33488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 33498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang LeaveExitFrameEpilogue(); 33508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang} 33518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 33528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 33538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid MacroAssembler::LeaveExitFrameEpilogue() { 3354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore current context from top and clear it in debug mode. 3355589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ExternalReference context_address(Isolate::kContextAddress, isolate()); 335644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Operand context_operand = ExternalOperand(context_address); 335744f0eee88ff00398ff7f715fab053374d808c90dSteve Block movq(rsi, context_operand); 3358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 335944f0eee88ff00398ff7f715fab053374d808c90dSteve Block movq(context_operand, Immediate(0)); 3360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 3361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Clear the top frame. 3363589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress, 336444f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()); 336544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Operand c_entry_fp_operand = ExternalOperand(c_entry_fp_address); 336644f0eee88ff00398ff7f715fab053374d808c90dSteve Block movq(c_entry_fp_operand, Immediate(0)); 3367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, 3371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 3372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 3373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label same_contexts; 3374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!holder_reg.is(scratch)); 3376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!scratch.is(kScratchRegister)); 3377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load current lexical context from the stack frame. 3378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(scratch, Operand(rbp, StandardFrameConstants::kContextOffset)); 3379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // When generating debug code, make sure the lexical context is set. 338144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 3382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(scratch, Immediate(0)); 3383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(not_equal, "we should not have an empty lexical context"); 3384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the global context of the current context. 3386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; 3387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(scratch, FieldOperand(scratch, offset)); 3388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(scratch, FieldOperand(scratch, GlobalObject::kGlobalContextOffset)); 3389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check the context is a global context. 339144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 3392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Cmp(FieldOperand(scratch, HeapObject::kMapOffset), 3393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch isolate()->factory()->global_context_map()); 3394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(equal, "JSGlobalObject::global_context should be a global context."); 3395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if both contexts are the same. 3398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(scratch, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); 3399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(equal, &same_contexts); 3400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compare security tokens. 3402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the security token in the calling global object is 3403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // compatible with the security token in the receiving global 3404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // object. 3405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check the context is a global context. 340744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 3408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Preserve original value of holder_reg. 3409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(holder_reg); 3410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(holder_reg, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); 3411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CompareRoot(holder_reg, Heap::kNullValueRootIndex); 3412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(not_equal, "JSGlobalProxy::context() should not be null."); 3413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Read the first word and compare to global_context_map(), 3415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(holder_reg, FieldOperand(holder_reg, HeapObject::kMapOffset)); 3416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CompareRoot(holder_reg, Heap::kGlobalContextMapRootIndex); 3417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(equal, "JSGlobalObject::global_context should be a global context."); 3418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pop(holder_reg); 3419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(kScratchRegister, 3422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); 34233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int token_offset = 34243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Context::kHeaderSize + Context::SECURITY_TOKEN_INDEX * kPointerSize; 3425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(scratch, FieldOperand(scratch, token_offset)); 3426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpq(scratch, FieldOperand(kScratchRegister, token_offset)); 3427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(not_equal, miss); 3428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&same_contexts); 3430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3433c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdochvoid MacroAssembler::GetNumberHash(Register r0, Register scratch) { 3434c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // First of all we assign the hash seed to scratch. 3435c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch LoadRoot(scratch, Heap::kHashSeedRootIndex); 3436c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch SmiToInteger32(scratch, scratch); 3437c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 3438c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // Xor original key with a seed. 3439c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch xorl(r0, scratch); 3440c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 3441c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // Compute the hash code from the untagged key. This must be kept in sync 3442c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // with ComputeIntegerHash in utils.h. 3443c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // 3444c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // hash = ~hash + (hash << 15); 3445c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch movl(scratch, r0); 3446c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch notl(r0); 3447c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch shll(scratch, Immediate(15)); 3448c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch addl(r0, scratch); 3449c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // hash = hash ^ (hash >> 12); 3450c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch movl(scratch, r0); 3451c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch shrl(scratch, Immediate(12)); 3452c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch xorl(r0, scratch); 3453c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // hash = hash + (hash << 2); 3454c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch leal(r0, Operand(r0, r0, times_4, 0)); 3455c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // hash = hash ^ (hash >> 4); 3456c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch movl(scratch, r0); 3457c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch shrl(scratch, Immediate(4)); 3458c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch xorl(r0, scratch); 3459c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // hash = hash * 2057; 3460c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch imull(r0, r0, Immediate(2057)); 3461c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // hash = hash ^ (hash >> 16); 3462c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch movl(scratch, r0); 3463c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch shrl(scratch, Immediate(16)); 3464c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch xorl(r0, scratch); 3465c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch} 3466c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 3467c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 3468c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 34693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::LoadFromNumberDictionary(Label* miss, 34703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register elements, 34713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register key, 34723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register r0, 34733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register r1, 34743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register r2, 34753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register result) { 34763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Register use: 34773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // 34783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // elements - holds the slow-case elements of the receiver on entry. 34793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Unchanged unless 'result' is the same register. 34803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // 34813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // key - holds the smi key on entry. 34823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Unchanged unless 'result' is the same register. 34833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // 34843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Scratch registers: 34853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // 34863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // r0 - holds the untagged key on entry and holds the hash once computed. 34873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // 34883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // r1 - used to hold the capacity mask of the dictionary 34893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // 34903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // r2 - used for the index into the dictionary. 34913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // 34923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // result - holds the result on exit if the load succeeded. 34933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Allowed to be the same as 'key' or 'result'. 34943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Unchanged on bailout so 'key' or 'result' can be used 34953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // in further computation. 34963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 34973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label done; 34983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 3499c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch GetNumberHash(r0, r1); 35003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 35013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Compute capacity mask. 3502c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch SmiToInteger32(r1, FieldOperand(elements, 3503c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch SeededNumberDictionary::kCapacityOffset)); 35043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch decl(r1); 35053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 35063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Generate an unrolled loop that performs a few probes before giving up. 35073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch const int kProbes = 4; 35083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch for (int i = 0; i < kProbes; i++) { 35093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Use r2 for index calculations and keep the hash intact in r0. 35103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch movq(r2, r0); 35113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Compute the masked index: (hash + i + i * i) & mask. 35123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (i > 0) { 3513c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch addl(r2, Immediate(SeededNumberDictionary::GetProbeOffset(i))); 35143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 35153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch and_(r2, r1); 35163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 35173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Scale the index by multiplying by the entry size. 3518c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch ASSERT(SeededNumberDictionary::kEntrySize == 3); 35193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3 35203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 35213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check if the key matches. 35223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch cmpq(key, FieldOperand(elements, 35233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch r2, 35243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch times_pointer_size, 3525c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch SeededNumberDictionary::kElementsStartOffset)); 35263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (i != (kProbes - 1)) { 35273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch j(equal, &done); 35283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 35293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch j(not_equal, miss); 35303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 35313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 35323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 35333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bind(&done); 35343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check that the value is a normal propety. 35353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch const int kDetailsOffset = 3536c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize; 35373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT_EQ(NORMAL, 0); 35383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset), 3539589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Smi::FromInt(PropertyDetails::TypeField::kMask)); 35403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch j(not_zero, miss); 35413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 35423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Get the value at the masked, scaled index. 35433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch const int kValueOffset = 3544c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch SeededNumberDictionary::kElementsStartOffset + kPointerSize; 35453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch movq(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); 35463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 35473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 35483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 3549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LoadAllocationTopHelper(Register result, 3550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 3551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags) { 3552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_top = 355344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::new_space_allocation_top_address(isolate()); 3554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Just return if allocation top is already known. 3556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((flags & RESULT_CONTAINS_TOP) != 0) { 3557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // No use of scratch if allocation top is provided. 35586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(!scratch.is_valid()); 3559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 3560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Assert that result actually contains top on entry. 356144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Operand top_operand = ExternalOperand(new_space_allocation_top); 356244f0eee88ff00398ff7f715fab053374d808c90dSteve Block cmpq(result, top_operand); 3563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(equal, "Unexpected allocation top"); 3564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 3565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 3566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 35686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Move address of new object to result. Use scratch register if available, 35696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // and keep address in scratch until call to UpdateAllocationTopHelper. 35706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (scratch.is_valid()) { 357144f0eee88ff00398ff7f715fab053374d808c90dSteve Block LoadAddress(scratch, new_space_allocation_top); 3572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(result, Operand(scratch, 0)); 35736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 357444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Load(result, new_space_allocation_top); 3575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::UpdateAllocationTopHelper(Register result_end, 3580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch) { 358144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 3582d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block testq(result_end, Immediate(kObjectAlignmentMask)); 3583d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Check(zero, "Unaligned allocation in new space"); 3584d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3585d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_top = 358744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::new_space_allocation_top_address(isolate()); 3588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update new top. 359044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (scratch.is_valid()) { 359144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Scratch already contains address of allocation top. 359244f0eee88ff00398ff7f715fab053374d808c90dSteve Block movq(Operand(scratch, 0), result_end); 3593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 359444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Store(new_space_allocation_top, result_end); 3595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(int object_size, 3600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 3601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result_end, 3602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 3603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required, 3604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags) { 36055913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!FLAG_inline_new) { 360644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 36075913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // Trash the registers to simulate an allocation failure. 36085913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck movl(result, Immediate(0x7091)); 36095913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (result_end.is_valid()) { 36105913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck movl(result_end, Immediate(0x7191)); 36115913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 36125913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (scratch.is_valid()) { 36135913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck movl(scratch, Immediate(0x7291)); 36145913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 36155913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 36165913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck jmp(gc_required); 36175913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck return; 36185913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 3619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!result.is(result_end)); 3620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load address of new object into result. 36228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang LoadAllocationTopHelper(result, scratch, flags); 3623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate new top and bail out if new space is exhausted. 3625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_limit = 362644f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::new_space_allocation_limit_address(isolate()); 36276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 36286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register top_reg = result_end.is_valid() ? result_end : result; 36296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 36301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (!top_reg.is(result)) { 36311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block movq(top_reg, result); 36326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 36331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block addq(top_reg, Immediate(object_size)); 36341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block j(carry, gc_required); 363544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Operand limit_operand = ExternalOperand(new_space_allocation_limit); 363644f0eee88ff00398ff7f715fab053374d808c90dSteve Block cmpq(top_reg, limit_operand); 3637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(above, gc_required); 3638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update allocation top. 36406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block UpdateAllocationTopHelper(top_reg, scratch); 3641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 36426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (top_reg.is(result)) { 36436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if ((flags & TAG_OBJECT) != 0) { 36446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block subq(result, Immediate(object_size - kHeapObjectTag)); 36456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 36466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block subq(result, Immediate(object_size)); 36476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 36486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if ((flags & TAG_OBJECT) != 0) { 36496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Tag the result if requested. 3650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addq(result, Immediate(kHeapObjectTag)); 3651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(int header_size, 3656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ScaleFactor element_size, 3657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register element_count, 3658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 3659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result_end, 3660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 3661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required, 3662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags) { 36635913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!FLAG_inline_new) { 366444f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 36655913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // Trash the registers to simulate an allocation failure. 36665913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck movl(result, Immediate(0x7091)); 36675913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck movl(result_end, Immediate(0x7191)); 36685913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (scratch.is_valid()) { 36695913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck movl(scratch, Immediate(0x7291)); 36705913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 36715913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // Register element_count is not modified by the function. 36725913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 36735913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck jmp(gc_required); 36745913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck return; 36755913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 3676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!result.is(result_end)); 3677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load address of new object into result. 36798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang LoadAllocationTopHelper(result, scratch, flags); 3680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate new top and bail out if new space is exhausted. 3682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_limit = 368344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::new_space_allocation_limit_address(isolate()); 36841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // We assume that element_count*element_size + header_size does not 36861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // overflow. 36871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block lea(result_end, Operand(element_count, element_size, header_size)); 36881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block addq(result_end, result); 36891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block j(carry, gc_required); 369044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Operand limit_operand = ExternalOperand(new_space_allocation_limit); 369144f0eee88ff00398ff7f715fab053374d808c90dSteve Block cmpq(result_end, limit_operand); 3692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(above, gc_required); 3693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update allocation top. 3695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UpdateAllocationTopHelper(result_end, scratch); 3696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Tag the result if requested. 3698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((flags & TAG_OBJECT) != 0) { 3699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addq(result, Immediate(kHeapObjectTag)); 3700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(Register object_size, 3705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 3706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result_end, 3707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 3708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required, 3709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags) { 37105913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!FLAG_inline_new) { 371144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 37125913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // Trash the registers to simulate an allocation failure. 37135913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck movl(result, Immediate(0x7091)); 37145913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck movl(result_end, Immediate(0x7191)); 37155913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (scratch.is_valid()) { 37165913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck movl(scratch, Immediate(0x7291)); 37175913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 37185913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // object_size is left unchanged by this function. 37195913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 37205913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck jmp(gc_required); 37215913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck return; 37225913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 37235913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck ASSERT(!result.is(result_end)); 37245913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck 3725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load address of new object into result. 37268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang LoadAllocationTopHelper(result, scratch, flags); 3727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate new top and bail out if new space is exhausted. 3729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_limit = 373044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::new_space_allocation_limit_address(isolate()); 3731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!object_size.is(result_end)) { 3732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movq(result_end, object_size); 3733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addq(result_end, result); 37351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block j(carry, gc_required); 373644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Operand limit_operand = ExternalOperand(new_space_allocation_limit); 373744f0eee88ff00398ff7f715fab053374d808c90dSteve Block cmpq(result_end, limit_operand); 3738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(above, gc_required); 3739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update allocation top. 3741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UpdateAllocationTopHelper(result_end, scratch); 3742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Tag the result if requested. 3744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((flags & TAG_OBJECT) != 0) { 3745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addq(result, Immediate(kHeapObjectTag)); 3746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::UndoAllocationInNewSpace(Register object) { 3751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_top = 375244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::new_space_allocation_top_address(isolate()); 3753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure the object has no tag before resetting top. 3755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block and_(object, Immediate(~kHeapObjectTagMask)); 375644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Operand top_operand = ExternalOperand(new_space_allocation_top); 3757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 375844f0eee88ff00398ff7f715fab053374d808c90dSteve Block cmpq(object, top_operand); 3759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(below, "Undo allocation of non allocated memory"); 3760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 376144f0eee88ff00398ff7f715fab053374d808c90dSteve Block movq(top_operand, object); 3762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 37653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::AllocateHeapNumber(Register result, 37663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register scratch, 37673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label* gc_required) { 37683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Allocate heap number in new space. 37693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block AllocateInNewSpace(HeapNumber::kSize, 37703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block result, 37713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block scratch, 37723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block no_reg, 37733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block gc_required, 37743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block TAG_OBJECT); 37753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 37763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Set the map. 37773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block LoadRoot(kScratchRegister, Heap::kHeapNumberMapRootIndex); 37783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); 37793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 37803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 37813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3782e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::AllocateTwoByteString(Register result, 3783e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register length, 3784e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch1, 3785e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch2, 3786e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch3, 3787e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* gc_required) { 3788e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Calculate the number of bytes needed for the characters in the string while 3789e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // observing object alignment. 37906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int kHeaderAlignment = SeqTwoByteString::kHeaderSize & 37916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block kObjectAlignmentMask; 3792e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(kShortSize == 2); 3793e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // scratch1 = length * 2 + kObjectAlignmentMask. 37946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block lea(scratch1, Operand(length, length, times_1, kObjectAlignmentMask + 37956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block kHeaderAlignment)); 3796e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke and_(scratch1, Immediate(~kObjectAlignmentMask)); 37976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (kHeaderAlignment > 0) { 37986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block subq(scratch1, Immediate(kHeaderAlignment)); 37996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3800e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3801e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Allocate two byte string in new space. 3802e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AllocateInNewSpace(SeqTwoByteString::kHeaderSize, 3803e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke times_1, 3804e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch1, 3805e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke result, 3806e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch2, 3807e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch3, 3808e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke gc_required, 3809e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke TAG_OBJECT); 3810e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3811e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Set the map, length and hash field. 3812e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke LoadRoot(kScratchRegister, Heap::kStringMapRootIndex); 3813e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); 38146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Integer32ToSmi(scratch1, length); 38156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(FieldOperand(result, String::kLengthOffset), scratch1); 38167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch movq(FieldOperand(result, String::kHashFieldOffset), 3817e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Immediate(String::kEmptyHashField)); 3818e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 3819e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3820e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3821e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::AllocateAsciiString(Register result, 3822e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register length, 3823e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch1, 3824e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch2, 3825e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch3, 3826e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* gc_required) { 3827e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Calculate the number of bytes needed for the characters in the string while 3828e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // observing object alignment. 38296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int kHeaderAlignment = SeqAsciiString::kHeaderSize & 38306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block kObjectAlignmentMask; 3831e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movl(scratch1, length); 3832e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(kCharSize == 1); 38336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block addq(scratch1, Immediate(kObjectAlignmentMask + kHeaderAlignment)); 3834e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke and_(scratch1, Immediate(~kObjectAlignmentMask)); 38356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (kHeaderAlignment > 0) { 38366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block subq(scratch1, Immediate(kHeaderAlignment)); 38376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3838e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 38393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Allocate ASCII string in new space. 3840e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AllocateInNewSpace(SeqAsciiString::kHeaderSize, 3841e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke times_1, 3842e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch1, 3843e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke result, 3844e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch2, 3845e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch3, 3846e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke gc_required, 3847e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke TAG_OBJECT); 3848e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3849e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Set the map, length and hash field. 3850e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke LoadRoot(kScratchRegister, Heap::kAsciiStringMapRootIndex); 3851e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); 38526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Integer32ToSmi(scratch1, length); 38536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block movq(FieldOperand(result, String::kLengthOffset), scratch1); 38547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch movq(FieldOperand(result, String::kHashFieldOffset), 3855e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Immediate(String::kEmptyHashField)); 3856e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 3857e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3858e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3859589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid MacroAssembler::AllocateTwoByteConsString(Register result, 3860e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch1, 3861e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch2, 3862e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* gc_required) { 3863e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Allocate heap number in new space. 3864e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AllocateInNewSpace(ConsString::kSize, 3865e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke result, 3866e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch1, 3867e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch2, 3868e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke gc_required, 3869e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke TAG_OBJECT); 3870e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3871e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Set the map. The other fields are left uninitialized. 3872e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke LoadRoot(kScratchRegister, Heap::kConsStringMapRootIndex); 3873e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); 3874e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 3875e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3876e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3877e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::AllocateAsciiConsString(Register result, 3878e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch1, 3879e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch2, 3880e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* gc_required) { 3881e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Allocate heap number in new space. 3882e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AllocateInNewSpace(ConsString::kSize, 3883e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke result, 3884e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch1, 3885e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke scratch2, 3886e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke gc_required, 3887e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke TAG_OBJECT); 3888e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3889e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Set the map. The other fields are left uninitialized. 3890e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke LoadRoot(kScratchRegister, Heap::kConsAsciiStringMapRootIndex); 3891e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); 3892e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 3893e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3894e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3895589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid MacroAssembler::AllocateTwoByteSlicedString(Register result, 3896589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register scratch1, 3897589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register scratch2, 3898589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label* gc_required) { 3899589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Allocate heap number in new space. 3900589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch AllocateInNewSpace(SlicedString::kSize, 3901589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch result, 3902589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch scratch1, 3903589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch scratch2, 3904589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch gc_required, 3905589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch TAG_OBJECT); 3906589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 3907589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Set the map. The other fields are left uninitialized. 3908589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch LoadRoot(kScratchRegister, Heap::kSlicedStringMapRootIndex); 3909589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); 3910589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch} 3911589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 3912589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 3913589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid MacroAssembler::AllocateAsciiSlicedString(Register result, 3914589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register scratch1, 3915589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register scratch2, 3916589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label* gc_required) { 3917589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Allocate heap number in new space. 3918589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch AllocateInNewSpace(SlicedString::kSize, 3919589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch result, 3920589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch scratch1, 3921589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch scratch2, 3922589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch gc_required, 3923589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch TAG_OBJECT); 3924589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 3925589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Set the map. The other fields are left uninitialized. 3926589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch LoadRoot(kScratchRegister, Heap::kSlicedAsciiStringMapRootIndex); 3927589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); 3928589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch} 3929589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 3930589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 393144f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Copy memory, byte-by-byte, from source to destination. Not optimized for 393244f0eee88ff00398ff7f715fab053374d808c90dSteve Block// long or aligned copies. The contents of scratch and length are destroyed. 393344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Destination is incremented by length, source, length and scratch are 393444f0eee88ff00398ff7f715fab053374d808c90dSteve Block// clobbered. 393544f0eee88ff00398ff7f715fab053374d808c90dSteve Block// A simpler loop is faster on small copies, but slower on large ones. 393644f0eee88ff00398ff7f715fab053374d808c90dSteve Block// The cld() instruction must have been emitted, to set the direction flag(), 393744f0eee88ff00398ff7f715fab053374d808c90dSteve Block// before calling this function. 393844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CopyBytes(Register destination, 393944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register source, 394044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register length, 394144f0eee88ff00398ff7f715fab053374d808c90dSteve Block int min_length, 394244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch) { 394344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(min_length >= 0); 394444f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (FLAG_debug_code) { 394544f0eee88ff00398ff7f715fab053374d808c90dSteve Block cmpl(length, Immediate(min_length)); 394644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Assert(greater_equal, "Invalid min_length"); 394744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 394844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label loop, done, short_string, short_loop; 394944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 395044f0eee88ff00398ff7f715fab053374d808c90dSteve Block const int kLongStringLimit = 20; 395144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (min_length <= kLongStringLimit) { 395244f0eee88ff00398ff7f715fab053374d808c90dSteve Block cmpl(length, Immediate(kLongStringLimit)); 395344f0eee88ff00398ff7f715fab053374d808c90dSteve Block j(less_equal, &short_string); 395444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 395544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 395644f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(source.is(rsi)); 395744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(destination.is(rdi)); 395844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(length.is(rcx)); 395944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 396044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Because source is 8-byte aligned in our uses of this function, 396144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // we keep source aligned for the rep movs operation by copying the odd bytes 396244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // at the end of the ranges. 396344f0eee88ff00398ff7f715fab053374d808c90dSteve Block movq(scratch, length); 396444f0eee88ff00398ff7f715fab053374d808c90dSteve Block shrl(length, Immediate(3)); 396544f0eee88ff00398ff7f715fab053374d808c90dSteve Block repmovsq(); 396644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Move remaining bytes of length. 396744f0eee88ff00398ff7f715fab053374d808c90dSteve Block andl(scratch, Immediate(0x7)); 396844f0eee88ff00398ff7f715fab053374d808c90dSteve Block movq(length, Operand(source, scratch, times_1, -8)); 396944f0eee88ff00398ff7f715fab053374d808c90dSteve Block movq(Operand(destination, scratch, times_1, -8), length); 397044f0eee88ff00398ff7f715fab053374d808c90dSteve Block addq(destination, scratch); 397144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 397244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (min_length <= kLongStringLimit) { 397344f0eee88ff00398ff7f715fab053374d808c90dSteve Block jmp(&done); 397444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 397544f0eee88ff00398ff7f715fab053374d808c90dSteve Block bind(&short_string); 397644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (min_length == 0) { 397744f0eee88ff00398ff7f715fab053374d808c90dSteve Block testl(length, length); 397844f0eee88ff00398ff7f715fab053374d808c90dSteve Block j(zero, &done); 397944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 398044f0eee88ff00398ff7f715fab053374d808c90dSteve Block lea(scratch, Operand(destination, length, times_1, 0)); 398144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 398244f0eee88ff00398ff7f715fab053374d808c90dSteve Block bind(&short_loop); 398344f0eee88ff00398ff7f715fab053374d808c90dSteve Block movb(length, Operand(source, 0)); 398444f0eee88ff00398ff7f715fab053374d808c90dSteve Block movb(Operand(destination, 0), length); 398544f0eee88ff00398ff7f715fab053374d808c90dSteve Block incq(source); 398644f0eee88ff00398ff7f715fab053374d808c90dSteve Block incq(destination); 398744f0eee88ff00398ff7f715fab053374d808c90dSteve Block cmpq(destination, scratch); 398844f0eee88ff00398ff7f715fab053374d808c90dSteve Block j(not_equal, &short_loop); 398944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 399044f0eee88ff00398ff7f715fab053374d808c90dSteve Block bind(&done); 399144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 399244f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 399344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 399444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 39953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::InitializeFieldsWithFiller(Register start_offset, 39963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register end_offset, 39973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register filler) { 39983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label loop, entry; 39993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch jmp(&entry); 40003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&loop); 40013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(Operand(start_offset, 0), filler); 40023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch addq(start_offset, Immediate(kPointerSize)); 40033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&entry); 40043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmpq(start_offset, end_offset); 40053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(less, &loop); 40063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 40073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4009d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::LoadContext(Register dst, int context_chain_length) { 4010d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (context_chain_length > 0) { 4011d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Move up the chain of contexts to the context containing the slot. 40123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch movq(dst, Operand(rsi, Context::SlotOffset(Context::PREVIOUS_INDEX))); 4013d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 1; i < context_chain_length; i++) { 40143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch movq(dst, Operand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX))); 4015d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 4016e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 4017e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Slot is in the current function context. Move it into the 4018e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // destination register in case we store into it (the write barrier 4019e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // cannot be allowed to destroy the context in rsi). 4020e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch movq(dst, rsi); 4021e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 4022e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 40233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // We should not have found a with context by walking the context 40243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // chain (i.e., the static scope chain and runtime context chain do 40253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // not agree). A variable occurring in such a scope should have 40263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // slot type LOOKUP and not CONTEXT. 402744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 40283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CompareRoot(FieldOperand(dst, HeapObject::kMapOffset), 40293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Heap::kWithContextMapRootIndex); 40303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Check(not_equal, "Variable resolved to with context."); 4031d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 4032d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 4033d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 40343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::LoadTransitionedArrayMapConditional( 40363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind expected_kind, 40373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind transitioned_kind, 40383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register map_in_out, 40393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 40403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* no_map_match) { 40413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load the global or builtins object from the current context. 40423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(scratch, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); 40433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(scratch, FieldOperand(scratch, GlobalObject::kGlobalContextOffset)); 40443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that the function's map is the same as the expected cached map. 40463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int expected_index = 40473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Context::GetContextMapIndexFromElementsKind(expected_kind); 40483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmpq(map_in_out, Operand(scratch, Context::SlotOffset(expected_index))); 40493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(not_equal, no_map_match); 40503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Use the transitioned cached map. 40523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int trans_index = 40533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Context::GetContextMapIndexFromElementsKind(transitioned_kind); 40543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(map_in_out, Operand(scratch, Context::SlotOffset(trans_index))); 40553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 40563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::LoadInitialArrayMap( 40593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register function_in, Register scratch, Register map_out) { 40603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!function_in.is(map_out)); 40613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label done; 40623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(map_out, FieldOperand(function_in, 40633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JSFunction::kPrototypeOrInitialMapOffset)); 40643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!FLAG_smi_only_arrays) { 40653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS, 40663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FAST_ELEMENTS, 40673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch map_out, 40683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 40693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &done); 40703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 40713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&done); 40723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 40733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 407444f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef _WIN64 407544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic const int kRegisterPassedArguments = 4; 407644f0eee88ff00398ff7f715fab053374d808c90dSteve Block#else 407744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic const int kRegisterPassedArguments = 6; 407844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif 40797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 4080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid MacroAssembler::LoadGlobalFunction(int index, Register function) { 4081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Load the global or builtins object from the current context. 4082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch movq(function, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); 4083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Load the global context from the global or builtins object. 4084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch movq(function, FieldOperand(function, GlobalObject::kGlobalContextOffset)); 4085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Load the function from the global context. 4086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch movq(function, Operand(function, Context::SlotOffset(index))); 4087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid MacroAssembler::LoadGlobalFunctionInitialMap(Register function, 4091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register map) { 4092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Load the initial map. The global functions all have initial maps. 4093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch movq(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 409444f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 4095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label ok, fail; 4096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CheckMap(map, isolate()->factory()->meta_map(), &fail, DO_SMI_CHECK); 4097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch jmp(&ok); 4098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bind(&fail); 4099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Abort("Global functions must have initial map"); 4100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bind(&ok); 4101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 41054515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkeint MacroAssembler::ArgumentStackSlotsForCFunctionCall(int num_arguments) { 41067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // On Windows 64 stack slots are reserved by the caller for all arguments 41077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // including the ones passed in registers, and space is always allocated for 41087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // the four register arguments even if the function takes fewer than four 41097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // arguments. 41107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // On AMD64 ABI (Linux/Mac) the first six arguments are passed in registers 41117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // and the caller does not reserve stack slots for them. 41124515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke ASSERT(num_arguments >= 0); 41134515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke#ifdef _WIN64 411444f0eee88ff00398ff7f715fab053374d808c90dSteve Block const int kMinimumStackSlots = kRegisterPassedArguments; 41157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (num_arguments < kMinimumStackSlots) return kMinimumStackSlots; 41167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch return num_arguments; 41174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke#else 41187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (num_arguments < kRegisterPassedArguments) return 0; 41197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch return num_arguments - kRegisterPassedArguments; 41204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke#endif 41214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke} 41224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 41237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 41244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid MacroAssembler::PrepareCallCFunction(int num_arguments) { 41254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke int frame_alignment = OS::ActivationFrameAlignment(); 41264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke ASSERT(frame_alignment != 0); 41274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke ASSERT(num_arguments >= 0); 412844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 41294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Make stack end at alignment and allocate space for arguments and old rsp. 41304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke movq(kScratchRegister, rsp); 41314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke ASSERT(IsPowerOf2(frame_alignment)); 41324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke int argument_slots_on_stack = 41334515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke ArgumentStackSlotsForCFunctionCall(num_arguments); 41344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke subq(rsp, Immediate((argument_slots_on_stack + 1) * kPointerSize)); 41354515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke and_(rsp, Immediate(-frame_alignment)); 41364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke movq(Operand(rsp, argument_slots_on_stack * kPointerSize), kScratchRegister); 41374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke} 41384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 41394515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 41404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid MacroAssembler::CallCFunction(ExternalReference function, 41414515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke int num_arguments) { 414244f0eee88ff00398ff7f715fab053374d808c90dSteve Block LoadAddress(rax, function); 41434515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke CallCFunction(rax, num_arguments); 41444515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke} 41454515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 41464515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 41474515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid MacroAssembler::CallCFunction(Register function, int num_arguments) { 41483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(has_frame()); 41496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check stack alignment. 415044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 41516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block CheckStackAlignment(); 41526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 41536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 41544515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke call(function); 41554515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke ASSERT(OS::ActivationFrameAlignment() != 0); 41564515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke ASSERT(num_arguments >= 0); 41574515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke int argument_slots_on_stack = 41584515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke ArgumentStackSlotsForCFunctionCall(num_arguments); 41594515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke movq(rsp, Operand(rsp, argument_slots_on_stack * kPointerSize)); 41604515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke} 41614515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 4162d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 41633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool AreAliased(Register r1, Register r2, Register r3, Register r4) { 41643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (r1.is(r2)) return true; 41653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (r1.is(r3)) return true; 41663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (r1.is(r4)) return true; 41673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (r2.is(r3)) return true; 41683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (r2.is(r4)) return true; 41693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (r3.is(r4)) return true; 41703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return false; 41713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 41723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 41733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCodePatcher::CodePatcher(byte* address, int size) 41758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch : address_(address), 41768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch size_(size), 41778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch masm_(Isolate::Current(), address, size + Assembler::kGap) { 4178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Create a new macro assembler pointing to the address of the code to patch. 4179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The size is adjusted with kGap on order for the assembler to generate size 4180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // bytes of instructions without failing with buffer size constraints. 4181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); 4182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 4183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCodePatcher::~CodePatcher() { 4186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Indicate that code has changed. 4187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CPU::FlushICache(address_, size_); 4188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the code was patched as expected. 4190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(masm_.pc_ == address_ + size_); 4191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); 4192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 4193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 41943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 41953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckPageFlag( 41963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object, 41973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 41983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int mask, 41993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition cc, 42003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* condition_met, 42013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance condition_met_distance) { 42023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(cc == zero || cc == not_zero); 42033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (scratch.is(object)) { 42043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(scratch, Immediate(~Page::kPageAlignmentMask)); 42053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 42063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(scratch, Immediate(~Page::kPageAlignmentMask)); 42073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(scratch, object); 42083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 42093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (mask < (1 << kBitsPerByte)) { 42103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch testb(Operand(scratch, MemoryChunk::kFlagsOffset), 42113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(static_cast<uint8_t>(mask))); 42123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 42133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch testl(Operand(scratch, MemoryChunk::kFlagsOffset), Immediate(mask)); 42143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 42153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(cc, condition_met, condition_met_distance); 42163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 42173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::JumpIfBlack(Register object, 42203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register bitmap_scratch, 42213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register mask_scratch, 42223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* on_black, 42233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance on_black_distance) { 42243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!AreAliased(object, bitmap_scratch, mask_scratch, rcx)); 42253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GetMarkBits(object, bitmap_scratch, mask_scratch); 42263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0); 42283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The mask_scratch register contains a 1 at the position of the first bit 42293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // and a 0 at all other positions, including the position of the second bit. 42303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(rcx, mask_scratch); 42313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make rcx into a mask that covers both marking bits using the operation 42323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rcx = mask | (mask << 1). 42333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lea(rcx, Operand(mask_scratch, mask_scratch, times_2, 0)); 42343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Note that we are using a 4-byte aligned 8-byte load. 42353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(rcx, Operand(bitmap_scratch, MemoryChunk::kHeaderSize)); 42363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmpq(mask_scratch, rcx); 42373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(equal, on_black, on_black_distance); 42383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 42393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Detect some, but not all, common pointer-free objects. This is used by the 42423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// incremental write barrier which doesn't care about oddballs (they are always 42433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// marked black immediately so this code is not hit). 42443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::JumpIfDataObject( 42453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register value, 42463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 42473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* not_data_object, 42483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance not_data_object_distance) { 42493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label is_data_object; 42503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(scratch, FieldOperand(value, HeapObject::kMapOffset)); 42513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompareRoot(scratch, Heap::kHeapNumberMapRootIndex); 42523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(equal, &is_data_object, Label::kNear); 42533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1); 42543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(kNotStringTag == 0x80 && kIsNotStringMask == 0x80); 42553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If it's a string and it's not a cons string then it's an object containing 42563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // no GC pointers. 42573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch testb(FieldOperand(scratch, Map::kInstanceTypeOffset), 42583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(kIsIndirectStringMask | kIsNotStringMask)); 42593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(not_zero, not_data_object, not_data_object_distance); 42603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&is_data_object); 42613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 42623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::GetMarkBits(Register addr_reg, 42653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register bitmap_reg, 42663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register mask_reg) { 42673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!AreAliased(addr_reg, bitmap_reg, mask_reg, rcx)); 42683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(bitmap_reg, addr_reg); 42693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Sign extended 32 bit immediate. 42703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(bitmap_reg, Immediate(~Page::kPageAlignmentMask)); 42713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(rcx, addr_reg); 42723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int shift = 42733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Bitmap::kBitsPerCellLog2 + kPointerSizeLog2 - Bitmap::kBytesPerCellLog2; 42743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch shrl(rcx, Immediate(shift)); 42753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(rcx, 42763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate((Page::kPageAlignmentMask >> shift) & 42773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ~(Bitmap::kBytesPerCell - 1))); 42783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch addq(bitmap_reg, rcx); 42803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(rcx, addr_reg); 42813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch shrl(rcx, Immediate(kPointerSizeLog2)); 42823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(rcx, Immediate((1 << Bitmap::kBitsPerCellLog2) - 1)); 42833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movl(mask_reg, Immediate(1)); 42843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch shl_cl(mask_reg); 42853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 42863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::EnsureNotWhite( 42893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register value, 42903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register bitmap_scratch, 42913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register mask_scratch, 42923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* value_is_white_and_not_data, 42933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance distance) { 42943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!AreAliased(value, bitmap_scratch, mask_scratch, rcx)); 42953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GetMarkBits(value, bitmap_scratch, mask_scratch); 42963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If the value is black or grey we don't need to do anything. 42983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(strcmp(Marking::kWhiteBitPattern, "00") == 0); 42993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0); 43003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(strcmp(Marking::kGreyBitPattern, "11") == 0); 43013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(strcmp(Marking::kImpossibleBitPattern, "01") == 0); 43023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label done; 43043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Since both black and grey have a 1 in the first position and white does 43063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // not have a 1 there we only need to check one bit. 43073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch testq(Operand(bitmap_scratch, MemoryChunk::kHeaderSize), mask_scratch); 43083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(not_zero, &done, Label::kNear); 43093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_debug_code) { 43113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for impossible bit pattern. 43123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label ok; 43133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch push(mask_scratch); 43143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // shl. May overflow making the check conservative. 43153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch addq(mask_scratch, mask_scratch); 43163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch testq(Operand(bitmap_scratch, MemoryChunk::kHeaderSize), mask_scratch); 43173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(zero, &ok, Label::kNear); 43183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int3(); 43193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&ok); 43203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch pop(mask_scratch); 43213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 43223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Value is white. We check whether it is data that doesn't need scanning. 43243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Currently only checks for HeapNumber and non-cons strings. 43253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register map = rcx; // Holds map while checking type. 43263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register length = rcx; // Holds length of object after checking type. 43273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label not_heap_number; 43283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label is_data_object; 43293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for heap-number 43313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(map, FieldOperand(value, HeapObject::kMapOffset)); 43323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompareRoot(map, Heap::kHeapNumberMapRootIndex); 43333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(not_equal, ¬_heap_number, Label::kNear); 43343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(length, Immediate(HeapNumber::kSize)); 43353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch jmp(&is_data_object, Label::kNear); 43363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(¬_heap_number); 43383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for strings. 43393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1); 43403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(kNotStringTag == 0x80 && kIsNotStringMask == 0x80); 43413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If it's a string and it's not a cons string then it's an object containing 43423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // no GC pointers. 43433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register instance_type = rcx; 43443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movzxbl(instance_type, FieldOperand(map, Map::kInstanceTypeOffset)); 43453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch testb(instance_type, Immediate(kIsIndirectStringMask | kIsNotStringMask)); 43463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(not_zero, value_is_white_and_not_data); 43473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // It's a non-indirect (non-cons and non-slice) string. 43483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If it's external, the length is just ExternalString::kSize. 43493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Otherwise it's String::kHeaderSize + string->length() * (1 or 2). 43503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label not_external; 43513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // External strings are the only ones with the kExternalStringTag bit 43523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // set. 43533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_EQ(0, kSeqStringTag & kExternalStringTag); 43543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_EQ(0, kConsStringTag & kExternalStringTag); 43553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch testb(instance_type, Immediate(kExternalStringTag)); 43563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(zero, ¬_external, Label::kNear); 43573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(length, Immediate(ExternalString::kSize)); 43583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch jmp(&is_data_object, Label::kNear); 43593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(¬_external); 43613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Sequential string, either ASCII or UC16. 43623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(kAsciiStringTag == 0x04); 43633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(length, Immediate(kStringEncodingMask)); 43643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch xor_(length, Immediate(kStringEncodingMask)); 43653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch addq(length, Immediate(0x04)); 43663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Value now either 4 (if ASCII) or 8 (if UC16), i.e. char-size shifted by 2. 43673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch imul(length, FieldOperand(value, String::kLengthOffset)); 43683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch shr(length, Immediate(2 + kSmiTagSize + kSmiShiftSize)); 43693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch addq(length, Immediate(SeqString::kHeaderSize + kObjectAlignmentMask)); 43703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(length, Immediate(~kObjectAlignmentMask)); 43713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&is_data_object); 43733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Value is a data object, and it is white. Mark it black. Since we know 43743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // that the object is white we can make it black by flipping one bit. 43753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch or_(Operand(bitmap_scratch, MemoryChunk::kHeaderSize), mask_scratch); 43763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(bitmap_scratch, Immediate(~Page::kPageAlignmentMask)); 43783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch addl(Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset), length); 43793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&done); 43813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 43823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckEnumCache(Register null_value, Label* call_runtime) { 43853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label next; 43863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register empty_fixed_array_value = r8; 43873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex); 43883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register empty_descriptor_array_value = r9; 43893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LoadRoot(empty_descriptor_array_value, 43903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::kEmptyDescriptorArrayRootIndex); 43913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(rcx, rax); 43923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&next); 43933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that there are no elements. Register rcx contains the 43953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // current JS object we've reached through the prototype chain. 43963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmpq(empty_fixed_array_value, 43973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldOperand(rcx, JSObject::kElementsOffset)); 43983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(not_equal, call_runtime); 43993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that instance descriptors are not empty so that we can 44013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // check for an enum cache. Leave the map in rbx for the subsequent 44023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // prototype load. 44033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(rbx, FieldOperand(rcx, HeapObject::kMapOffset)); 44043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(rdx, FieldOperand(rbx, Map::kInstanceDescriptorsOrBitField3Offset)); 44053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JumpIfSmi(rdx, call_runtime); 44063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that there is an enum cache in the non-empty instance 44083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // descriptors (rdx). This is the case if the next enumeration 44093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // index field does not contain a smi. 44103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(rdx, FieldOperand(rdx, DescriptorArray::kEnumerationIndexOffset)); 44113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JumpIfSmi(rdx, call_runtime); 44123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // For all objects but the receiver, check that the cache is empty. 44143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label check_prototype; 44153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmpq(rcx, rax); 44163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(equal, &check_prototype, Label::kNear); 44173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(rdx, FieldOperand(rdx, DescriptorArray::kEnumCacheBridgeCacheOffset)); 44183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmpq(rdx, empty_fixed_array_value); 44193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(not_equal, call_runtime); 44203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load the prototype from the map and loop if non-null. 44223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&check_prototype); 44233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movq(rcx, FieldOperand(rbx, Map::kPrototypeOffset)); 44243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmpq(rcx, null_value); 44253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(not_equal, &next); 44263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 44273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 4430f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 4431f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_X64 4432