macro-assembler-ia32.cc revision bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8
13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_IA32 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/bits.h" 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/division-by-constant.h" 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/bootstrapper.h" 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h" 11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/debug/debug.h" 12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/ia32/frames-ia32.h" 13014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/ia32/macro-assembler-ia32.h" 14958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/runtime/runtime.h" 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ------------------------------------------------------------------------- 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// MacroAssembler implementation. 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 22014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochMacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size, 23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CodeObjectRequired create_code_object) 248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch : Assembler(arg_isolate, buffer, size), 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block generating_stub_(false), 263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch has_frame_(false) { 27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (create_code_object == CodeObjectRequired::kYes) { 28014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch code_object_ = 29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<Object>::New(isolate()->heap()->undefined_value(), isolate()); 308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Load(Register dst, const Operand& src, Representation r) { 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!r.IsDouble()); 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (r.IsInteger8()) { 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch movsx_b(dst, src); 38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (r.IsUInteger8()) { 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch movzx_b(dst, src); 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (r.IsInteger16()) { 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch movsx_w(dst, src); 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (r.IsUInteger16()) { 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch movzx_w(dst, src); 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(dst, src); 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Store(Register src, const Operand& dst, Representation r) { 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!r.IsDouble()); 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (r.IsInteger8() || r.IsUInteger8()) { 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov_b(dst, src); 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (r.IsInteger16() || r.IsUInteger16()) { 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov_w(dst, src); 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (r.IsHeapObject()) { 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AssertNotSmi(src); 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (r.IsSmi()) { 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AssertSmi(src); 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(dst, src); 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index) { 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (isolate()->heap()->RootCanBeTreatedAsConstant(index)) { 69014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mov(destination, isolate()->heap()->root_handle(index)); 70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference roots_array_start = 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::roots_array_start(isolate()); 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(destination, Immediate(index)); 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(destination, Operand::StaticArray(destination, 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch times_pointer_size, 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch roots_array_start)); 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::StoreRoot(Register source, 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch, 83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap::RootListIndex index) { 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Heap::RootCanBeWrittenAfterInitialization(index)); 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference roots_array_start = 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::roots_array_start(isolate()); 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(scratch, Immediate(index)); 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(Operand::StaticArray(scratch, times_pointer_size, roots_array_start), 89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch source); 90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CompareRoot(Register with, 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch, 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap::RootListIndex index) { 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference roots_array_start = 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::roots_array_start(isolate()); 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(scratch, Immediate(index)); 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(with, Operand::StaticArray(scratch, 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch times_pointer_size, 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch roots_array_start)); 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) { 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(isolate()->heap()->RootCanBeTreatedAsConstant(index)); 107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch cmp(with, isolate()->heap()->root_handle(index)); 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CompareRoot(const Operand& with, 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap::RootListIndex index) { 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(isolate()->heap()->RootCanBeTreatedAsConstant(index)); 114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch cmp(with, isolate()->heap()->root_handle(index)); 115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::PushRoot(Heap::RootListIndex index) { 119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(isolate()->heap()->RootCanBeTreatedAsConstant(index)); 120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Push(isolate()->heap()->root_handle(index)); 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 123109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#define REG(Name) \ 124109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch { Register::kCode_##Name } 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 126109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochstatic const Register saved_regs[] = {REG(eax), REG(ecx), REG(edx)}; 127109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 128109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#undef REG 129109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 130109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochstatic const int kNumberOfSavedRegs = sizeof(saved_regs) / sizeof(Register); 131109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 132109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::PushCallerSaved(SaveFPRegsMode fp_mode, 133109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register exclusion1, Register exclusion2, 134109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register exclusion3) { 135109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // We don't allow a GC during a store buffer overflow so there is no need to 136109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // store the registers in any particular way, but we do have to store and 137109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // restore them. 138109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch for (int i = 0; i < kNumberOfSavedRegs; i++) { 139109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register reg = saved_regs[i]; 140109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (!reg.is(exclusion1) && !reg.is(exclusion2) && !reg.is(exclusion3)) { 141109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch push(reg); 142109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 143109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 144109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (fp_mode == kSaveFPRegs) { 145109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch sub(esp, Immediate(kDoubleSize * (XMMRegister::kMaxNumRegisters - 1))); 146109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Save all XMM registers except XMM0. 147109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch for (int i = XMMRegister::kMaxNumRegisters - 1; i > 0; i--) { 148109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch XMMRegister reg = XMMRegister::from_code(i); 149109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch movsd(Operand(esp, (i - 1) * kDoubleSize), reg); 150109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 151109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 152109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 153109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 154109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1, 155109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register exclusion2, Register exclusion3) { 156109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (fp_mode == kSaveFPRegs) { 157109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Restore all XMM registers except XMM0. 158109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch for (int i = XMMRegister::kMaxNumRegisters - 1; i > 0; i--) { 159109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch XMMRegister reg = XMMRegister::from_code(i); 160109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch movsd(reg, Operand(esp, (i - 1) * kDoubleSize)); 161109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 162109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch add(esp, Immediate(kDoubleSize * (XMMRegister::kMaxNumRegisters - 1))); 163109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 164109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 165109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch for (int i = kNumberOfSavedRegs - 1; i >= 0; i--) { 166109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register reg = saved_regs[i]; 167109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (!reg.is(exclusion1) && !reg.is(exclusion2) && !reg.is(exclusion3)) { 168109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch pop(reg); 169109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 1706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 171109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 172109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 173109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::InNewSpace(Register object, Register scratch, Condition cc, 174109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label* condition_met, 175109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label::Distance distance) { 176109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const int mask = 177109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch (1 << MemoryChunk::IN_FROM_SPACE) | (1 << MemoryChunk::IN_TO_SPACE); 178109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CheckPageFlag(object, scratch, mask, cc, condition_met, distance); 1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 1806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::RememberedSetHelper( 1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object, // Only used for debug checks. 1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register addr, 1853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 1863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SaveFPRegsMode save_fp, 1873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler::RememberedSetFinalAction and_then) { 1883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label done; 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (emit_debug_code()) { 1903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label ok; 1913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JumpIfNotInNewSpace(object, scratch, &ok, Label::kNear); 1923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int3(); 1933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&ok); 1943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load store buffer top. 1963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference store_buffer = 1973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference::store_buffer_top(isolate()); 1983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(scratch, Operand::StaticVariable(store_buffer)); 1993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store pointer to buffer. 2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(Operand(scratch, 0), addr); 2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Increment buffer top. 2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(scratch, Immediate(kPointerSize)); 2033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Write back new top of buffer. 2043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(Operand::StaticVariable(store_buffer), scratch); 2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Call stub on end of buffer. 2063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for end of buffer. 2073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch test(scratch, Immediate(StoreBuffer::kStoreBufferMask)); 2083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (and_then == kReturnAtEnd) { 2093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label buffer_overflowed; 2103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch j(equal, &buffer_overflowed, Label::kNear); 2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ret(0); 2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&buffer_overflowed); 2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(and_then == kFallThroughAtEnd); 2153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch j(not_equal, &done, Label::kNear); 2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StoreBufferOverflowStub store_buffer_overflow(isolate(), save_fp); 2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallStub(&store_buffer_overflow); 2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (and_then == kReturnAtEnd) { 2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ret(0); 2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(and_then == kFallThroughAtEnd); 2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&done); 2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::ClampDoubleToUint8(XMMRegister input_reg, 229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch XMMRegister scratch_reg, 230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register result_reg) { 231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label conv_failure; 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch xorps(scratch_reg, scratch_reg); 234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cvtsd2si(result_reg, input_reg); 235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch test(result_reg, Immediate(0xFFFFFF00)); 236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(zero, &done, Label::kNear); 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(result_reg, Immediate(0x1)); 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch j(overflow, &conv_failure, Label::kNear); 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(result_reg, Immediate(0)); 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch setcc(sign, result_reg); 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sub(result_reg, Immediate(1)); 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch and_(result_reg, Immediate(255)); 243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch jmp(&done, Label::kNear); 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bind(&conv_failure); 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Move(result_reg, Immediate(0)); 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ucomisd(input_reg, scratch_reg); 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch j(below, &done, Label::kNear); 248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Move(result_reg, Immediate(255)); 249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bind(&done); 250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::ClampUint8(Register reg) { 254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch test(reg, Immediate(0xFFFFFF00)); 256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(zero, &done, Label::kNear); 257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch setcc(negative, reg); // 1 if negative, 0 if positive. 258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch dec_b(reg); // 0 if negative, 255 if positive. 259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bind(&done); 260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::SlowTruncateToI(Register result_reg, 264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register input_reg, 265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int offset) { 266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DoubleToIStub stub(isolate(), input_reg, result_reg, offset, true); 267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch call(stub.GetCode(), RelocInfo::CODE_TARGET); 268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TruncateDoubleToI(Register result_reg, 272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch XMMRegister input_reg) { 273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cvttsd2si(result_reg, Operand(input_reg)); 275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(result_reg, 0x1); 276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch j(no_overflow, &done, Label::kNear); 277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sub(esp, Immediate(kDoubleSize)); 279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch movsd(MemOperand(esp, 0), input_reg); 280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SlowTruncateToI(result_reg, esp, 0); 281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch add(esp, Immediate(kDoubleSize)); 282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bind(&done); 283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::DoubleToI(Register result_reg, XMMRegister input_reg, 287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch XMMRegister scratch, 288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MinusZeroMode minus_zero_mode, 289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* lost_precision, Label* is_nan, 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* minus_zero, Label::Distance dst) { 291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!input_reg.is(scratch)); 292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cvttsd2si(result_reg, Operand(input_reg)); 293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Cvtsi2sd(scratch, Operand(result_reg)); 294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ucomisd(scratch, input_reg); 295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch j(not_equal, lost_precision, dst); 296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch j(parity_even, is_nan, dst); 297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (minus_zero_mode == FAIL_ON_MINUS_ZERO) { 298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The integer converted back is equal to the original. We 300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // only have to test if we got -0 as an input. 301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch test(result_reg, Operand(result_reg)); 302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch j(not_zero, &done, Label::kNear); 303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch movmskpd(result_reg, input_reg); 304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Bit 0 contains the sign of the double in input_reg. 305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If input was positive, we are ok and return 0, otherwise 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // jump to minus_zero. 307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch and_(result_reg, 1); 308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch j(not_zero, minus_zero, dst); 309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bind(&done); 310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TruncateHeapNumberToI(Register result_reg, 315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register input_reg) { 316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done, slow_case; 317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (CpuFeatures::IsSupported(SSE3)) { 319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CpuFeatureScope scope(this, SSE3); 320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label convert; 321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Use more powerful conversion when sse3 is available. 322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load x87 register with heap number. 323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); 324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get exponent alone and check for too-big exponent. 325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(result_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset)); 326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch and_(result_reg, HeapNumber::kExponentMask); 327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const uint32_t kTooBigExponent = 328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift; 329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(Operand(result_reg), Immediate(kTooBigExponent)); 330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch j(greater_equal, &slow_case, Label::kNear); 331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Reserve space for 64 bit answer. 333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sub(Operand(esp), Immediate(kDoubleSize)); 334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Do conversion, which cannot fail because we checked the exponent. 335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch fisttp_d(Operand(esp, 0)); 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(result_reg, Operand(esp, 0)); // Low word of answer is the result. 337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch add(Operand(esp), Immediate(kDoubleSize)); 338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch jmp(&done, Label::kNear); 339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Slow case. 341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bind(&slow_case); 342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (input_reg.is(result_reg)) { 343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Input is clobbered. Restore number from fpu stack 344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sub(Operand(esp), Immediate(kDoubleSize)); 345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch fstp_d(Operand(esp, 0)); 346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SlowTruncateToI(result_reg, esp, 0); 347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch add(esp, Immediate(kDoubleSize)); 348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch fstp(0); 350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SlowTruncateToI(result_reg, input_reg); 351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); 354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cvttsd2si(result_reg, Operand(xmm0)); 355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(result_reg, 0x1); 356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch j(no_overflow, &done, Label::kNear); 357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if the input was 0x8000000 (kMinInt). 358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If no, then we got an overflow and we deoptimize. 359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference min_int = ExternalReference::address_of_min_int(); 360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ucomisd(xmm0, Operand::StaticVariable(min_int)); 361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch j(not_equal, &slow_case, Label::kNear); 362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch j(parity_even, &slow_case, Label::kNear); // NaN. 363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch jmp(&done, Label::kNear); 364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Slow case. 366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bind(&slow_case); 367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (input_reg.is(result_reg)) { 368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Input is clobbered. Restore number from double scratch. 369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sub(esp, Immediate(kDoubleSize)); 370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch movsd(MemOperand(esp, 0), xmm0); 371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SlowTruncateToI(result_reg, esp, 0); 372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch add(esp, Immediate(kDoubleSize)); 373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SlowTruncateToI(result_reg, input_reg); 375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bind(&done); 378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 381958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::LoadUint32(XMMRegister dst, const Operand& src) { 382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(src, Immediate(0)); 384958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference uint32_bias = ExternalReference::address_of_uint32_bias(); 385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Cvtsi2sd(dst, src); 386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch j(not_sign, &done, Label::kNear); 387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch addsd(dst, Operand::StaticVariable(uint32_bias)); 388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bind(&done); 389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::RecordWriteArray( 393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object, 394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value, 395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register index, 396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SaveFPRegsMode save_fp, 397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RememberedSetAction remembered_set_action, 398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SmiCheck smi_check, 399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PointersToHereCheck pointers_to_here_check_for_value) { 4003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // First, check if a write barrier is even needed. The tests below 4013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // catch stores of Smis. 4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label done; 4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Skip barrier if writing a smi. 4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (smi_check == INLINE_SMI_CHECK) { 406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(0, kSmiTag); 4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test(value, Immediate(kSmiTagMask)); 4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(zero, &done); 4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Array access: calculate the destination address in the same manner as 4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // KeyedStoreIC::GenerateGeneric. Multiply a smi by 2 to get an offset 4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // into an array of words. 4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register dst = index; 4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lea(dst, Operand(object, index, times_half_pointer_size, 4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArray::kHeaderSize - kHeapObjectTag)); 4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordWrite(object, dst, value, save_fp, remembered_set_action, 419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OMIT_SMI_CHECK, pointers_to_here_check_for_value); 4203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&done); 4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Clobber clobbered input registers when running with the debug-code flag 4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // turned on to provoke errors. 4253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (emit_debug_code()) { 426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(value, Immediate(bit_cast<int32_t>(kZapValue))); 427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(index, Immediate(bit_cast<int32_t>(kZapValue))); 428257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::RecordWriteField( 4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object, 4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int offset, 4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register value, 4363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register dst, 4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SaveFPRegsMode save_fp, 4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RememberedSetAction remembered_set_action, 439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SmiCheck smi_check, 440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PointersToHereCheck pointers_to_here_check_for_value) { 4417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // First, check if a write barrier is even needed. The tests below 4423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // catch stores of Smis. 443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Skip barrier if writing a smi. 4463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (smi_check == INLINE_SMI_CHECK) { 4473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JumpIfSmi(value, &done, Label::kNear); 4483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 4503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Although the object register is tagged, the offset is relative to the start 4513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // of the object, so so offset must be a multiple of kPointerSize. 452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsAligned(offset, kPointerSize)); 453592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 4543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lea(dst, FieldOperand(object, offset)); 4553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (emit_debug_code()) { 4563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label ok; 4573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch test_b(dst, Immediate((1 << kPointerSizeLog2) - 1)); 4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(zero, &ok, Label::kNear); 4593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int3(); 4603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&ok); 46185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch } 4623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordWrite(object, dst, value, save_fp, remembered_set_action, 464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OMIT_SMI_CHECK, pointers_to_here_check_for_value); 465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&done); 4674515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 4683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Clobber clobbered input registers when running with the debug-code flag 4694515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // turned on to provoke errors. 47044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(value, Immediate(bit_cast<int32_t>(kZapValue))); 472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(dst, Immediate(bit_cast<int32_t>(kZapValue))); 4734515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::RecordWriteForMap( 478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object, 479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> map, 480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1, 481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2, 482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SaveFPRegsMode save_fp) { 483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register address = scratch1; 486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value = scratch2; 4873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (emit_debug_code()) { 488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label ok; 489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch lea(address, FieldOperand(object, HeapObject::kMapOffset)); 4903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch test_b(address, Immediate((1 << kPointerSizeLog2) - 1)); 491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch j(zero, &ok, Label::kNear); 492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int3(); 493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bind(&ok); 494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!object.is(value)); 497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!object.is(address)); 498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!value.is(address)); 499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AssertNotSmi(object); 500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!FLAG_incremental_marking) { 502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compute the address. 506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch lea(address, FieldOperand(object, HeapObject::kMapOffset)); 507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // A single check of the map's pages interesting flag suffices, since it is 509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // only set during incremental collection, and then it's also guaranteed that 510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the from object's page's interesting flag is also set. This optimization 511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // relies on the fact that maps can never be in new space. 512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!isolate()->heap()->InNewSpace(*map)); 513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CheckPageFlagForMap(map, 514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemoryChunk::kPointersToHereAreInterestingMask, 515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch zero, 516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &done, 517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label::kNear); 518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordWriteStub stub(isolate(), object, value, address, OMIT_REMEMBERED_SET, 520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch save_fp); 521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallStub(&stub); 522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bind(&done); 524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Count number of write barriers in generated code. 526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate()->counters()->write_barriers_static()->Increment(); 527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1); 528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Clobber clobbered input registers when running with the debug-code flag 530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // turned on to provoke errors. 531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (emit_debug_code()) { 532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(value, Immediate(bit_cast<int32_t>(kZapValue))); 533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(scratch1, Immediate(bit_cast<int32_t>(kZapValue))); 534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(scratch2, Immediate(bit_cast<int32_t>(kZapValue))); 535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::RecordWrite( 540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object, 541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register address, 542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value, 543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SaveFPRegsMode fp_mode, 544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RememberedSetAction remembered_set_action, 545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SmiCheck smi_check, 546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PointersToHereCheck pointers_to_here_check_for_value) { 547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!object.is(value)); 548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!object.is(address)); 549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!value.is(address)); 550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AssertNotSmi(object); 551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (remembered_set_action == OMIT_REMEMBERED_SET && 5533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch !FLAG_incremental_marking) { 5543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return; 5553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 5563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (emit_debug_code()) { 5583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label ok; 5593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmp(value, Operand(address, 0)); 5603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(equal, &ok, Label::kNear); 5613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int3(); 5623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&ok); 5633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 5643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5658defd9ff6930b4e24729971a61cf7469daf119beSteve Block // First, check if a write barrier is even needed. The tests below 5668defd9ff6930b4e24729971a61cf7469daf119beSteve Block // catch stores of Smis and stores into young gen. 5678defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label done; 5688defd9ff6930b4e24729971a61cf7469daf119beSteve Block 5693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (smi_check == INLINE_SMI_CHECK) { 5703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Skip barrier if writing a smi. 5713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JumpIfSmi(value, &done, Label::kNear); 5723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 5733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (pointers_to_here_check_for_value != kPointersToHereAreAlwaysInteresting) { 575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CheckPageFlag(value, 576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch value, // Used as scratch. 577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemoryChunk::kPointersToHereAreInterestingMask, 578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch zero, 579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &done, 580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label::kNear); 581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPageFlag(object, 5833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value, // Used as scratch. 5843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MemoryChunk::kPointersFromHereAreInterestingMask, 5853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch zero, 5863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &done, 5873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::kNear); 5883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordWriteStub stub(isolate(), object, value, address, remembered_set_action, 590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch fp_mode); 5913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallStub(&stub); 5928defd9ff6930b4e24729971a61cf7469daf119beSteve Block 5938defd9ff6930b4e24729971a61cf7469daf119beSteve Block bind(&done); 5948defd9ff6930b4e24729971a61cf7469daf119beSteve Block 595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Count number of write barriers in generated code. 596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate()->counters()->write_barriers_static()->Increment(); 597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1); 598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Clobber clobbered registers when running with the debug-code flag 6008defd9ff6930b4e24729971a61cf7469daf119beSteve Block // turned on to provoke errors. 60144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(address, Immediate(bit_cast<int32_t>(kZapValue))); 603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(value, Immediate(bit_cast<int32_t>(kZapValue))); 6048defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 6058defd9ff6930b4e24729971a61cf7469daf119beSteve Block} 6068defd9ff6930b4e24729971a61cf7469daf119beSteve Block 607109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::RecordWriteCodeEntryField(Register js_function, 608109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register code_entry, 609109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register scratch) { 610109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const int offset = JSFunction::kCodeEntryOffset; 611109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 612109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Since a code entry (value) is always in old space, we don't need to update 613109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // remembered set. If incremental marking is off, there is nothing for us to 614109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // do. 615109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (!FLAG_incremental_marking) return; 616109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 617109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DCHECK(!js_function.is(code_entry)); 618109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DCHECK(!js_function.is(scratch)); 619109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DCHECK(!code_entry.is(scratch)); 620109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch AssertNotSmi(js_function); 621109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 622109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (emit_debug_code()) { 623109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label ok; 624109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch lea(scratch, FieldOperand(js_function, offset)); 625109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch cmp(code_entry, Operand(scratch, 0)); 626109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch j(equal, &ok, Label::kNear); 627109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch int3(); 628109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch bind(&ok); 629109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 630109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 631109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // First, check if a write barrier is even needed. The tests below 632109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // catch stores of Smis and stores into young gen. 633109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label done; 634109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 635109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CheckPageFlag(code_entry, scratch, 636109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch MemoryChunk::kPointersToHereAreInterestingMask, zero, &done, 637109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label::kNear); 638109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CheckPageFlag(js_function, scratch, 639109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch MemoryChunk::kPointersFromHereAreInterestingMask, zero, &done, 640109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label::kNear); 641109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 642109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Save input registers. 643109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch push(js_function); 644109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch push(code_entry); 645109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 646109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const Register dst = scratch; 647109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch lea(dst, FieldOperand(js_function, offset)); 648109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 649109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Save caller-saved registers. 650109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushCallerSaved(kDontSaveFPRegs, js_function, code_entry); 651109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 652109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch int argument_count = 3; 653109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PrepareCallCFunction(argument_count, code_entry); 654109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch mov(Operand(esp, 0 * kPointerSize), js_function); 655109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch mov(Operand(esp, 1 * kPointerSize), dst); // Slot. 656109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch mov(Operand(esp, 2 * kPointerSize), 657109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Immediate(ExternalReference::isolate_address(isolate()))); 658109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 659109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch { 660109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch AllowExternalCallThatCantCauseGC scope(this); 661109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CallCFunction( 662109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ExternalReference::incremental_marking_record_write_code_entry_function( 663109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch isolate()), 664109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch argument_count); 665109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 666109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 667109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Restore caller-saved registers. 668109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopCallerSaved(kDontSaveFPRegs, js_function, code_entry); 669109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 670109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Restore input registers. 671109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch pop(code_entry); 672109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch pop(js_function); 673109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 674109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch bind(&done); 675109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 6768defd9ff6930b4e24729971a61cf7469daf119beSteve Block 677402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::DebugBreak() { 678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Move(eax, Immediate(0)); 679014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mov(ebx, Immediate(ExternalReference(Runtime::kHandleDebuggerStatement, 680014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch isolate()))); 681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CEntryStub ces(isolate(), 1); 682014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch call(ces.GetCode(), RelocInfo::DEBUGGER_STATEMENT); 683402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Cvtsi2sd(XMMRegister dst, const Operand& src) { 686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch xorps(dst, dst); 687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cvtsi2sd(dst, src); 688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 691109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::Cvtui2ss(XMMRegister dst, Register src, Register tmp) { 692109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label msb_set_src; 693109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label jmp_return; 694109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch test(src, src); 695109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch j(sign, &msb_set_src, Label::kNear); 696109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch cvtsi2ss(dst, src); 697109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch jmp(&jmp_return, Label::kNear); 698109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch bind(&msb_set_src); 699109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch mov(tmp, src); 700109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch shr(src, 1); 701109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Recover the least significant bit to avoid rounding errors. 702109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch and_(tmp, Immediate(1)); 703109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch or_(src, tmp); 704109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch cvtsi2ss(dst, src); 705109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch addss(dst, dst); 706109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch bind(&jmp_return); 707109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 708109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 7093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::ShlPair(Register high, Register low, uint8_t shift) { 7103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (shift >= 32) { 7113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch mov(high, low); 7123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch shl(high, shift - 32); 7133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch xor_(low, low); 7143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } else { 7153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch shld(high, low, shift); 7163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch shl(low, shift); 7173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 7183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch} 7193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 7203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::ShlPair_cl(Register high, Register low) { 7213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch shld_cl(high, low); 7223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch shl_cl(low); 7233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Label done; 7243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch test(ecx, Immediate(0x20)); 7253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch j(equal, &done, Label::kNear); 7263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch mov(high, low); 7273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch xor_(low, low); 7283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch bind(&done); 7293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch} 7303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 7313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::ShrPair(Register high, Register low, uint8_t shift) { 7323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (shift >= 32) { 7333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch mov(low, high); 7343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch shr(low, shift - 32); 7353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch xor_(high, high); 7363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } else { 7373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch shrd(high, low, shift); 7383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch shr(high, shift); 7393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 7403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch} 7413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 7423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::ShrPair_cl(Register high, Register low) { 7433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch shrd_cl(low, high); 7443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch shr_cl(high); 7453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Label done; 7463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch test(ecx, Immediate(0x20)); 7473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch j(equal, &done, Label::kNear); 7483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch mov(low, high); 7493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch xor_(high, high); 7503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch bind(&done); 7513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch} 7523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 7533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::SarPair(Register high, Register low, uint8_t shift) { 7543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (shift >= 32) { 7553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch mov(low, high); 7563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch sar(low, shift - 32); 7573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch sar(high, 31); 7583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } else { 7593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch shrd(high, low, shift); 7603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch sar(high, shift); 7613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 7623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch} 7633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 7643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::SarPair_cl(Register high, Register low) { 7653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch shrd_cl(low, high); 7663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch sar_cl(high); 7673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Label done; 7683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch test(ecx, Immediate(0x20)); 7693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch j(equal, &done, Label::kNear); 7703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch mov(low, high); 7713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch sar(high, 31); 7723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch bind(&done); 7733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch} 774109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 775053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Blockbool MacroAssembler::IsUnsafeImmediate(const Immediate& x) { 776053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block static const int kMaxImmediateBits = 17; 777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!RelocInfo::IsNone(x.rmode_)) return false; 778053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block return !is_intn(x.x_, kMaxImmediateBits); 779053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block} 780053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block 781053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block 782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::SafeMove(Register dst, const Immediate& x) { 783053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block if (IsUnsafeImmediate(x) && jit_cookie() != 0) { 784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Move(dst, Immediate(x.x_ ^ jit_cookie())); 785053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block xor_(dst, jit_cookie()); 786053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block } else { 787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Move(dst, x); 788053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block } 789053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block} 790053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block 791053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block 792053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Blockvoid MacroAssembler::SafePush(const Immediate& x) { 793053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block if (IsUnsafeImmediate(x) && jit_cookie() != 0) { 794053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block push(Immediate(x.x_ ^ jit_cookie())); 795053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block xor_(Operand(esp, 0), Immediate(jit_cookie())); 796053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block } else { 797053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block push(x); 798053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block } 799053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block} 800053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block 801053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block 802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpObjectType(Register heap_object, 803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstanceType type, 804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register map) { 805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(map, FieldOperand(heap_object, HeapObject::kMapOffset)); 806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CmpInstanceType(map, type); 807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpInstanceType(Register map, InstanceType type) { 8113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch cmpb(FieldOperand(map, Map::kInstanceTypeOffset), Immediate(type)); 812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::CheckFastElements(Register map, 8163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label* fail, 8173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label::Distance distance) { 818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); 819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); 820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(FAST_ELEMENTS == 2); 821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3); 8223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmpb(FieldOperand(map, Map::kBitField2Offset), 8233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Immediate(Map::kMaximumBitField2FastHoleyElementValue)); 8243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(above, fail, distance); 8253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 8263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckFastObjectElements(Register map, 8293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* fail, 8303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance distance) { 831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); 832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); 833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(FAST_ELEMENTS == 2); 834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3); 8353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmpb(FieldOperand(map, Map::kBitField2Offset), 8363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Immediate(Map::kMaximumBitField2FastHoleySmiElementValue)); 8373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(below_equal, fail, distance); 8383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch cmpb(FieldOperand(map, Map::kBitField2Offset), 8393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Immediate(Map::kMaximumBitField2FastHoleyElementValue)); 8403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch j(above, fail, distance); 8413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 8423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 8433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CheckFastSmiElements(Register map, 845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fail, 846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label::Distance distance) { 847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); 848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); 8493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmpb(FieldOperand(map, Map::kBitField2Offset), 8503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Immediate(Map::kMaximumBitField2FastHoleySmiElementValue)); 8513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(above, fail, distance); 8523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 8533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::StoreNumberToDoubleElements( 8563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register maybe_number, 8573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register elements, 8583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register key, 8593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1, 8603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch XMMRegister scratch2, 8613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* fail, 862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int elements_offset) { 863014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label smi_value, done; 8643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JumpIfSmi(maybe_number, &smi_value, Label::kNear); 8653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckMap(maybe_number, 8673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate()->factory()->heap_number_map(), 8683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch fail, 8693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DONT_DO_SMI_CHECK); 8703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 871014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Double value, turn potential sNaN into qNaN. 872014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Move(scratch2, 1.0); 873014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mulsd(scratch2, FieldOperand(maybe_number, HeapNumber::kValueOffset)); 874014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch jmp(&done, Label::kNear); 8753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&smi_value); 8773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Value is a smi. Convert to a double and store. 8783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Preserve original value. 8793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(scratch1, maybe_number); 8803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiUntag(scratch1); 881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Cvtsi2sd(scratch2, scratch1); 882014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bind(&done); 883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch movsd(FieldOperand(elements, key, times_4, 884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FixedDoubleArray::kHeaderSize - elements_offset), 885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch scratch2); 8863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 8873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CompareMap(Register obj, Handle<Map> map) { 8903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmp(FieldOperand(obj, HeapObject::kMapOffset), map); 8913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 8923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::CheckMap(Register obj, 8953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Handle<Map> map, 8963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Label* fail, 897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SmiCheckType smi_check_type) { 898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (smi_check_type == DO_SMI_CHECK) { 899257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch JumpIfSmi(obj, fail); 9003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 9013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CompareMap(obj, map); 9033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu j(not_equal, fail); 9043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 9053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 907958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::DispatchWeakMap(Register obj, Register scratch1, 908958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch2, Handle<WeakCell> cell, 909958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<Code> success, 910958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier SmiCheckType smi_check_type) { 911257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label fail; 912257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (smi_check_type == DO_SMI_CHECK) { 913257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch JumpIfSmi(obj, &fail); 914257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 915958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier mov(scratch1, FieldOperand(obj, HeapObject::kMapOffset)); 916958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CmpWeakValue(scratch1, cell, scratch2); 917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(equal, success); 918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bind(&fail); 920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 923e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeCondition MacroAssembler::IsObjectStringType(Register heap_object, 924e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register map, 925e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register instance_type) { 926e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke mov(map, FieldOperand(heap_object, HeapObject::kMapOffset)); 927e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset)); 92869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kNotStringTag != 0); 929e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke test(instance_type, Immediate(kIsNotStringMask)); 930e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return zero; 931e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 932e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 933e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochCondition MacroAssembler::IsObjectNameType(Register heap_object, 935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register map, 936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register instance_type) { 937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(map, FieldOperand(heap_object, HeapObject::kMapOffset)); 938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset)); 9393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch cmpb(instance_type, Immediate(LAST_NAME_TYPE)); 940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return below_equal; 941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::FCmp() { 945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch fucomip(); 946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch fstp(0); 947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertNumber(Register object) { 951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (emit_debug_code()) { 952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label ok; 953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JumpIfSmi(object, &ok); 954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(FieldOperand(object, HeapObject::kMapOffset), 955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate()->factory()->heap_number_map()); 956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Check(equal, kOperandNotANumber); 957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bind(&ok); 9583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::AssertNotNumber(Register object) { 9623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (emit_debug_code()) { 9633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch test(object, Immediate(kSmiTagMask)); 9643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Check(not_equal, kOperandIsANumber); 9653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch cmp(FieldOperand(object, HeapObject::kMapOffset), 9663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch isolate()->factory()->heap_number_map()); 9673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Check(not_equal, kOperandIsANumber); 9683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 9693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch} 970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertSmi(Register object) { 972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (emit_debug_code()) { 973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch test(object, Immediate(kSmiTagMask)); 974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Check(equal, kOperandIsNotASmi); 975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertString(Register object) { 980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (emit_debug_code()) { 981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch test(object, Immediate(kSmiTagMask)); 982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Check(not_equal, kOperandIsASmiAndNotAString); 983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch push(object); 984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(object, FieldOperand(object, HeapObject::kMapOffset)); 985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CmpInstanceType(object, FIRST_NONSTRING_TYPE); 986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch pop(object); 987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Check(below, kOperandIsNotAString); 988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertName(Register object) { 993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (emit_debug_code()) { 994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch test(object, Immediate(kSmiTagMask)); 995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Check(not_equal, kOperandIsASmiAndNotAName); 996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch push(object); 997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(object, FieldOperand(object, HeapObject::kMapOffset)); 998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CmpInstanceType(object, LAST_NAME_TYPE); 999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch pop(object); 1000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Check(below_equal, kOperandIsNotAName); 1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1005014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::AssertFunction(Register object) { 1006014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (emit_debug_code()) { 1007014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch test(object, Immediate(kSmiTagMask)); 1008014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Check(not_equal, kOperandIsASmiAndNotAFunction); 1009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Push(object); 1010014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CmpObjectType(object, JS_FUNCTION_TYPE, object); 1011014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Pop(object); 1012014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Check(equal, kOperandIsNotAFunction); 1013014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1014014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 1015014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1016014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1017014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::AssertBoundFunction(Register object) { 1018014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (emit_debug_code()) { 1019014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch test(object, Immediate(kSmiTagMask)); 1020014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Check(not_equal, kOperandIsASmiAndNotABoundFunction); 1021014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Push(object); 1022014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CmpObjectType(object, JS_BOUND_FUNCTION_TYPE, object); 1023014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Pop(object); 1024014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Check(equal, kOperandIsNotABoundFunction); 1025014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1026014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 1027014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1028bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::AssertGeneratorObject(Register object) { 1029bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (emit_debug_code()) { 1030bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch test(object, Immediate(kSmiTagMask)); 1031bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Check(not_equal, kOperandIsASmiAndNotAGeneratorObject); 1032bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Push(object); 1033bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch CmpObjectType(object, JS_GENERATOR_OBJECT_TYPE, object); 1034bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Pop(object); 1035bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Check(equal, kOperandIsNotAGeneratorObject); 1036bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 1037bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1038014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1039109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::AssertReceiver(Register object) { 1040109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (emit_debug_code()) { 1041109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch test(object, Immediate(kSmiTagMask)); 1042109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Check(not_equal, kOperandIsASmiAndNotAReceiver); 1043109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Push(object); 1044109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); 1045109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CmpObjectType(object, FIRST_JS_RECEIVER_TYPE, object); 1046109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Pop(object); 1047109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Check(above_equal, kOperandIsNotAReceiver); 1048109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 1049109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 1050109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1051109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertUndefinedOrAllocationSite(Register object) { 1053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (emit_debug_code()) { 1054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done_checking; 1055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AssertNotSmi(object); 1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(object, isolate()->factory()->undefined_value()); 1057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch j(equal, &done_checking); 1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(FieldOperand(object, 0), 1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(isolate()->factory()->allocation_site_map())); 1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assert(equal, kExpectedUndefinedOrCell); 1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bind(&done_checking); 1062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1063402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 1064402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1065402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertNotSmi(Register object) { 1067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (emit_debug_code()) { 1068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch test(object, Immediate(kSmiTagMask)); 1069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Check(not_equal, kOperandIsASmi); 1070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1071756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick} 1072756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 10733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::StubPrologue(StackFrame::Type type) { 1074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch push(ebp); // Caller's frame pointer. 1075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(ebp, esp); 10763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch push(Immediate(Smi::FromInt(type))); 107780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 107880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Prologue(bool code_pre_aging) { 1080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PredictableCodeSizeScope predictible_code_size_scope(this, 1081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kNoCodeAgeSequenceLength); 1082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (code_pre_aging) { 1083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Pre-age the code. 1084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch call(isolate()->builtins()->MarkCodeAsExecutedOnce(), 1085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RelocInfo::CODE_AGE_SEQUENCE); 1086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Nop(kNoCodeAgeSequenceLength - Assembler::kCallInstructionLength); 1087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch push(ebp); // Caller's frame pointer. 1089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(ebp, esp); 1090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch push(esi); // Callee's context. 1091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch push(edi); // Callee's JS function. 1092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 10936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 10946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1096014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::EmitLoadTypeFeedbackVector(Register vector) { 1097014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mov(vector, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 1098014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mov(vector, FieldOperand(vector, JSFunction::kSharedFunctionInfoOffset)); 1099014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mov(vector, FieldOperand(vector, SharedFunctionInfo::kFeedbackVectorOffset)); 1100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 1101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1103958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::EnterFrame(StackFrame::Type type, 1104958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool load_constant_pool_pointer_reg) { 1105958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Out-of-line constant pool not implemented on ia32. 1106958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier UNREACHABLE(); 1107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 1108958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1109958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::EnterFrame(StackFrame::Type type) { 1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(ebp); 11123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(ebp, esp); 1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Immediate(Smi::FromInt(type))); 11143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (type == StackFrame::INTERNAL) { 11153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch push(Immediate(CodeObject())); 11163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 111744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 111844f0eee88ff00398ff7f715fab053374d808c90dSteve Block cmp(Operand(esp, 0), Immediate(isolate()->factory()->undefined_value())); 1119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Check(not_equal, kCodeObjectNotProperlyPatched); 1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LeaveFrame(StackFrame::Type type) { 112544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 11263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch cmp(Operand(ebp, CommonFrameConstants::kContextOrFrameTypeOffset), 1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(Smi::FromInt(type))); 1128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Check(equal, kStackFrameTypesMustMatch); 1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block leave(); 1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 113380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 113480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::EnterExitFramePrologue() { 11353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the frame structure on the stack. 11363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch DCHECK_EQ(+2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement); 11373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch DCHECK_EQ(+1 * kPointerSize, ExitFrameConstants::kCallerPCOffset); 11383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch DCHECK_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset); 1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(ebp); 11403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(ebp, esp); 1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 114280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Reserve room for entry stack pointer and push the code object. 11433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch push(Immediate(Smi::FromInt(StackFrame::EXIT))); 11443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch DCHECK_EQ(-2 * kPointerSize, ExitFrameConstants::kSPOffset); 1145402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu push(Immediate(0)); // Saved entry sp, patched before call. 11463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch DCHECK_EQ(-3 * kPointerSize, ExitFrameConstants::kCodeOffset); 1147402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu push(Immediate(CodeObject())); // Accessed from ExitFrame::code_slot. 1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save the frame pointer and the context in top. 1150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress, isolate()); 1151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference context_address(Isolate::kContextAddress, isolate()); 1152958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference c_function_address(Isolate::kCFunctionAddress, isolate()); 1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(Operand::StaticVariable(c_entry_fp_address), ebp); 1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(Operand::StaticVariable(context_address), esi); 1155958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier mov(Operand::StaticVariable(c_function_address), ebx); 1156d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid MacroAssembler::EnterExitFrameEpilogue(int argc, bool save_doubles) { 1160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Optionally save all XMM registers. 1161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (save_doubles) { 1162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int space = XMMRegister::kMaxNumRegisters * kDoubleSize + 1163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch argc * kPointerSize; 11643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch sub(esp, Immediate(space)); 11653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch const int offset = -ExitFrameConstants::kFixedFrameSizeFromFp; 1166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) { 1167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch XMMRegister reg = XMMRegister::from_code(i); 1168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch movsd(Operand(ebp, offset - ((i + 1) * kDoubleSize)), reg); 1169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 11713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch sub(esp, Immediate(argc * kPointerSize)); 1172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the required frame alignment for the OS. 1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kFrameAlignment = base::OS::ActivationFrameAlignment(); 1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (kFrameAlignment > 0) { 1177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(base::bits::IsPowerOfTwo32(kFrameAlignment)); 1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block and_(esp, -kFrameAlignment); 1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the saved entry sp. 1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(Operand(ebp, ExitFrameConstants::kSPOffset), esp); 1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1186109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::EnterExitFrame(int argc, bool save_doubles) { 118780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen EnterExitFramePrologue(); 1188d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 11893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up argc and argv in callee-saved registers. 1190d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; 11913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(edi, eax); 1192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block lea(esi, Operand(ebp, eax, times_4, offset)); 1193d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 119444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Reserve space for argc, argv and isolate. 1195109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch EnterExitFrameEpilogue(argc, save_doubles); 1196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1197d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 11998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid MacroAssembler::EnterApiExitFrame(int argc) { 120080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen EnterExitFramePrologue(); 1201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch EnterExitFrameEpilogue(argc, false); 1202d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1203d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LeaveExitFrame(bool save_doubles, bool pop_arguments) { 1206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Optionally restore all XMM registers. 1207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (save_doubles) { 12083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch const int offset = -ExitFrameConstants::kFixedFrameSizeFromFp; 1209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) { 1210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch XMMRegister reg = XMMRegister::from_code(i); 1211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch movsd(reg, Operand(ebp, offset - ((i + 1) * kDoubleSize))); 1212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (pop_arguments) { 1216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Get the return address from the stack and restore the frame pointer. 1217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mov(ecx, Operand(ebp, 1 * kPointerSize)); 1218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mov(ebp, Operand(ebp, 0 * kPointerSize)); 1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Pop the arguments and the receiver from the caller stack. 1221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch lea(esp, Operand(esi, 1 * kPointerSize)); 1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Push the return address to get ready to return. 1224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch push(ecx); 1225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 1226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Otherwise just leave the exit frame. 1227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch leave(); 1228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 12298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 1230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LeaveExitFrameEpilogue(true); 12318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang} 12328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 1233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::LeaveExitFrameEpilogue(bool restore_context) { 1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore current context from top and clear it in debug mode. 1236589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ExternalReference context_address(Isolate::kContextAddress, isolate()); 1237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (restore_context) { 1238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(esi, Operand::StaticVariable(context_address)); 1239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 1241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(Operand::StaticVariable(context_address), Immediate(0)); 1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Clear the top frame. 1245589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress, 124644f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()); 1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(Operand::StaticVariable(c_entry_fp_address), Immediate(0)); 1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::LeaveApiExitFrame(bool restore_context) { 12523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(esp, ebp); 12538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang pop(ebp); 12548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 1255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LeaveExitFrameEpilogue(restore_context); 12568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang} 12578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 12588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 1259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::PushStackHandler() { 1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Adjust this code if not the case. 1261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(StackHandlerConstants::kSize == 1 * kPointerSize); 126269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); 12633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 12643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Link the current handler as the next handler. 12653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference handler_address(Isolate::kHandlerAddress, isolate()); 12663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch push(Operand::StaticVariable(handler_address)); 1267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 12683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set this new handler as the current one. 12693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(Operand::StaticVariable(handler_address), esp); 1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::PopStackHandler() { 127469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); 12753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference handler_address(Isolate::kHandlerAddress, isolate()); 12763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch pop(Operand::StaticVariable(handler_address)); 12773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(esp, Immediate(StackHandlerConstants::kSize - kPointerSize)); 12783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 12793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 12803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, 1282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1, 1283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2, 1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label same_contexts; 1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!holder_reg.is(scratch1)); 1288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!holder_reg.is(scratch2)); 1289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!scratch1.is(scratch2)); 1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Load current lexical context from the active StandardFrame, which 12923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // may require crawling past STUB frames. 12933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Label load_context; 12943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Label has_context; 12953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch mov(scratch2, ebp); 12963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch bind(&load_context); 12973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch mov(scratch1, 12983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch MemOperand(scratch2, CommonFrameConstants::kContextOrFrameTypeOffset)); 12993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch JumpIfNotSmi(scratch1, &has_context); 13003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch mov(scratch2, MemOperand(scratch2, CommonFrameConstants::kCallerFPOffset)); 13013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch jmp(&load_context); 13023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch bind(&has_context); 1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // When generating debug code, make sure the lexical context is set. 130544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 1306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(scratch1, Immediate(0)); 1307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Check(not_equal, kWeShouldNotHaveAnEmptyLexicalContext); 1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the native context of the current context. 1310014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mov(scratch1, ContextOperand(scratch1, Context::NATIVE_CONTEXT_INDEX)); 1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check the context is a native context. 131344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 1314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Read the first word and compare to native_context_map. 1315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(FieldOperand(scratch1, HeapObject::kMapOffset), 1316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate()->factory()->native_context_map()); 1317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext); 1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if both contexts are the same. 1321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(scratch1, FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset)); 1322257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(equal, &same_contexts); 1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compare security tokens, save holder_reg on the stack so we can use it 1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // as a temporary register. 1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the security token in the calling global object is 1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // compatible with the security token in the receiving global 1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // object. 1330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(scratch2, 1331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset)); 1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check the context is a native context. 133444f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 1335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(scratch2, isolate()->factory()->null_value()); 1336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Check(not_equal, kJSGlobalProxyContextShouldNotBeNull); 1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Read the first word and compare to native_context_map(), 1339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(FieldOperand(scratch2, HeapObject::kMapOffset), 1340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate()->factory()->native_context_map()); 1341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext); 1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int token_offset = Context::kHeaderSize + 1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Context::SECURITY_TOKEN_INDEX * kPointerSize; 1346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(scratch1, FieldOperand(scratch1, token_offset)); 1347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(scratch1, FieldOperand(scratch2, token_offset)); 1348257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(not_equal, miss); 1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&same_contexts); 1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Compute the hash code from the untagged key. This must be kept in sync with 1355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ComputeIntegerHash in utils.h and KeyedLoadGenericStub in 1356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// code-stub-hydrogen.cc 1357c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch// 1358c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch// Note: r0 will contain hash code 1359c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdochvoid MacroAssembler::GetNumberHash(Register r0, Register scratch) { 1360c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // Xor original key with a seed. 1361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (serializer_enabled()) { 13623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference roots_array_start = 13633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference::roots_array_start(isolate()); 1364c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch mov(scratch, Immediate(Heap::kHashSeedRootIndex)); 13653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(scratch, 13663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand::StaticArray(scratch, times_pointer_size, roots_array_start)); 1367c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch SmiUntag(scratch); 13683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch xor_(r0, scratch); 1369c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch } else { 1370c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch int32_t seed = isolate()->heap()->HashSeed(); 13713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch xor_(r0, Immediate(seed)); 1372c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch } 1373c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 1374c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // hash = ~hash + (hash << 15); 1375c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch mov(scratch, r0); 1376c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch not_(r0); 1377c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch shl(scratch, 15); 13783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(r0, scratch); 1379c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // hash = hash ^ (hash >> 12); 1380c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch mov(scratch, r0); 1381c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch shr(scratch, 12); 13823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch xor_(r0, scratch); 1383c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // hash = hash + (hash << 2); 1384c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch lea(r0, Operand(r0, r0, times_4, 0)); 1385c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // hash = hash ^ (hash >> 4); 1386c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch mov(scratch, r0); 1387c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch shr(scratch, 4); 13883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch xor_(r0, scratch); 1389c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // hash = hash * 2057; 1390c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch imul(r0, r0, 2057); 1391c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // hash = hash ^ (hash >> 16); 1392c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch mov(scratch, r0); 1393c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch shr(scratch, 16); 13943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch xor_(r0, scratch); 1395014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch and_(r0, 0x3fffffff); 1396c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch} 1397c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 1398c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 1399c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 14003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::LoadFromNumberDictionary(Label* miss, 14013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register elements, 14023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register key, 14033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register r0, 14043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register r1, 14053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register r2, 14063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register result) { 14073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Register use: 14083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // 14093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // elements - holds the slow-case elements of the receiver and is unchanged. 14103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // 14113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // key - holds the smi key on entry and is unchanged. 14123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // 14133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Scratch registers: 14143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // 14153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // r0 - holds the untagged key on entry and holds the hash once computed. 14163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // 14173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // r1 - used to hold the capacity mask of the dictionary 14183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // 14193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // r2 - used for the index into the dictionary. 14203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // 14213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // result - holds the result on exit if the load succeeds and we fall through. 14223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 14233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label done; 14243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 1425c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch GetNumberHash(r0, r1); 14263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 14273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Compute capacity mask. 1428c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch mov(r1, FieldOperand(elements, SeededNumberDictionary::kCapacityOffset)); 14293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch shr(r1, kSmiTagSize); // convert smi to int 14303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch dec(r1); 14313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 14323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Generate an unrolled loop that performs a few probes before giving up. 1433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < kNumberDictionaryProbes; i++) { 14343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Use r2 for index calculations and keep the hash intact in r0. 14353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch mov(r2, r0); 14363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Compute the masked index: (hash + i + i * i) & mask. 14373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (i > 0) { 14383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(r2, Immediate(SeededNumberDictionary::GetProbeOffset(i))); 14393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 14403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(r2, r1); 14413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 14423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Scale the index by multiplying by the entry size. 1443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(SeededNumberDictionary::kEntrySize == 3); 14443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3 14453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 14463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check if the key matches. 14473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch cmp(key, FieldOperand(elements, 14483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch r2, 14493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch times_pointer_size, 1450c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch SeededNumberDictionary::kElementsStartOffset)); 1451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (i != (kNumberDictionaryProbes - 1)) { 14523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch j(equal, &done); 14533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 14543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch j(not_equal, miss); 14553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 14563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 14573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 14583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bind(&done); 1459958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that the value is a field property. 14603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch const int kDetailsOffset = 1461c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize; 1462014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_EQ(DATA, 0); 14633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset), 1464589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Immediate(PropertyDetails::TypeField::kMask << kSmiTagSize)); 14653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch j(not_zero, miss); 14663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 14673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Get the value at the masked, scaled index. 14683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch const int kValueOffset = 1469c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch SeededNumberDictionary::kElementsStartOffset + kPointerSize; 14703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch mov(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); 14713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 14723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 14733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LoadAllocationTopHelper(Register result, 1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags) { 1477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference allocation_top = 1478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationUtils::GetAllocationTopReference(isolate(), flags); 1479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Just return if allocation top is already known. 1481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((flags & RESULT_CONTAINS_TOP) != 0) { 1482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // No use of scratch if allocation top is provided. 1483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(scratch.is(no_reg)); 1484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 1485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Assert that result actually contains top on entry. 1486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(result, Operand::StaticVariable(allocation_top)); 1487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Check(equal, kUnexpectedAllocationTop); 1488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 1490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Move address of new object to result. Use scratch register if available. 1493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (scratch.is(no_reg)) { 1494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(result, Operand::StaticVariable(allocation_top)); 1495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(scratch, Immediate(allocation_top)); 1497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(result, Operand(scratch, 0)); 1498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::UpdateAllocationTopHelper(Register result_end, 1503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch, 1504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationFlags flags) { 150544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 1506d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block test(result_end, Immediate(kObjectAlignmentMask)); 1507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Check(zero, kUnalignedAllocationInNewSpace); 1508d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1509d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference allocation_top = 1511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationUtils::GetAllocationTopReference(isolate(), flags); 1512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update new top. Use scratch if available. 1514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (scratch.is(no_reg)) { 1515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(Operand::StaticVariable(allocation_top), result_end); 1516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(Operand(scratch, 0), result_end); 1518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Allocate(int object_size, 1523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result, 1524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result_end, 1525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch, 1526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* gc_required, 1527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationFlags flags) { 1528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0); 1529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(object_size <= Page::kMaxRegularHeapObjectSize); 1530bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK((flags & ALLOCATION_FOLDED) == 0); 15315913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!FLAG_inline_new) { 153244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 15335913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // Trash the registers to simulate an allocation failure. 15345913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck mov(result, Immediate(0x7091)); 15355913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (result_end.is_valid()) { 15365913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck mov(result_end, Immediate(0x7191)); 15375913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 15385913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (scratch.is_valid()) { 15395913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck mov(scratch, Immediate(0x7291)); 15405913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 15415913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 15425913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck jmp(gc_required); 15435913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck return; 15445913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 1545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!result.is(result_end)); 1546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load address of new object into result. 15488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang LoadAllocationTopHelper(result, scratch, flags); 1549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference allocation_limit = 1551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationUtils::GetAllocationLimitReference(isolate(), flags); 1552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Align the next allocation. Storing the filler map without checking top is 1554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // safe in new-space because the limit of the heap is aligned there. 1555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((flags & DOUBLE_ALIGNMENT) != 0) { 1556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(kPointerAlignment * 2 == kDoubleAlignment); 1557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label aligned; 1558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch test(result, Immediate(kDoubleAlignmentMask)); 1559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch j(zero, &aligned, Label::kNear); 1560014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if ((flags & PRETENURE) != 0) { 1561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(result, Operand::StaticVariable(allocation_limit)); 1562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch j(above_equal, gc_required); 1563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(Operand(result, 0), 1565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(isolate()->factory()->one_pointer_filler_map())); 1566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch add(result, Immediate(kDoubleSize / 2)); 1567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bind(&aligned); 1568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Calculate new top and bail out if space is exhausted. 1571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register top_reg = result_end.is_valid() ? result_end : result; 1572bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 15731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (!top_reg.is(result)) { 15741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block mov(top_reg, result); 1575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 15763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(top_reg, Immediate(object_size)); 1577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(top_reg, Operand::StaticVariable(allocation_limit)); 1578257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(above, gc_required); 1579e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1580bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) { 1581bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // The top pointer is not updated for allocation folding dominators. 1582bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch UpdateAllocationTopHelper(top_reg, scratch, flags); 1583bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 1584bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 1585bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if (top_reg.is(result)) { 1586bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch sub(result, Immediate(object_size - kHeapObjectTag)); 1587bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } else { 1588bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Tag the result. 1589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(kHeapObjectTag == 1); 1590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inc(result); 1591bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } 1592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Allocate(int header_size, 1596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ScaleFactor element_size, 1597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register element_count, 1598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RegisterValueType element_count_type, 1599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result, 1600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result_end, 1601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch, 1602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* gc_required, 1603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationFlags flags) { 1604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((flags & SIZE_IN_WORDS) == 0); 1605bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK((flags & ALLOCATION_FOLDING_DOMINATOR) == 0); 1606bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK((flags & ALLOCATION_FOLDED) == 0); 16075913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!FLAG_inline_new) { 160844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 16095913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // Trash the registers to simulate an allocation failure. 16105913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck mov(result, Immediate(0x7091)); 16115913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck mov(result_end, Immediate(0x7191)); 16125913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (scratch.is_valid()) { 16135913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck mov(scratch, Immediate(0x7291)); 16145913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 16155913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // Register element_count is not modified by the function. 16165913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 16175913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck jmp(gc_required); 16185913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck return; 16195913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 1620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!result.is(result_end)); 1621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load address of new object into result. 16238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang LoadAllocationTopHelper(result, scratch, flags); 1624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference allocation_limit = 1626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationUtils::GetAllocationLimitReference(isolate(), flags); 1627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Align the next allocation. Storing the filler map without checking top is 1629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // safe in new-space because the limit of the heap is aligned there. 1630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((flags & DOUBLE_ALIGNMENT) != 0) { 1631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(kPointerAlignment * 2 == kDoubleAlignment); 1632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label aligned; 1633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch test(result, Immediate(kDoubleAlignmentMask)); 1634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch j(zero, &aligned, Label::kNear); 1635014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if ((flags & PRETENURE) != 0) { 1636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(result, Operand::StaticVariable(allocation_limit)); 1637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch j(above_equal, gc_required); 1638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(Operand(result, 0), 1640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(isolate()->factory()->one_pointer_filler_map())); 1641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch add(result, Immediate(kDoubleSize / 2)); 1642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bind(&aligned); 1643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 16441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Calculate new top and bail out if space is exhausted. 16461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // We assume that element_count*element_size + header_size does not 16471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // overflow. 1648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (element_count_type == REGISTER_VALUE_IS_SMI) { 1649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(static_cast<ScaleFactor>(times_2 - 1) == times_1); 1650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(static_cast<ScaleFactor>(times_4 - 1) == times_2); 1651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(static_cast<ScaleFactor>(times_8 - 1) == times_4); 1652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(element_size >= times_2); 1653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(kSmiTagSize == 1); 1654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch element_size = static_cast<ScaleFactor>(element_size - 1); 1655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(element_count_type == REGISTER_VALUE_IS_INT32); 1657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1658bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 16591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block lea(result_end, Operand(element_count, element_size, header_size)); 16603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(result_end, result); 1661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(result_end, Operand::StaticVariable(allocation_limit)); 1662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(above, gc_required); 1663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1664bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Tag result. 1665bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK(kHeapObjectTag == 1); 1666bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch inc(result); 1667e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UpdateAllocationTopHelper(result_end, scratch, flags); 1669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Allocate(Register object_size, 1673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result, 1674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result_end, 1675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch, 1676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* gc_required, 1677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationFlags flags) { 1678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0); 1679bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK((flags & ALLOCATION_FOLDED) == 0); 16805913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!FLAG_inline_new) { 168144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 16825913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // Trash the registers to simulate an allocation failure. 16835913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck mov(result, Immediate(0x7091)); 16845913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck mov(result_end, Immediate(0x7191)); 16855913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (scratch.is_valid()) { 16865913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck mov(scratch, Immediate(0x7291)); 16875913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 16885913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // object_size is left unchanged by this function. 16895913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 16905913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck jmp(gc_required); 16915913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck return; 16925913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 1693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!result.is(result_end)); 1694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load address of new object into result. 16968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang LoadAllocationTopHelper(result, scratch, flags); 1697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference allocation_limit = 1699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationUtils::GetAllocationLimitReference(isolate(), flags); 1700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Align the next allocation. Storing the filler map without checking top is 1702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // safe in new-space because the limit of the heap is aligned there. 1703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((flags & DOUBLE_ALIGNMENT) != 0) { 1704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(kPointerAlignment * 2 == kDoubleAlignment); 1705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label aligned; 1706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch test(result, Immediate(kDoubleAlignmentMask)); 1707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch j(zero, &aligned, Label::kNear); 1708014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if ((flags & PRETENURE) != 0) { 1709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(result, Operand::StaticVariable(allocation_limit)); 1710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch j(above_equal, gc_required); 1711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(Operand(result, 0), 1713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(isolate()->factory()->one_pointer_filler_map())); 1714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch add(result, Immediate(kDoubleSize / 2)); 1715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bind(&aligned); 1716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Calculate new top and bail out if space is exhausted. 1719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!object_size.is(result_end)) { 1720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(result_end, object_size); 1721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 17223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(result_end, result); 1723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(result_end, Operand::StaticVariable(allocation_limit)); 1724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(above, gc_required); 1725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1726bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Tag result. 1727bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK(kHeapObjectTag == 1); 1728bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch inc(result); 1729bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1730bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) { 1731bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // The top pointer is not updated for allocation folding dominators. 1732bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch UpdateAllocationTopHelper(result_end, scratch, flags); 1733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1734bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1735e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1736bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::FastAllocate(int object_size, Register result, 1737bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register result_end, AllocationFlags flags) { 1738bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK(!result.is(result_end)); 1739bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Load address of new object into result. 1740bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch LoadAllocationTopHelper(result, no_reg, flags); 1741bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1742bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if ((flags & DOUBLE_ALIGNMENT) != 0) { 1743bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK(kPointerAlignment * 2 == kDoubleAlignment); 1744bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label aligned; 1745bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch test(result, Immediate(kDoubleAlignmentMask)); 1746bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch j(zero, &aligned, Label::kNear); 1747bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch mov(Operand(result, 0), 1748bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Immediate(isolate()->factory()->one_pointer_filler_map())); 1749bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch add(result, Immediate(kDoubleSize / 2)); 1750bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch bind(&aligned); 1751bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 1752bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1753bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch lea(result_end, Operand(result, object_size)); 1754bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch UpdateAllocationTopHelper(result_end, no_reg, flags); 1755bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1756bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK(kHeapObjectTag == 1); 1757bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch inc(result); 1758bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1759bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1760bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::FastAllocate(Register object_size, Register result, 1761bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register result_end, AllocationFlags flags) { 1762bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK(!result.is(result_end)); 1763bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Load address of new object into result. 1764bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch LoadAllocationTopHelper(result, no_reg, flags); 1765bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1766bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if ((flags & DOUBLE_ALIGNMENT) != 0) { 1767bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK(kPointerAlignment * 2 == kDoubleAlignment); 1768bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label aligned; 1769bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch test(result, Immediate(kDoubleAlignmentMask)); 1770bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch j(zero, &aligned, Label::kNear); 1771bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch mov(Operand(result, 0), 1772bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Immediate(isolate()->factory()->one_pointer_filler_map())); 1773bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch add(result, Immediate(kDoubleSize / 2)); 1774bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch bind(&aligned); 1775bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 1776bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1777bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch lea(result_end, Operand(result, object_size, times_1, 0)); 1778bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch UpdateAllocationTopHelper(result_end, no_reg, flags); 1779bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1780bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK(kHeapObjectTag == 1); 1781bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch inc(result); 1782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 17853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::AllocateHeapNumber(Register result, 17863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register scratch1, 17873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register scratch2, 1788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* gc_required, 1789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MutableMode mode) { 17903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Allocate heap number in new space. 1791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Allocate(HeapNumber::kSize, result, scratch1, scratch2, gc_required, 1792bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch NO_ALLOCATION_FLAGS); 1793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> map = mode == MUTABLE 1795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? isolate()->factory()->mutable_heap_number_map() 1796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : isolate()->factory()->heap_number_map(); 17973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 17983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Set the map. 1799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(FieldOperand(result, HeapObject::kMapOffset), Immediate(map)); 18003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 18013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 18023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1803d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::AllocateTwoByteString(Register result, 1804d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register length, 1805d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch1, 1806d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch2, 1807d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch3, 1808d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label* gc_required) { 1809d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Calculate the number of bytes needed for the characters in the string while 1810d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // observing object alignment. 1811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); 1812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(kShortSize == 2); 1813e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // scratch1 = length * 2 + kObjectAlignmentMask. 1814e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke lea(scratch1, Operand(length, length, times_1, kObjectAlignmentMask)); 18153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(scratch1, Immediate(~kObjectAlignmentMask)); 1816d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1817d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Allocate two byte string in new space. 1818bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Allocate(SeqTwoByteString::kHeaderSize, times_1, scratch1, 1819bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch REGISTER_VALUE_IS_INT32, result, scratch2, scratch3, gc_required, 1820bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch NO_ALLOCATION_FLAGS); 1821d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1822d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Set the map, length and hash field. 1823d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mov(FieldOperand(result, HeapObject::kMapOffset), 182444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Immediate(isolate()->factory()->string_map())); 18256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block mov(scratch1, length); 18266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block SmiTag(scratch1); 18276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block mov(FieldOperand(result, String::kLengthOffset), scratch1); 1828d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mov(FieldOperand(result, String::kHashFieldOffset), 1829d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Immediate(String::kEmptyHashField)); 1830d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1831d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1832d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AllocateOneByteString(Register result, Register length, 1834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1, Register scratch2, 1835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch3, 1836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* gc_required) { 1837d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Calculate the number of bytes needed for the characters in the string while 1838d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // observing object alignment. 1839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0); 1840d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mov(scratch1, length); 1841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(kCharSize == 1); 18423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(scratch1, Immediate(kObjectAlignmentMask)); 18433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(scratch1, Immediate(~kObjectAlignmentMask)); 1844d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Allocate one-byte string in new space. 1846bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Allocate(SeqOneByteString::kHeaderSize, times_1, scratch1, 1847bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch REGISTER_VALUE_IS_INT32, result, scratch2, scratch3, gc_required, 1848bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch NO_ALLOCATION_FLAGS); 1849d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1850d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Set the map, length and hash field. 1851d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mov(FieldOperand(result, HeapObject::kMapOffset), 1852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(isolate()->factory()->one_byte_string_map())); 18536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block mov(scratch1, length); 18546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block SmiTag(scratch1); 18556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block mov(FieldOperand(result, String::kLengthOffset), scratch1); 1856d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mov(FieldOperand(result, String::kHashFieldOffset), 1857d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Immediate(String::kEmptyHashField)); 1858d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1859d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1860d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AllocateOneByteString(Register result, int length, 1862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1, Register scratch2, 1863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* gc_required) { 1864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(length > 0); 18659ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick 1866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Allocate one-byte string in new space. 1867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Allocate(SeqOneByteString::SizeFor(length), result, scratch1, scratch2, 1868bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch gc_required, NO_ALLOCATION_FLAGS); 18699ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick 18709ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick // Set the map, length and hash field. 18719ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick mov(FieldOperand(result, HeapObject::kMapOffset), 1872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(isolate()->factory()->one_byte_string_map())); 18739ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick mov(FieldOperand(result, String::kLengthOffset), 18749ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick Immediate(Smi::FromInt(length))); 18759ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick mov(FieldOperand(result, String::kHashFieldOffset), 18769ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick Immediate(String::kEmptyHashField)); 18779ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick} 18789ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick 18799ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick 1880589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid MacroAssembler::AllocateTwoByteConsString(Register result, 1881d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch1, 1882d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch2, 1883d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label* gc_required) { 1884d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Allocate heap number in new space. 1885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required, 1886bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch NO_ALLOCATION_FLAGS); 1887d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1888d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Set the map. The other fields are left uninitialized. 1889d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mov(FieldOperand(result, HeapObject::kMapOffset), 189044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Immediate(isolate()->factory()->cons_string_map())); 1891d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1892d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1893d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AllocateOneByteConsString(Register result, 1895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1, 1896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2, 1897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* gc_required) { 1898bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required, 1899bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch NO_ALLOCATION_FLAGS); 1900d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1901d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Set the map. The other fields are left uninitialized. 1902d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mov(FieldOperand(result, HeapObject::kMapOffset), 1903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(isolate()->factory()->cons_one_byte_string_map())); 1904d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1905d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1906b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1907589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid MacroAssembler::AllocateTwoByteSlicedString(Register result, 190869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Register scratch1, 190969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Register scratch2, 191069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Label* gc_required) { 191169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Allocate heap number in new space. 1912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required, 1913bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch NO_ALLOCATION_FLAGS); 191469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 191569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Set the map. The other fields are left uninitialized. 191669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch mov(FieldOperand(result, HeapObject::kMapOffset), 191769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Immediate(isolate()->factory()->sliced_string_map())); 191869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch} 191969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 192069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 1921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AllocateOneByteSlicedString(Register result, 1922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1, 1923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2, 1924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* gc_required) { 192569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Allocate heap number in new space. 1926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required, 1927bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch NO_ALLOCATION_FLAGS); 192869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 192969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Set the map. The other fields are left uninitialized. 193069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch mov(FieldOperand(result, HeapObject::kMapOffset), 1931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(isolate()->factory()->sliced_one_byte_string_map())); 193269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch} 193369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 193469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 1935014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::AllocateJSValue(Register result, Register constructor, 1936014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register value, Register scratch, 1937014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label* gc_required) { 1938014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!result.is(constructor)); 1939014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!result.is(scratch)); 1940014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!result.is(value)); 1941014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1942014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Allocate JSValue in new space. 1943bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Allocate(JSValue::kSize, result, scratch, no_reg, gc_required, 1944bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch NO_ALLOCATION_FLAGS); 1945014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1946014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Initialize the JSValue. 1947014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LoadGlobalFunctionInitialMap(constructor, scratch); 1948014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mov(FieldOperand(result, HeapObject::kMapOffset), scratch); 1949014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LoadRoot(scratch, Heap::kEmptyFixedArrayRootIndex); 1950014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mov(FieldOperand(result, JSObject::kPropertiesOffset), scratch); 1951014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mov(FieldOperand(result, JSObject::kElementsOffset), scratch); 1952014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mov(FieldOperand(result, JSValue::kValueOffset), value); 1953014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize); 1954014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 1955014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1956014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1957b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// Copy memory, byte-by-byte, from source to destination. Not optimized for 1958b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// long or aligned copies. The contents of scratch and length are destroyed. 1959b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// Source and destination are incremented by length. 1960b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// Many variants of movsb, loop unrolling, word moves, and indexed operands 1961b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// have been tried here already, and this is fastest. 1962b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// A simpler loop is faster on small copies, but 30% slower on large ones. 1963b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// The cld() instruction must have been emitted, to set the direction flag(), 1964b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// before calling this function. 1965b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid MacroAssembler::CopyBytes(Register source, 1966b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register destination, 1967b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register length, 1968b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register scratch) { 1969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label short_loop, len4, len8, len12, done, short_string; 1970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(source.is(esi)); 1971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(destination.is(edi)); 1972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(length.is(ecx)); 1973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(length, Immediate(4)); 1974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch j(below, &short_string, Label::kNear); 1975b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1976b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Because source is 4-byte aligned in our uses of this function, 1977b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // we keep source aligned for the rep_movs call by copying the odd bytes 1978b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // at the end of the ranges. 1979b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch mov(scratch, Operand(source, length, times_1, -4)); 1980b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch mov(Operand(destination, length, times_1, -4), scratch); 1981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(length, Immediate(8)); 1983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch j(below_equal, &len4, Label::kNear); 1984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(length, Immediate(12)); 1985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch j(below_equal, &len8, Label::kNear); 1986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(length, Immediate(16)); 1987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch j(below_equal, &len12, Label::kNear); 1988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1989b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch mov(scratch, ecx); 1990b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch shr(ecx, 2); 1991b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch rep_movs(); 19923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(scratch, Immediate(0x3)); 19933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(destination, scratch); 1994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch jmp(&done, Label::kNear); 1995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bind(&len12); 1997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(scratch, Operand(source, 8)); 1998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(Operand(destination, 8), scratch); 1999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bind(&len8); 2000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(scratch, Operand(source, 4)); 2001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(Operand(destination, 4), scratch); 2002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bind(&len4); 2003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(scratch, Operand(source, 0)); 2004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(Operand(destination, 0), scratch); 2005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch add(destination, length); 2006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch jmp(&done, Label::kNear); 2007b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2008b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch bind(&short_string); 20093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test(length, length); 2010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch j(zero, &done, Label::kNear); 2011b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2012b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch bind(&short_loop); 2013b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch mov_b(scratch, Operand(source, 0)); 2014b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch mov_b(Operand(destination, 0), scratch); 2015b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch inc(source); 2016b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch inc(destination); 2017b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch dec(length); 2018b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch j(not_zero, &short_loop); 2019b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2020b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch bind(&done); 20218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang} 20228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 2023d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2024014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::InitializeFieldsWithFiller(Register current_address, 2025014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register end_address, 20263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register filler) { 20273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label loop, entry; 2028109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch jmp(&entry, Label::kNear); 20293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&loop); 2030014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mov(Operand(current_address, 0), filler); 2031014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch add(current_address, Immediate(kPointerSize)); 20323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&entry); 2033014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch cmp(current_address, end_address); 2034109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch j(below, &loop, Label::kNear); 20353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 20363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 20373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 20383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::BooleanBitTest(Register object, 20393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int field_offset, 20403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int bit_index) { 20413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bit_index += kSmiTagSize + kSmiShiftSize; 2042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(base::bits::IsPowerOfTwo32(kBitsPerByte)); 20433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int byte_index = bit_index / kBitsPerByte; 20443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int byte_bit_index = bit_index & (kBitsPerByte - 1); 20453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test_b(FieldOperand(object, field_offset + byte_index), 20463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Immediate(1 << byte_bit_index)); 20473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 20483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 20493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 20503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::NegativeZeroTest(Register result, 2052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register op, 2053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* then_label) { 2054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label ok; 20553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test(result, result); 2056109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch j(not_zero, &ok, Label::kNear); 20573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test(op, op); 2058109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch j(sign, then_label, Label::kNear); 2059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&ok); 2060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::NegativeZeroTest(Register result, 2064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register op1, 2065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register op2, 2066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 2067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* then_label) { 2068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label ok; 20693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test(result, result); 2070109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch j(not_zero, &ok, Label::kNear); 20713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(scratch, op1); 20723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch or_(scratch, op2); 2073109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch j(sign, then_label, Label::kNear); 2074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&ok); 2075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2078014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::GetMapConstructor(Register result, Register map, 2079014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register temp) { 2080014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label done, loop; 2081014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mov(result, FieldOperand(map, Map::kConstructorOrBackPointerOffset)); 2082014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bind(&loop); 2083014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JumpIfSmi(result, &done, Label::kNear); 2084014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CmpObjectType(result, MAP_TYPE, temp); 2085014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch j(not_equal, &done, Label::kNear); 2086014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mov(result, FieldOperand(result, Map::kConstructorOrBackPointerOffset)); 2087014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch jmp(&loop); 2088014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bind(&done); 2089014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 20903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2092014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::TryGetFunctionPrototype(Register function, Register result, 2093014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register scratch, Label* miss) { 2094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the prototype or initial map from the function. 2095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(result, 2096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 2097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the prototype or initial map is the hole, don't return it and 2099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // simply miss the cache instead. This will allow us to allocate a 2100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // prototype object on-demand in the runtime system. 21013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmp(result, Immediate(isolate()->factory()->the_hole_value())); 2102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(equal, miss); 2103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the function does not have an initial map, we're done. 2105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label done; 2106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CmpObjectType(result, MAP_TYPE, scratch); 2107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch j(not_equal, &done, Label::kNear); 2108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the prototype from the initial map. 2110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(result, FieldOperand(result, Map::kPrototypeOffset)); 2111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // All done. 2113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&done); 2114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CallStub(CodeStub* stub, TypeFeedbackId ast_id) { 2118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(AllowThisStubCall(stub)); // Calls are not allowed in some stubs. 2119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id); 2120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2123d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::TailCallStub(CodeStub* stub) { 2124d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block jmp(stub->GetCode(), RelocInfo::CODE_TARGET); 2125d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2126d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2127d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 212885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochvoid MacroAssembler::StubReturn(int argc) { 2129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(argc >= 1 && generating_stub()); 213085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch ret((argc - 1) * kPointerSize); 2131592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch} 2132592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 2133592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 21343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool MacroAssembler::AllowThisStubCall(CodeStub* stub) { 2135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return has_frame_ || !stub->SometimesSetsUpAFrame(); 2136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 213980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::IndexFromHash(Register hash, Register index) { 214080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // The assert checks that the constants for the maximum number of digits 214180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // for an array index cached in the hash field and the number of bits 214280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // reserved for it does not conflict. 2143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(TenToThe(String::kMaxCachedArrayIndexLength) < 214480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen (1 << String::kArrayIndexValueBits)); 214580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (!index.is(hash)) { 214680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen mov(index, hash); 214780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 2148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DecodeFieldToSmi<String::ArrayIndexValueBits>(index); 2149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 215244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CallRuntime(const Runtime::Function* f, 2153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int num_arguments, 2154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SaveFPRegsMode save_doubles) { 2155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the expected number of arguments of the runtime function is 2156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // constant, we check that the actual number of arguments match the 2157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // expectation. 2158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(f->nargs < 0 || f->nargs == num_arguments); 2159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 21604515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // TODO(1236192): Most runtime routines don't need the number of 21614515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // arguments passed in because it is constant. At some point we 21624515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // should remove this need and make the runtime routine entry code 21634515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // smarter. 2164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Move(eax, Immediate(num_arguments)); 216544f0eee88ff00398ff7f715fab053374d808c90dSteve Block mov(ebx, Immediate(ExternalReference(f, isolate()))); 2166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CEntryStub ces(isolate(), 1, save_doubles); 21674515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke CallStub(&ces); 2168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2171bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid MacroAssembler::CallExternalReference(ExternalReference ref, 2172bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch int num_arguments) { 2173bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch mov(eax, Immediate(num_arguments)); 2174bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch mov(ebx, Immediate(ref)); 2175bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 2176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CEntryStub stub(isolate(), 1); 2177bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch CallStub(&stub); 2178bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 2179bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 2180bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 2181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::TailCallRuntime(Runtime::FunctionId fid) { 2182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 2183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[0] : return address 2184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[8] : argument num_arguments - 1 2185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ... 2186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[8 * num_arguments] : argument 0 (receiver) 2187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 2188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // For runtime functions with variable arguments: 2189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : number of arguments 2190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 21913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const Runtime::Function* function = Runtime::FunctionForId(fid); 2193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_EQ(1, function->result_size); 2194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (function->nargs >= 0) { 2195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // TODO(1236192): Most runtime routines don't need the number of 2196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // arguments passed in because it is constant. At some point we 2197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // should remove this need and make the runtime routine entry code 2198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // smarter. 2199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mov(eax, Immediate(function->nargs)); 2200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JumpToExternalReference(ExternalReference(fid, isolate())); 2202d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2203d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 22056ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::JumpToExternalReference(const ExternalReference& ext) { 2206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the entry point and jump to the C entry runtime stub. 2207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(ebx, Immediate(ext)); 2208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CEntryStub ces(isolate(), 1); 2209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block jmp(ces.GetCode(), RelocInfo::CODE_TARGET); 2210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 22123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::PrepareForTailCall( 22133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch const ParameterCount& callee_args_count, Register caller_args_count_reg, 22143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Register scratch0, Register scratch1, ReturnAddressState ra_state, 22153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch int number_of_temp_values_after_return_address) { 22163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#if DEBUG 22173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (callee_args_count.is_reg()) { 22183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch DCHECK(!AreAliased(callee_args_count.reg(), caller_args_count_reg, scratch0, 22193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch scratch1)); 22203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } else { 22213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch DCHECK(!AreAliased(caller_args_count_reg, scratch0, scratch1)); 22223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 22233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch DCHECK(ra_state != ReturnAddressState::kNotOnStack || 22243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch number_of_temp_values_after_return_address == 0); 22253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#endif 22263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 22273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Calculate the destination address where we will put the return address 22283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // after we drop current frame. 22293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Register new_sp_reg = scratch0; 22303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (callee_args_count.is_reg()) { 22313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch sub(caller_args_count_reg, callee_args_count.reg()); 22323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch lea(new_sp_reg, 22333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Operand(ebp, caller_args_count_reg, times_pointer_size, 22343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch StandardFrameConstants::kCallerPCOffset - 22353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch number_of_temp_values_after_return_address * kPointerSize)); 22363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } else { 22373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch lea(new_sp_reg, Operand(ebp, caller_args_count_reg, times_pointer_size, 22383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch StandardFrameConstants::kCallerPCOffset - 22393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch (callee_args_count.immediate() + 22403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch number_of_temp_values_after_return_address) * 22413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch kPointerSize)); 22423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 22433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 22443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (FLAG_debug_code) { 22453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch cmp(esp, new_sp_reg); 22463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Check(below, kStackAccessBelowStackPointer); 22473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 22483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 22493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Copy return address from caller's frame to current frame's return address 22503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // to avoid its trashing and let the following loop copy it to the right 22513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // place. 22523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Register tmp_reg = scratch1; 22533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (ra_state == ReturnAddressState::kOnStack) { 22543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch mov(tmp_reg, Operand(ebp, StandardFrameConstants::kCallerPCOffset)); 22553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch mov(Operand(esp, number_of_temp_values_after_return_address * kPointerSize), 22563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch tmp_reg); 22573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } else { 22583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch DCHECK(ReturnAddressState::kNotOnStack == ra_state); 22593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch DCHECK_EQ(0, number_of_temp_values_after_return_address); 22603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Push(Operand(ebp, StandardFrameConstants::kCallerPCOffset)); 22613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 22623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 22633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Restore caller's frame pointer now as it could be overwritten by 22643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // the copying loop. 22653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch mov(ebp, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 22663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 22673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // +2 here is to copy both receiver and return address. 22683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Register count_reg = caller_args_count_reg; 22693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (callee_args_count.is_reg()) { 22703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch lea(count_reg, Operand(callee_args_count.reg(), 22713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 2 + number_of_temp_values_after_return_address)); 22723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } else { 22733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch mov(count_reg, Immediate(callee_args_count.immediate() + 2 + 22743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch number_of_temp_values_after_return_address)); 22753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // TODO(ishell): Unroll copying loop for small immediate values. 22763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 22773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 22783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Now copy callee arguments to the caller frame going backwards to avoid 22793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // callee arguments corruption (source and destination areas could overlap). 22803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Label loop, entry; 22813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch jmp(&entry, Label::kNear); 22823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch bind(&loop); 22833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch dec(count_reg); 22843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch mov(tmp_reg, Operand(esp, count_reg, times_pointer_size, 0)); 22853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch mov(Operand(new_sp_reg, count_reg, times_pointer_size, 0), tmp_reg); 22863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch bind(&entry); 22873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch cmp(count_reg, Immediate(0)); 22883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch j(not_equal, &loop, Label::kNear); 22893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 22903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Leave current frame. 22913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch mov(esp, new_sp_reg); 22923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch} 2293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokePrologue(const ParameterCount& expected, 2295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 2296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* done, 22973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool* definitely_mismatches, 2298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InvokeFlag flag, 2299257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance done_near, 2300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CallWrapper& call_wrapper) { 2301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool definitely_matches = false; 23023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *definitely_mismatches = false; 2303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label invoke; 2304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (expected.is_immediate()) { 2305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(actual.is_immediate()); 2306014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mov(eax, actual.immediate()); 2307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (expected.immediate() == actual.immediate()) { 2308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block definitely_matches = true; 2309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 2310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel; 2311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (expected.immediate() == sentinel) { 2312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Don't worry about adapting arguments for builtins that 2313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // don't want that done. Skip adaption code by making it look 2314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // like we have a match between expected and actual number of 2315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // arguments. 2316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block definitely_matches = true; 2317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 23183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *definitely_mismatches = true; 2319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(ebx, expected.immediate()); 2320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 2323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (actual.is_immediate()) { 2324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Expected is in register, actual is immediate. This is the 2325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // case when we invoke function values without going through the 2326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // IC mechanism. 2327014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mov(eax, actual.immediate()); 2328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmp(expected.reg(), actual.immediate()); 2329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(equal, &invoke); 2330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expected.reg().is(ebx)); 2331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (!expected.reg().is(actual.reg())) { 2332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Both expected and actual are in (different) registers. This 2333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is the case when we invoke functions using call and apply. 23343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmp(expected.reg(), actual.reg()); 2335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(equal, &invoke); 2336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(actual.reg().is(eax)); 2337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expected.reg().is(ebx)); 2338014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 2339014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Move(eax, actual.reg()); 2340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!definitely_matches) { 2344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> adaptor = 234544f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()->builtins()->ArgumentsAdaptorTrampoline(); 2346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (flag == CALL_FUNCTION) { 2347257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch call_wrapper.BeforeCall(CallSize(adaptor, RelocInfo::CODE_TARGET)); 2348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block call(adaptor, RelocInfo::CODE_TARGET); 2349257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch call_wrapper.AfterCall(); 23503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!*definitely_mismatches) { 23513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch jmp(done, done_near); 23523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 2354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block jmp(adaptor, RelocInfo::CODE_TARGET); 2355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&invoke); 2357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2361014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::FloodFunctionIfStepping(Register fun, Register new_target, 2362014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const ParameterCount& expected, 2363014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const ParameterCount& actual) { 2364014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label skip_flooding; 2365014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference step_in_enabled = 2366014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference::debug_step_in_enabled_address(isolate()); 23673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch cmpb(Operand::StaticVariable(step_in_enabled), Immediate(0)); 2368014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch j(equal, &skip_flooding); 2369014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2370014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrameScope frame(this, 2371014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch has_frame() ? StackFrame::NONE : StackFrame::INTERNAL); 2372014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (expected.is_reg()) { 2373014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SmiTag(expected.reg()); 2374014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Push(expected.reg()); 2375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2376014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (actual.is_reg()) { 2377014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SmiTag(actual.reg()); 2378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Push(actual.reg()); 2379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2380014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (new_target.is_valid()) { 2381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Push(new_target); 2382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Push(fun); 2384014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Push(fun); 2385109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CallRuntime(Runtime::kDebugPrepareStepInIfStepping); 2386014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Pop(fun); 2387014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (new_target.is_valid()) { 2388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Pop(new_target); 2389014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2390014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (actual.is_reg()) { 2391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Pop(actual.reg()); 2392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SmiUntag(actual.reg()); 2393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2394014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (expected.is_reg()) { 2395014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Pop(expected.reg()); 2396014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SmiUntag(expected.reg()); 2397014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2398014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2399014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bind(&skip_flooding); 2400014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2401014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2402014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::InvokeFunctionCode(Register function, Register new_target, 2404014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const ParameterCount& expected, 2405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const ParameterCount& actual, 2406014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch InvokeFlag flag, 2407014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const CallWrapper& call_wrapper) { 24083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // You can't call a function without a valid frame. 2409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(flag == JUMP_FUNCTION || has_frame()); 2410014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(function.is(edi)); 2411014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_IMPLIES(new_target.is_valid(), new_target.is(edx)); 2412014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2413014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (call_wrapper.NeedsDebugStepCheck()) { 2414014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FloodFunctionIfStepping(function, new_target, expected, actual); 2415014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2416014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2417014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Clear the new.target register if not given. 2418014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!new_target.is_valid()) { 2419014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mov(edx, isolate()->factory()->undefined_value()); 2420014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 24213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2422257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 24233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool definitely_mismatches = false; 2424014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch InvokePrologue(expected, actual, &done, &definitely_mismatches, flag, 2425014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label::kNear, call_wrapper); 24263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!definitely_mismatches) { 2427014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // We call indirectly through the code field in the function to 2428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // allow recompilation to take effect without changing any of the 2429014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // call sites. 2430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Operand code = FieldOperand(function, JSFunction::kCodeEntryOffset); 24313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (flag == CALL_FUNCTION) { 24323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch call_wrapper.BeforeCall(CallSize(code)); 24333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch call(code); 24343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch call_wrapper.AfterCall(); 24353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 2436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(flag == JUMP_FUNCTION); 24373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch jmp(code); 24383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 24393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&done); 2440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeFunction(Register fun, 2445014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register new_target, 2446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 2447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InvokeFlag flag, 2448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CallWrapper& call_wrapper) { 24493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // You can't call a function without a valid frame. 2450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(flag == JUMP_FUNCTION || has_frame()); 24513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(fun.is(edi)); 2453014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 2454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 2455014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kFormalParameterCountOffset)); 24567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch SmiUntag(ebx); 2457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ParameterCount expected(ebx); 2459014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch InvokeFunctionCode(edi, new_target, expected, actual, flag, call_wrapper); 2460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::InvokeFunction(Register fun, 2464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const ParameterCount& expected, 2465402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu const ParameterCount& actual, 2466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InvokeFlag flag, 2467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CallWrapper& call_wrapper) { 24683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // You can't call a function without a valid frame. 2469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(flag == JUMP_FUNCTION || has_frame()); 24703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(fun.is(edi)); 2472402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 2473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2474014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch InvokeFunctionCode(edi, no_reg, expected, actual, flag, call_wrapper); 2475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::InvokeFunction(Handle<JSFunction> function, 2479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const ParameterCount& expected, 2480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const ParameterCount& actual, 2481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InvokeFlag flag, 2482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CallWrapper& call_wrapper) { 2483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LoadHeapObject(edi, function); 2484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InvokeFunction(edi, expected, actual, flag, call_wrapper); 2485402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 2486402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 2487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2488d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::LoadContext(Register dst, int context_chain_length) { 2489d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (context_chain_length > 0) { 2490d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Move up the chain of contexts to the context containing the slot. 24913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch mov(dst, Operand(esi, Context::SlotOffset(Context::PREVIOUS_INDEX))); 2492d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 1; i < context_chain_length; i++) { 24933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch mov(dst, Operand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX))); 2494d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 24951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 24961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Slot is in the current function context. Move it into the 24971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // destination register in case we store into it (the write barrier 24981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // cannot be allowed to destroy the context in esi). 24991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block mov(dst, esi); 25001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 25011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 25023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // We should not have found a with context by walking the context chain 25031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // (i.e., the static scope chain and runtime context chain do not agree). 25041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // A variable occurring in such a scope should have slot type LOOKUP and 25051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // not CONTEXT. 250644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 25073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch cmp(FieldOperand(dst, HeapObject::kMapOffset), 25083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch isolate()->factory()->with_context_map()); 2509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Check(not_equal, kVariableResolvedToWithContext); 2510d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2511d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2512d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2513d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2514014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LoadGlobalProxy(Register dst) { 2515014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mov(dst, NativeContextOperand()); 2516014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mov(dst, ContextOperand(dst, Context::GLOBAL_PROXY_INDEX)); 2517014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2518014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2519014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 25203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::LoadTransitionedArrayMapConditional( 25213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind expected_kind, 25223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind transitioned_kind, 25233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register map_in_out, 25243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 25253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* no_map_match) { 2526014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(IsFastElementsKind(expected_kind)); 2527014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(IsFastElementsKind(transitioned_kind)); 25283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 25293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that the function's map is the same as the expected cached map. 2530014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mov(scratch, NativeContextOperand()); 2531014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch cmp(map_in_out, 2532014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ContextOperand(scratch, Context::ArrayMapIndex(expected_kind))); 25333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(not_equal, no_map_match); 25343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 25353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Use the transitioned cached map. 2536014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mov(map_in_out, 2537014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ContextOperand(scratch, Context::ArrayMapIndex(transitioned_kind))); 25383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 25393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 25403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 254180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::LoadGlobalFunction(int index, Register function) { 2542014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Load the native context from the current context. 2543014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mov(function, NativeContextOperand()); 2544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the function from the native context. 2545014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mov(function, ContextOperand(function, index)); 254680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 254780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 254880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 254980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::LoadGlobalFunctionInitialMap(Register function, 255080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Register map) { 255180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Load the initial map. The global functions all have initial maps. 255280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen mov(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 255344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 255480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label ok, fail; 2555257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CheckMap(map, isolate()->factory()->meta_map(), &fail, DO_SMI_CHECK); 255680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen jmp(&ok); 255780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen bind(&fail); 2558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Abort(kGlobalFunctionsMustHaveInitialMap); 255980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen bind(&ok); 256080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 256180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 256280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 2563d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2564e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Store the value in register src in the safepoint register stack 2565e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// slot for register dst. 2566e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Register src) { 2567e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch mov(SafepointRegisterSlot(dst), src); 2568e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2569e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2570e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2571e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Immediate src) { 2572e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch mov(SafepointRegisterSlot(dst), src); 2573e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2574e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2575e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2576e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) { 2577e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch mov(dst, SafepointRegisterSlot(src)); 2578e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2579e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2580e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2581e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochOperand MacroAssembler::SafepointRegisterSlot(Register reg) { 2582e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return Operand(esp, SafepointRegisterStackIndex(reg.code()) * kPointerSize); 2583e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2584e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2585e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochint MacroAssembler::SafepointRegisterStackIndex(int reg_code) { 2587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The registers are pushed starting with the lowest encoding, 2588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // which means that lowest encodings are furthest away from 2589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // the stack pointer. 2590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(reg_code >= 0 && reg_code < kNumSafepointRegisters); 2591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return kNumSafepointRegisters - reg_code - 1; 2592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 25953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::LoadHeapObject(Register result, 25963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<HeapObject> object) { 2597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllowDeferredHandleDereference embedding_raw_address; 25983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (isolate()->heap()->InNewSpace(*object)) { 2599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Cell> cell = isolate()->factory()->NewCell(object); 2600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(result, Operand::ForCell(cell)); 26013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 26023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(result, object); 26033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 26043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 26053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 26063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CmpHeapObject(Register reg, Handle<HeapObject> object) { 2608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllowDeferredHandleDereference using_raw_address; 2609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (isolate()->heap()->InNewSpace(*object)) { 2610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Cell> cell = isolate()->factory()->NewCell(object); 2611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(reg, Operand::ForCell(cell)); 2612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(reg, object); 2614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 26183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::PushHeapObject(Handle<HeapObject> object) { 2619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllowDeferredHandleDereference using_raw_address; 26203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (isolate()->heap()->InNewSpace(*object)) { 2621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Cell> cell = isolate()->factory()->NewCell(object); 2622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch push(Operand::ForCell(cell)); 26233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 26243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Push(object); 26253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 26263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 26273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 26283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2629958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::CmpWeakValue(Register value, Handle<WeakCell> cell, 2630958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch) { 2631958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier mov(scratch, cell); 2632958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier cmp(value, FieldOperand(scratch, WeakCell::kValueOffset)); 2633958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2634958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2635958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2636014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::GetWeakValue(Register value, Handle<WeakCell> cell) { 2637958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier mov(value, cell); 2638958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier mov(value, FieldOperand(value, WeakCell::kValueOffset)); 2639014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2640014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2641014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2642014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LoadWeakValue(Register value, Handle<WeakCell> cell, 2643014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label* miss) { 2644014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch GetWeakValue(value, cell); 2645958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier JumpIfSmi(value, miss); 2646958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2647958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2648958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Ret() { 2650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ret(0); 2651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 26541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::Ret(int bytes_dropped, Register scratch) { 26551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (is_uint16(bytes_dropped)) { 26561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ret(bytes_dropped); 26571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 26581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block pop(scratch); 26593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(esp, Immediate(bytes_dropped)); 26601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block push(scratch); 26611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ret(0); 26621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 26631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 26641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 26651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2666e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::Drop(int stack_elements) { 2667e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (stack_elements > 0) { 26683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(esp, Immediate(stack_elements * kPointerSize)); 2669e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2670e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 2671e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2672e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 26730d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::Move(Register dst, Register src) { 26740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!dst.is(src)) { 26750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen mov(dst, src); 26760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 26770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 26780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 26790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 2680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Move(Register dst, const Immediate& x) { 2681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (x.is_zero()) { 2682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch xor_(dst, dst); // Shorter than mov of 32-bit immediate 0. 2683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(dst, x); 2685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Move(const Operand& dst, const Immediate& x) { 2690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(dst, x); 2691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2694958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::Move(XMMRegister dst, uint32_t src) { 2695958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (src == 0) { 2696958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier pxor(dst, dst); 2697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2698958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier unsigned cnt = base::bits::CountPopulation32(src); 2699958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier unsigned nlz = base::bits::CountLeadingZeros32(src); 2700958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier unsigned ntz = base::bits::CountTrailingZeros32(src); 2701958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (nlz + cnt + ntz == 32) { 2702958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier pcmpeqd(dst, dst); 2703958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (ntz == 0) { 2704958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier psrld(dst, 32 - cnt); 2705958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 2706958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier pslld(dst, 32 - cnt); 2707958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (nlz != 0) psrld(dst, nlz); 2708958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2709958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 2710958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier push(eax); 2711958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier mov(eax, Immediate(src)); 2712958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier movd(dst, Operand(eax)); 2713958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier pop(eax); 2714958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2715958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2716958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2717958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2718958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2719958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::Move(XMMRegister dst, uint64_t src) { 2720014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (src == 0) { 2721014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch pxor(dst, dst); 2722958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 2723014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch uint32_t lower = static_cast<uint32_t>(src); 2724014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch uint32_t upper = static_cast<uint32_t>(src >> 32); 2725958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier unsigned cnt = base::bits::CountPopulation64(src); 2726958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier unsigned nlz = base::bits::CountLeadingZeros64(src); 2727958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier unsigned ntz = base::bits::CountTrailingZeros64(src); 2728958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (nlz + cnt + ntz == 64) { 2729958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier pcmpeqd(dst, dst); 2730958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (ntz == 0) { 2731958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier psrlq(dst, 64 - cnt); 2732958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 2733958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier psllq(dst, 64 - cnt); 2734958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (nlz != 0) psrlq(dst, nlz); 2735958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2736958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else if (lower == 0) { 2737958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Move(dst, upper); 2738958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier psllq(dst, 32); 2739958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else if (CpuFeatures::IsSupported(SSE4_1)) { 2740958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CpuFeatureScope scope(this, SSE4_1); 2741958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier push(eax); 2742958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Move(eax, Immediate(lower)); 2743958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier movd(dst, Operand(eax)); 2744958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Move(eax, Immediate(upper)); 2745958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier pinsrd(dst, Operand(eax), 1); 2746958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier pop(eax); 2747958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 2748958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier push(Immediate(upper)); 2749958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier push(Immediate(lower)); 2750958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier movsd(dst, Operand(esp, 0)); 2751958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier add(esp, Immediate(kDoubleSize)); 2752958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2757014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Pextrd(Register dst, XMMRegister src, int8_t imm8) { 2758014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (imm8 == 0) { 2759014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch movd(dst, src); 2760014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return; 2761014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2762014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_EQ(1, imm8); 2763014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (CpuFeatures::IsSupported(SSE4_1)) { 2764014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CpuFeatureScope sse_scope(this, SSE4_1); 2765014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch pextrd(dst, src, imm8); 2766014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return; 2767014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2768014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch pshufd(xmm0, src, 1); 2769014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch movd(dst, xmm0); 2770014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2771014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2772014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2773014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Pinsrd(XMMRegister dst, const Operand& src, int8_t imm8) { 2774014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(imm8 == 0 || imm8 == 1); 2775014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (CpuFeatures::IsSupported(SSE4_1)) { 2776014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CpuFeatureScope sse_scope(this, SSE4_1); 2777014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch pinsrd(dst, src, imm8); 2778014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return; 2779014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2780014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch movd(xmm0, src); 2781014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (imm8 == 1) { 2782014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch punpckldq(dst, xmm0); 2783014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 2784014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_EQ(0, imm8); 2785014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch psrlq(dst, 32); 2786014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch punpckldq(xmm0, dst); 2787014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch movaps(dst, xmm0); 2788014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2789014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2790014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2791014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2792014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Lzcnt(Register dst, const Operand& src) { 2793014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (CpuFeatures::IsSupported(LZCNT)) { 2794014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CpuFeatureScope scope(this, LZCNT); 2795014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch lzcnt(dst, src); 2796014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return; 2797014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2798014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label not_zero_src; 2799014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bsr(dst, src); 2800014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch j(not_zero, ¬_zero_src, Label::kNear); 2801014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Move(dst, Immediate(63)); // 63^31 == 32 2802014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bind(¬_zero_src); 2803014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch xor_(dst, Immediate(31)); // for x in [0..31], 31^x == 31-x. 2804014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2805014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2806014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2807014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Tzcnt(Register dst, const Operand& src) { 2808014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (CpuFeatures::IsSupported(BMI1)) { 2809014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CpuFeatureScope scope(this, BMI1); 2810014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch tzcnt(dst, src); 2811014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return; 2812014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2813014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label not_zero_src; 2814014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bsf(dst, src); 2815014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch j(not_zero, ¬_zero_src, Label::kNear); 2816014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Move(dst, Immediate(32)); // The result of tzcnt is 32 if src = 0. 2817014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bind(¬_zero_src); 2818014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2819014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2820014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2821014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Popcnt(Register dst, const Operand& src) { 2822014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (CpuFeatures::IsSupported(POPCNT)) { 2823014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CpuFeatureScope scope(this, POPCNT); 2824014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch popcnt(dst, src); 2825014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return; 2826014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2827014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch UNREACHABLE(); 2828014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2829014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2830014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SetCounter(StatsCounter* counter, int value) { 2832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_native_code_counters && counter->Enabled()) { 2833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(Operand::StaticVariable(ExternalReference(counter)), Immediate(value)); 2834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::IncrementCounter(StatsCounter* counter, int value) { 2839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(value > 0); 2840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_native_code_counters && counter->Enabled()) { 2841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand operand = Operand::StaticVariable(ExternalReference(counter)); 2842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (value == 1) { 2843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inc(operand); 2844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 2845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block add(operand, Immediate(value)); 2846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::DecrementCounter(StatsCounter* counter, int value) { 2852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(value > 0); 2853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_native_code_counters && counter->Enabled()) { 2854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand operand = Operand::StaticVariable(ExternalReference(counter)); 2855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (value == 1) { 2856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block dec(operand); 2857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 2858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block sub(operand, Immediate(value)); 2859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2864d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid MacroAssembler::IncrementCounter(Condition cc, 2865d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke StatsCounter* counter, 2866d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke int value) { 2867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(value > 0); 2868d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (FLAG_native_code_counters && counter->Enabled()) { 2869d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label skip; 2870d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke j(NegateCondition(cc), &skip); 2871d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke pushfd(); 2872d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke IncrementCounter(counter, value); 2873d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke popfd(); 2874d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke bind(&skip); 2875d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 2876d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 2877d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 2878d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 2879d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid MacroAssembler::DecrementCounter(Condition cc, 2880d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke StatsCounter* counter, 2881d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke int value) { 2882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(value > 0); 2883d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (FLAG_native_code_counters && counter->Enabled()) { 2884d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label skip; 2885d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke j(NegateCondition(cc), &skip); 2886d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke pushfd(); 2887d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke DecrementCounter(counter, value); 2888d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke popfd(); 2889d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke bind(&skip); 2890d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 2891d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 2892d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 2893d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 2894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Assert(Condition cc, BailoutReason reason) { 2895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (emit_debug_code()) Check(cc, reason); 2896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2899756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid MacroAssembler::AssertFastElements(Register elements) { 290044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 290144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Factory* factory = isolate()->factory(); 2902756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Label ok; 2903756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick cmp(FieldOperand(elements, HeapObject::kMapOffset), 290444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Immediate(factory->fixed_array_map())); 2905756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick j(equal, &ok); 2906756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick cmp(FieldOperand(elements, HeapObject::kMapOffset), 29073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Immediate(factory->fixed_double_array_map())); 29083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch j(equal, &ok); 29093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch cmp(FieldOperand(elements, HeapObject::kMapOffset), 291044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Immediate(factory->fixed_cow_array_map())); 2911756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick j(equal, &ok); 2912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Abort(kJSObjectWithFastElementsMapHasSlowElements); 2913756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick bind(&ok); 2914756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 2915756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick} 2916756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 2917756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 2918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Check(Condition cc, BailoutReason reason) { 2919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label L; 2920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(cc, &L); 2921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Abort(reason); 2922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // will not return here 2923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&L); 2924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29276ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::CheckStackAlignment() { 2928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int frame_alignment = base::OS::ActivationFrameAlignment(); 29296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int frame_alignment_mask = frame_alignment - 1; 29306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (frame_alignment > kPointerSize) { 2931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(base::bits::IsPowerOfTwo32(frame_alignment)); 29326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label alignment_as_expected; 29336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block test(esp, Immediate(frame_alignment_mask)); 29346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block j(zero, &alignment_as_expected); 29356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Abort if stack is not aligned. 29366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int3(); 29376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block bind(&alignment_as_expected); 29386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 29396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 29406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 29416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Abort(BailoutReason reason) { 2943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 2944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* msg = GetBailoutReason(reason); 2945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (msg != NULL) { 2946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RecordComment("Abort message: "); 2947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RecordComment(msg); 2948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_trap_on_abort) { 2951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int3(); 2952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 2953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 2955d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch push(Immediate(reinterpret_cast<intptr_t>(Smi::FromInt(reason)))); 29573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Disable stub call restrictions to always allow calls to abort. 29583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!has_frame_) { 29593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We don't actually want to generate a pile of code for this, so just 29603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // claim there is a stack frame, without generating one. 29613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(this, StackFrame::NONE); 2962109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CallRuntime(Runtime::kAbort); 29633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 2964109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CallRuntime(Runtime::kAbort); 29653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // will not return here 2967d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int3(); 2968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2971257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::LoadInstanceDescriptors(Register map, 2972257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register descriptors) { 2973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(descriptors, FieldOperand(map, Map::kDescriptorsOffset)); 2974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) { 2978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(dst, FieldOperand(map, Map::kBitField3Offset)); 2979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DecodeField<Map::NumberOfOwnDescriptorsBits>(dst); 2980756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick} 2981756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 2982756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 2983014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LoadAccessor(Register dst, Register holder, 2984014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int accessor_index, 2985014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch AccessorComponent accessor) { 2986014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mov(dst, FieldOperand(holder, HeapObject::kMapOffset)); 2987014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LoadInstanceDescriptors(dst, dst); 2988014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mov(dst, FieldOperand(dst, DescriptorArray::GetValueOffset(accessor_index))); 2989014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int offset = accessor == ACCESSOR_GETTER ? AccessorPair::kGetterOffset 2990014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch : AccessorPair::kSetterOffset; 2991014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mov(dst, FieldOperand(dst, offset)); 2992014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2993014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2994014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 29950d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::LoadPowerOf2(XMMRegister dst, 29960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register scratch, 29970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int power) { 2998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(is_uintn(power + HeapNumber::kExponentBias, 29990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen HeapNumber::kExponentBits)); 30000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen mov(scratch, Immediate(power + HeapNumber::kExponentBias)); 30013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movd(dst, scratch); 30020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen psllq(dst, HeapNumber::kMantissaBits); 30030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 30040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 30050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 3006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfInstanceTypeIsNotSequentialOneByte( 3007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register instance_type, Register scratch, Label* failure) { 3008402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (!scratch.is(instance_type)) { 3009402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu mov(scratch, instance_type); 3010402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 3011402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu and_(scratch, 3012402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask); 3013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(scratch, kStringTag | kSeqStringTag | kOneByteStringTag); 3014402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu j(not_equal, failure); 3015402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 3016402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 3017402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 3018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfNotBothSequentialOneByteStrings(Register object1, 3019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object2, 3020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1, 3021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2, 3022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* failure) { 3023d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Check that both objects are not smis. 302469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 30253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(scratch1, object1); 30263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(scratch1, object2); 30273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch JumpIfSmi(scratch1, failure); 3028d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 3029d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Load instance type for both strings. 3030d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke mov(scratch1, FieldOperand(object1, HeapObject::kMapOffset)); 3031d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke mov(scratch2, FieldOperand(object2, HeapObject::kMapOffset)); 3032d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke movzx_b(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset)); 3033d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke movzx_b(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset)); 3034d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 3035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that both are flat one-byte strings. 3036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kFlatOneByteStringMask = 3037d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; 3038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kFlatOneByteStringTag = 3039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kStringTag | kOneByteStringTag | kSeqStringTag; 3040d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Interleave bits from both instance types and compare them in one check. 3041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(0, kFlatOneByteStringMask & (kFlatOneByteStringMask << 3)); 3042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch and_(scratch1, kFlatOneByteStringMask); 3043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch and_(scratch2, kFlatOneByteStringMask); 3044d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke lea(scratch1, Operand(scratch1, scratch2, times_8, 0)); 3045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(scratch1, kFlatOneByteStringTag | (kFlatOneByteStringTag << 3)); 3046d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke j(not_equal, failure); 3047d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 3048d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 3049d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 3050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfNotUniqueNameInstanceType(Operand operand, 3051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* not_unique_name, 3052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label::Distance distance) { 3053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); 3054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label succeed; 3055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch test(operand, Immediate(kIsNotStringMask | kIsNotInternalizedMask)); 3056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch j(zero, &succeed); 30573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch cmpb(operand, Immediate(SYMBOL_TYPE)); 3058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch j(not_equal, not_unique_name, distance); 3059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bind(&succeed); 3061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::EmitSeqStringSetCharCheck(Register string, 3065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register index, 3066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value, 3067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t encoding_mask) { 3068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label is_object; 3069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JumpIfNotSmi(string, &is_object, Label::kNear); 3070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Abort(kNonObject); 3071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bind(&is_object); 3072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch push(value); 3074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(value, FieldOperand(string, HeapObject::kMapOffset)); 3075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch movzx_b(value, FieldOperand(value, Map::kInstanceTypeOffset)); 3076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch and_(value, Immediate(kStringRepresentationMask | kStringEncodingMask)); 3078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(value, Immediate(encoding_mask)); 3079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch pop(value); 3080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Check(equal, kUnexpectedStringType); 3081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The index is assumed to be untagged coming in, tag it to compare with the 3083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // string length without using a temp register, it is restored at the end of 3084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // this function. 3085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SmiTag(index); 3086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Check(no_overflow, kIndexIsTooLarge); 3087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(index, FieldOperand(string, String::kLengthOffset)); 3089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Check(less, kIndexIsTooLarge); 3090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(index, Immediate(Smi::FromInt(0))); 3092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Check(greater_equal, kIndexIsNegative); 3093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore the index 3095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SmiUntag(index); 3096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 30996ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::PrepareCallCFunction(int num_arguments, Register scratch) { 3100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int frame_alignment = base::OS::ActivationFrameAlignment(); 31018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (frame_alignment != 0) { 31026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Make stack end at alignment and make room for num_arguments words 31036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // and the original value of esp. 31046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block mov(scratch, esp); 31053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch sub(esp, Immediate((num_arguments + 1) * kPointerSize)); 3106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(base::bits::IsPowerOfTwo32(frame_alignment)); 31078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch and_(esp, -frame_alignment); 31086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block mov(Operand(esp, num_arguments * kPointerSize), scratch); 31096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 31103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch sub(esp, Immediate(num_arguments * kPointerSize)); 31116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 31126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 31136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 31146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 31156ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::CallCFunction(ExternalReference function, 31166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int num_arguments) { 31176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Trashing eax is ok as it will be the return value. 31183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(eax, Immediate(function)); 31196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block CallCFunction(eax, num_arguments); 31206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 31216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 31226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 31236ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::CallCFunction(Register function, 31246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int num_arguments) { 3125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(has_frame()); 31266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check stack alignment. 312744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 31286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block CheckStackAlignment(); 31296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 31306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 31313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch call(function); 3132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (base::OS::ActivationFrameAlignment() != 0) { 31336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block mov(esp, Operand(esp, num_arguments * kPointerSize)); 31346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 31353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(esp, Immediate(num_arguments * kPointerSize)); 31366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 31376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 31386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 31396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG 3141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool AreAliased(Register reg1, 3142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg2, 3143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg3, 3144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg4, 3145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg5, 3146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg6, 3147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg7, 3148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg8) { 3149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int n_of_valid_regs = reg1.is_valid() + reg2.is_valid() + 3150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg3.is_valid() + reg4.is_valid() + reg5.is_valid() + reg6.is_valid() + 3151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg7.is_valid() + reg8.is_valid(); 3152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RegList regs = 0; 3154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (reg1.is_valid()) regs |= reg1.bit(); 3155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (reg2.is_valid()) regs |= reg2.bit(); 3156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (reg3.is_valid()) regs |= reg3.bit(); 3157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (reg4.is_valid()) regs |= reg4.bit(); 3158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (reg5.is_valid()) regs |= reg5.bit(); 3159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (reg6.is_valid()) regs |= reg6.bit(); 3160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (reg7.is_valid()) regs |= reg7.bit(); 3161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (reg8.is_valid()) regs |= reg8.bit(); 3162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int n_of_non_aliasing_regs = NumRegs(regs); 3163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return n_of_valid_regs != n_of_non_aliasing_regs; 31653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 3166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 31673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 31683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochCodePatcher::CodePatcher(Isolate* isolate, byte* address, int size) 31708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch : address_(address), 31718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch size_(size), 3172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch masm_(isolate, address, size + Assembler::kGap, CodeObjectRequired::kNo) { 3173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Create a new macro assembler pointing to the address of the code to patch. 3174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The size is adjusted with kGap on order for the assembler to generate size 3175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // bytes of instructions without failing with buffer size constraints. 3176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); 3177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCodePatcher::~CodePatcher() { 3181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Indicate that code has changed. 3182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Assembler::FlushICache(masm_.isolate(), address_, size_); 3183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the code was patched as expected. 3185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(masm_.pc_ == address_ + size_); 3186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); 3187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 31903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckPageFlag( 31913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object, 31923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 31933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int mask, 31943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition cc, 31953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* condition_met, 31963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance condition_met_distance) { 3197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(cc == zero || cc == not_zero); 31983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (scratch.is(object)) { 31993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(scratch, Immediate(~Page::kPageAlignmentMask)); 32003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 32013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(scratch, Immediate(~Page::kPageAlignmentMask)); 32023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(scratch, object); 32033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 32043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (mask < (1 << kBitsPerByte)) { 32053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch test_b(Operand(scratch, MemoryChunk::kFlagsOffset), Immediate(mask)); 32063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 32073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test(Operand(scratch, MemoryChunk::kFlagsOffset), Immediate(mask)); 32083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 32093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(cc, condition_met, condition_met_distance); 32103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 32113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 32123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CheckPageFlagForMap( 3214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> map, 3215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int mask, 3216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cc, 3217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* condition_met, 3218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label::Distance condition_met_distance) { 3219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(cc == zero || cc == not_zero); 3220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Page* page = Page::FromAddress(map->address()); 3221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!serializer_enabled()); // Serializer cannot match page_flags. 3222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference reference(ExternalReference::page_flags(page)); 3223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The inlined static address check of the page's flags relies 3224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // on maps never being compacted. 3225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!isolate()->heap()->mark_compact_collector()-> 3226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IsOnEvacuationCandidate(*map)); 3227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (mask < (1 << kBitsPerByte)) { 32283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch test_b(Operand::StaticVariable(reference), Immediate(mask)); 3229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 3230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch test(Operand::StaticVariable(reference), Immediate(mask)); 3231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch j(cc, condition_met, condition_met_distance); 3233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 32363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::JumpIfBlack(Register object, 32373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch0, 32383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1, 32393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* on_black, 32403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance on_black_near) { 3241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HasColor(object, scratch0, scratch1, on_black, on_black_near, 1, 3242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1); // kBlackBitPattern. 3243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0); 32443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 32453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 32463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 32473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::HasColor(Register object, 32483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register bitmap_scratch, 32493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register mask_scratch, 32503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* has_color, 32513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance has_color_distance, 32523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int first_bit, 32533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int second_bit) { 3254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!AreAliased(object, bitmap_scratch, mask_scratch, ecx)); 32553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 32563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GetMarkBits(object, bitmap_scratch, mask_scratch); 32573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 32583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label other_color, word_boundary; 32593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize)); 32603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(first_bit == 1 ? zero : not_zero, &other_color, Label::kNear); 32613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(mask_scratch, mask_scratch); // Shift left 1 by adding. 32623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(zero, &word_boundary, Label::kNear); 32633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize)); 32643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(second_bit == 1 ? not_zero : zero, has_color, has_color_distance); 32653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch jmp(&other_color, Label::kNear); 32663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 32673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&word_boundary); 32683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch test_b(Operand(bitmap_scratch, MemoryChunk::kHeaderSize + kPointerSize), 32693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Immediate(1)); 32703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 32713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(second_bit == 1 ? not_zero : zero, has_color, has_color_distance); 32723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&other_color); 32733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 32743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 32753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 32763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::GetMarkBits(Register addr_reg, 32773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register bitmap_reg, 32783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register mask_reg) { 3279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!AreAliased(addr_reg, mask_reg, bitmap_reg, ecx)); 32803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(bitmap_reg, Immediate(~Page::kPageAlignmentMask)); 32813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(bitmap_reg, addr_reg); 32823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(ecx, addr_reg); 32833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int shift = 32843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Bitmap::kBitsPerCellLog2 + kPointerSizeLog2 - Bitmap::kBytesPerCellLog2; 32853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch shr(ecx, shift); 32863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(ecx, 32873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (Page::kPageAlignmentMask >> shift) & ~(Bitmap::kBytesPerCell - 1)); 32883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 32893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(bitmap_reg, ecx); 32903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(ecx, addr_reg); 32913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch shr(ecx, kPointerSizeLog2); 32923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(ecx, (1 << Bitmap::kBitsPerCellLog2) - 1); 32933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(mask_reg, Immediate(1)); 32943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch shl_cl(mask_reg); 32953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 32963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 32973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3298014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::JumpIfWhite(Register value, Register bitmap_scratch, 3299014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register mask_scratch, Label* value_is_white, 3300014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label::Distance distance) { 3301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!AreAliased(value, bitmap_scratch, mask_scratch, ecx)); 33023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GetMarkBits(value, bitmap_scratch, mask_scratch); 33033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 33043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If the value is black or grey we don't need to do anything. 3305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0); 3306014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0); 3307014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(strcmp(Marking::kGreyBitPattern, "10") == 0); 3308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0); 33093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 33103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Since both black and grey have a 1 in the first position and white does 33113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // not have a 1 there we only need to check one bit. 33123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize)); 3313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch j(zero, value_is_white, Label::kNear); 33143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 33153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 33163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::EnumLength(Register dst, Register map) { 3318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(Map::EnumLengthBits::kShift == 0); 3319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(dst, FieldOperand(map, Map::kBitField3Offset)); 3320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch and_(dst, Immediate(Map::EnumLengthBits::kMask)); 3321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SmiTag(dst); 3322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 33253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckEnumCache(Label* call_runtime) { 3326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label next, start; 33273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(ecx, eax); 3328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if the enum length field is properly initialized, indicating that 3330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // there is an enum cache. 3331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset)); 3332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EnumLength(edx, ebx); 3334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(edx, Immediate(Smi::FromInt(kInvalidEnumCacheSentinel))); 3335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch j(equal, call_runtime); 3336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch jmp(&start); 3338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 33393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&next); 3340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset)); 33413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // For all objects but the receiver, check that the cache is empty. 3343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EnumLength(edx, ebx); 3344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(edx, Immediate(Smi::FromInt(0))); 33453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(not_equal, call_runtime); 33463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bind(&start); 33483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that there are no elements. Register rcx contains the current JS 3350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // object we've reached through the prototype chain. 3351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label no_elements; 3352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset)); 3353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(ecx, isolate()->factory()->empty_fixed_array()); 3354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch j(equal, &no_elements); 33553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Second chance, the object may be using the empty slow element dictionary. 3357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(ecx, isolate()->factory()->empty_slow_element_dictionary()); 33583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(not_equal, call_runtime); 33593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bind(&no_elements); 33613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset)); 33623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmp(ecx, isolate()->factory()->null_value()); 33633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(not_equal, &next); 33643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 33653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TestJSArrayForAllocationMemento( 3368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register receiver_reg, 3369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch_reg, 3370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* no_memento_found) { 33713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Label map_check; 33723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Label top_check; 3373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference new_space_allocation_top = 3374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::new_space_allocation_top_address(isolate()); 33753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch const int kMementoMapOffset = JSArray::kSize - kHeapObjectTag; 33763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch const int kMementoEndOffset = kMementoMapOffset + AllocationMemento::kSize; 33773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 33783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Bail out if the object is not in new space. 33793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch JumpIfNotInNewSpace(receiver_reg, scratch_reg, no_memento_found); 33803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // If the object is in new space, we need to check whether it is on the same 33813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // page as the current top. 33823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch lea(scratch_reg, Operand(receiver_reg, kMementoEndOffset)); 33833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch xor_(scratch_reg, Operand::StaticVariable(new_space_allocation_top)); 33843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch test(scratch_reg, Immediate(~Page::kPageAlignmentMask)); 33853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch j(zero, &top_check); 33863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // The object is on a different page than allocation top. Bail out if the 33873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // object sits on the page boundary as no memento can follow and we cannot 33883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // touch the memory following it. 33893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch lea(scratch_reg, Operand(receiver_reg, kMementoEndOffset)); 33903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch xor_(scratch_reg, receiver_reg); 33913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch test(scratch_reg, Immediate(~Page::kPageAlignmentMask)); 33923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch j(not_zero, no_memento_found); 33933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Continue with the actual map check. 33943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch jmp(&map_check); 33953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // If top is on the same page as the current object, we need to check whether 33963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // we are below top. 33973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch bind(&top_check); 33983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch lea(scratch_reg, Operand(receiver_reg, kMementoEndOffset)); 3399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(scratch_reg, Operand::StaticVariable(new_space_allocation_top)); 3400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch j(greater, no_memento_found); 34013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Memento map check. 34023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch bind(&map_check); 34033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch mov(scratch_reg, Operand(receiver_reg, kMementoMapOffset)); 34043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch cmp(scratch_reg, Immediate(isolate()->factory()->allocation_memento_map())); 3405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfDictionaryInPrototypeChain( 3409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object, 3410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch0, 3411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1, 3412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* found) { 3413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!scratch1.is(scratch0)); 3414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Factory* factory = isolate()->factory(); 3415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register current = scratch0; 3416014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label loop_again, end; 3417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // scratch contained elements pointer. 3419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(current, object); 3420014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mov(current, FieldOperand(current, HeapObject::kMapOffset)); 3421014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mov(current, FieldOperand(current, Map::kPrototypeOffset)); 3422014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch cmp(current, Immediate(factory->null_value())); 3423014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch j(equal, &end); 3424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Loop based on the map going up the prototype chain. 3426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bind(&loop_again); 3427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(current, FieldOperand(current, HeapObject::kMapOffset)); 3428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(JS_PROXY_TYPE < JS_OBJECT_TYPE); 3429014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(JS_VALUE_TYPE < JS_OBJECT_TYPE); 3430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CmpInstanceType(current, JS_OBJECT_TYPE); 3431014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch j(below, found); 3432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(scratch1, FieldOperand(current, Map::kBitField2Offset)); 3433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DecodeField<Map::ElementsKindBits>(scratch1); 3434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(scratch1, Immediate(DICTIONARY_ELEMENTS)); 3435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch j(equal, found); 3436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(current, FieldOperand(current, Map::kPrototypeOffset)); 3437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp(current, Immediate(factory->null_value())); 3438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch j(not_equal, &loop_again); 3439014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3440014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bind(&end); 3441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TruncatingDiv(Register dividend, int32_t divisor) { 3445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!dividend.is(eax)); 3446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!dividend.is(edx)); 3447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch base::MagicNumbersForDivision<uint32_t> mag = 3448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch base::SignedDivisionByConstant(static_cast<uint32_t>(divisor)); 3449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(eax, Immediate(mag.multiplier)); 3450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch imul(dividend); 3451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool neg = (mag.multiplier & (static_cast<uint32_t>(1) << 31)) != 0; 3452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (divisor > 0 && neg) add(edx, dividend); 3453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (divisor < 0 && !neg && mag.multiplier > 0) sub(edx, dividend); 3454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (mag.shift > 0) sar(edx, mag.shift); 3455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(eax, dividend); 3456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch shr(eax, 31); 3457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch add(edx, eax); 3458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3461014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 3462014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 3463f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3464f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_IA32 3465