13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h" 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 30f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_IA32) 31f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "bootstrapper.h" 338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "codegen.h" 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "debug.h" 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "runtime.h" 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "serialize.h" 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ------------------------------------------------------------------------- 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// MacroAssembler implementation. 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 448b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochMacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size) 458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch : Assembler(arg_isolate, buffer, size), 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block generating_stub_(false), 473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch allow_stub_calls_(true), 483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch has_frame_(false) { 498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (isolate() != NULL) { 508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch code_object_ = Handle<Object>(isolate()->heap()->undefined_value(), 518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch isolate()); 528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::InNewSpace( 573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object, 583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition cc, 603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* condition_met, 613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance condition_met_distance) { 623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(cc == equal || cc == not_equal); 633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (scratch.is(object)) { 643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(scratch, Immediate(~Page::kPageAlignmentMask)); 653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(scratch, Immediate(~Page::kPageAlignmentMask)); 673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(scratch, object); 686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that we can use a test_b. 703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(MemoryChunk::IN_FROM_SPACE < 8); 713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(MemoryChunk::IN_TO_SPACE < 8); 723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int mask = (1 << MemoryChunk::IN_FROM_SPACE) 733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch | (1 << MemoryChunk::IN_TO_SPACE); 743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If non-zero, the page belongs to new-space. 753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test_b(Operand(scratch, MemoryChunk::kFlagsOffset), 763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static_cast<uint8_t>(mask)); 773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(cc, condition_met, condition_met_distance); 783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::RememberedSetHelper( 823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object, // Only used for debug checks. 833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register addr, 843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SaveFPRegsMode save_fp, 863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler::RememberedSetFinalAction and_then) { 873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label done; 883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_debug_code) { 893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label ok; 903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JumpIfNotInNewSpace(object, scratch, &ok, Label::kNear); 913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int3(); 923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&ok); 933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load store buffer top. 953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference store_buffer = 963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference::store_buffer_top(isolate()); 973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(scratch, Operand::StaticVariable(store_buffer)); 983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store pointer to buffer. 993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(Operand(scratch, 0), addr); 1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Increment buffer top. 1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(scratch, Immediate(kPointerSize)); 1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Write back new top of buffer. 1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(Operand::StaticVariable(store_buffer), scratch); 1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Call stub on end of buffer. 1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for end of buffer. 1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test(scratch, Immediate(StoreBuffer::kStoreBufferOverflowBit)); 1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (and_then == kReturnAtEnd) { 1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label buffer_overflowed; 1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(not_equal, &buffer_overflowed, Label::kNear); 1103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ret(0); 1113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&buffer_overflowed); 1123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 1133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(and_then == kFallThroughAtEnd); 1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(equal, &done, Label::kNear); 1153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StoreBufferOverflowStub store_buffer_overflow = 1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StoreBufferOverflowStub(save_fp); 1183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallStub(&store_buffer_overflow); 1193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (and_then == kReturnAtEnd) { 1203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ret(0); 1213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 1223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(and_then == kFallThroughAtEnd); 1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&done); 1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::ClampDoubleToUint8(XMMRegister input_reg, 129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch XMMRegister scratch_reg, 130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register result_reg) { 131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference zero_ref = ExternalReference::address_of_zero(); 133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movdbl(scratch_reg, Operand::StaticVariable(zero_ref)); 134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Set(result_reg, Immediate(0)); 135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ucomisd(input_reg, scratch_reg); 136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(below, &done, Label::kNear); 137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference half_ref = ExternalReference::address_of_one_half(); 138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch movdbl(scratch_reg, Operand::StaticVariable(half_ref)); 139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch addsd(scratch_reg, input_reg); 140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cvttsd2si(result_reg, Operand(scratch_reg)); 141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch test(result_reg, Immediate(0xFFFFFF00)); 142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(zero, &done, Label::kNear); 143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Set(result_reg, Immediate(255)); 144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bind(&done); 145257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 146257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::ClampUint8(Register reg) { 149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch test(reg, Immediate(0xFFFFFF00)); 151257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(zero, &done, Label::kNear); 152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch setcc(negative, reg); // 1 if negative, 0 if positive. 153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch dec_b(reg); // 0 if negative, 255 if positive. 154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bind(&done); 155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::RecordWriteArray(Register object, 1593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register value, 1603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register index, 1613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SaveFPRegsMode save_fp, 1623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RememberedSetAction remembered_set_action, 1633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiCheck smi_check) { 1643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // First, check if a write barrier is even needed. The tests below 1653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // catch stores of Smis. 1663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label done; 1673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Skip barrier if writing a smi. 1693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (smi_check == INLINE_SMI_CHECK) { 1703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_EQ(0, kSmiTag); 1713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test(value, Immediate(kSmiTagMask)); 1723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(zero, &done); 1733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Array access: calculate the destination address in the same manner as 1763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // KeyedStoreIC::GenerateGeneric. Multiply a smi by 2 to get an offset 1773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // into an array of words. 1783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register dst = index; 1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lea(dst, Operand(object, index, times_half_pointer_size, 1803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArray::kHeaderSize - kHeapObjectTag)); 1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RecordWrite( 1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch object, dst, value, save_fp, remembered_set_action, OMIT_SMI_CHECK); 1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&done); 1863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Clobber clobbered input registers when running with the debug-code flag 1883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // turned on to provoke errors. 1893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (emit_debug_code()) { 1903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(value, Immediate(BitCast<int32_t>(kZapValue))); 1913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(index, Immediate(BitCast<int32_t>(kZapValue))); 192257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::RecordWriteField( 1973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object, 1983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int offset, 1993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register value, 2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register dst, 2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SaveFPRegsMode save_fp, 2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RememberedSetAction remembered_set_action, 2033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiCheck smi_check) { 2047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // First, check if a write barrier is even needed. The tests below 2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // catch stores of Smis. 206257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Skip barrier if writing a smi. 2093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (smi_check == INLINE_SMI_CHECK) { 2103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JumpIfSmi(value, &done, Label::kNear); 2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Although the object register is tagged, the offset is relative to the start 2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // of the object, so so offset must be a multiple of kPointerSize. 2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(IsAligned(offset, kPointerSize)); 216592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lea(dst, FieldOperand(object, offset)); 2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (emit_debug_code()) { 2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label ok; 2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test_b(dst, (1 << kPointerSizeLog2) - 1); 2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(zero, &ok, Label::kNear); 2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int3(); 2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&ok); 22485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch } 2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RecordWrite( 2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch object, dst, value, save_fp, remembered_set_action, OMIT_SMI_CHECK); 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&done); 2304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Clobber clobbered input registers when running with the debug-code flag 2324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // turned on to provoke errors. 23344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 2346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block mov(value, Immediate(BitCast<int32_t>(kZapValue))); 2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(dst, Immediate(BitCast<int32_t>(kZapValue))); 2364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2408defd9ff6930b4e24729971a61cf7469daf119beSteve Blockvoid MacroAssembler::RecordWrite(Register object, 2418defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register address, 2423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register value, 2433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SaveFPRegsMode fp_mode, 2443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RememberedSetAction remembered_set_action, 2453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiCheck smi_check) { 2463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!object.is(value)); 2473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!object.is(address)); 2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!value.is(address)); 2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (emit_debug_code()) { 2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AbortIfSmi(object); 2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (remembered_set_action == OMIT_REMEMBERED_SET && 2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch !FLAG_incremental_marking) { 2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return; 2563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_debug_code) { 2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label ok; 2603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmp(value, Operand(address, 0)); 2613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(equal, &ok, Label::kNear); 2623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int3(); 2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&ok); 2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2668defd9ff6930b4e24729971a61cf7469daf119beSteve Block // First, check if a write barrier is even needed. The tests below 2678defd9ff6930b4e24729971a61cf7469daf119beSteve Block // catch stores of Smis and stores into young gen. 2688defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label done; 2698defd9ff6930b4e24729971a61cf7469daf119beSteve Block 2703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (smi_check == INLINE_SMI_CHECK) { 2713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Skip barrier if writing a smi. 2723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JumpIfSmi(value, &done, Label::kNear); 2733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPageFlag(value, 2763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value, // Used as scratch. 2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MemoryChunk::kPointersToHereAreInterestingMask, 2783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch zero, 2793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &done, 2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::kNear); 2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPageFlag(object, 2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value, // Used as scratch. 2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MemoryChunk::kPointersFromHereAreInterestingMask, 2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch zero, 2853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &done, 2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::kNear); 2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RecordWriteStub stub(object, value, address, remembered_set_action, fp_mode); 2893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallStub(&stub); 2908defd9ff6930b4e24729971a61cf7469daf119beSteve Block 2918defd9ff6930b4e24729971a61cf7469daf119beSteve Block bind(&done); 2928defd9ff6930b4e24729971a61cf7469daf119beSteve Block 2933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Clobber clobbered registers when running with the debug-code flag 2948defd9ff6930b4e24729971a61cf7469daf119beSteve Block // turned on to provoke errors. 29544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 2968defd9ff6930b4e24729971a61cf7469daf119beSteve Block mov(address, Immediate(BitCast<int32_t>(kZapValue))); 2978defd9ff6930b4e24729971a61cf7469daf119beSteve Block mov(value, Immediate(BitCast<int32_t>(kZapValue))); 2988defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 2998defd9ff6930b4e24729971a61cf7469daf119beSteve Block} 3008defd9ff6930b4e24729971a61cf7469daf119beSteve Block 3018defd9ff6930b4e24729971a61cf7469daf119beSteve Block 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT 303402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::DebugBreak() { 304402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Set(eax, Immediate(0)); 30544f0eee88ff00398ff7f715fab053374d808c90dSteve Block mov(ebx, Immediate(ExternalReference(Runtime::kDebugBreak, isolate()))); 306402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu CEntryStub ces(1); 307402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu call(ces.GetCode(), RelocInfo::DEBUG_BREAK); 308402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 31180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Set(Register dst, const Immediate& x) { 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (x.is_zero()) { 3143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch xor_(dst, dst); // Shorter than mov. 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(dst, x); 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Set(const Operand& dst, const Immediate& x) { 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(dst, x); 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 326053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Blockbool MacroAssembler::IsUnsafeImmediate(const Immediate& x) { 327053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block static const int kMaxImmediateBits = 17; 328053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block if (x.rmode_ != RelocInfo::NONE) return false; 329053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block return !is_intn(x.x_, kMaxImmediateBits); 330053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block} 331053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block 332053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block 333053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Blockvoid MacroAssembler::SafeSet(Register dst, const Immediate& x) { 334053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block if (IsUnsafeImmediate(x) && jit_cookie() != 0) { 335053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block Set(dst, Immediate(x.x_ ^ jit_cookie())); 336053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block xor_(dst, jit_cookie()); 337053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block } else { 338053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block Set(dst, x); 339053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block } 340053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block} 341053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block 342053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block 343053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Blockvoid MacroAssembler::SafePush(const Immediate& x) { 344053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block if (IsUnsafeImmediate(x) && jit_cookie() != 0) { 345053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block push(Immediate(x.x_ ^ jit_cookie())); 346053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block xor_(Operand(esp, 0), Immediate(jit_cookie())); 347053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block } else { 348053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block push(x); 349053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block } 350053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block} 351053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block 352053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block 35369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) { 35469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // see ROOT_ACCESSOR macro in factory.h 3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> value(&isolate()->heap()->roots_array_start()[index]); 3563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmp(with, value); 3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CompareRoot(const Operand& with, 3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::RootListIndex index) { 3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // see ROOT_ACCESSOR macro in factory.h 3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> value(&isolate()->heap()->roots_array_start()[index]); 364c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch cmp(with, value); 365c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch} 366c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 367c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpObjectType(Register heap_object, 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstanceType type, 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register map) { 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(map, FieldOperand(heap_object, HeapObject::kMapOffset)); 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CmpInstanceType(map, type); 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpInstanceType(Register map, InstanceType type) { 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmpb(FieldOperand(map, Map::kInstanceTypeOffset), 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static_cast<int8_t>(type)); 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::CheckFastElements(Register map, 3833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label* fail, 3843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label::Distance distance) { 3853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS == 0); 3863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(FAST_ELEMENTS == 1); 3873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmpb(FieldOperand(map, Map::kBitField2Offset), 3883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Map::kMaximumBitField2FastElementValue); 3893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(above, fail, distance); 3903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 3913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckFastObjectElements(Register map, 3943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* fail, 3953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance distance) { 3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS == 0); 3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(FAST_ELEMENTS == 1); 3983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmpb(FieldOperand(map, Map::kBitField2Offset), 3993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Map::kMaximumBitField2FastSmiOnlyElementValue); 4003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(below_equal, fail, distance); 4013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch cmpb(FieldOperand(map, Map::kBitField2Offset), 4023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Map::kMaximumBitField2FastElementValue); 4033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch j(above, fail, distance); 4043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 4053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 4063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckFastSmiOnlyElements(Register map, 4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* fail, 4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance distance) { 4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS == 0); 4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmpb(FieldOperand(map, Map::kBitField2Offset), 4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Map::kMaximumBitField2FastSmiOnlyElementValue); 4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(above, fail, distance); 4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::StoreNumberToDoubleElements( 4183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register maybe_number, 4193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register elements, 4203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register key, 4213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1, 4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch XMMRegister scratch2, 4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* fail, 4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool specialize_for_processor) { 4253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label smi_value, done, maybe_nan, not_nan, is_nan, have_double_value; 4263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JumpIfSmi(maybe_number, &smi_value, Label::kNear); 4273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckMap(maybe_number, 4293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate()->factory()->heap_number_map(), 4303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch fail, 4313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DONT_DO_SMI_CHECK); 4323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Double value, canonicalize NaN. 4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uint32_t offset = HeapNumber::kValueOffset + sizeof(kHoleNanLower32); 4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmp(FieldOperand(maybe_number, offset), 4363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(kNaNOrInfinityLowerBoundUpper32)); 4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(greater_equal, &maybe_nan, Label::kNear); 4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(¬_nan); 4403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference canonical_nan_reference = 4413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference::address_of_canonical_non_hole_nan(); 4423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (CpuFeatures::IsSupported(SSE2) && specialize_for_processor) { 4433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CpuFeatures::Scope use_sse2(SSE2); 4443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movdbl(scratch2, FieldOperand(maybe_number, HeapNumber::kValueOffset)); 4453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&have_double_value); 4463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movdbl(FieldOperand(elements, key, times_4, FixedDoubleArray::kHeaderSize), 4473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch2); 4483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 4493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch fld_d(FieldOperand(maybe_number, HeapNumber::kValueOffset)); 4503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&have_double_value); 4513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch fstp_d(FieldOperand(elements, key, times_4, FixedDoubleArray::kHeaderSize)); 4523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch jmp(&done); 4543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&maybe_nan); 4563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise 4573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // it's an Infinity, and the non-NaN code path applies. 4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(greater, &is_nan, Label::kNear); 4593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmp(FieldOperand(maybe_number, HeapNumber::kValueOffset), Immediate(0)); 4603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(zero, ¬_nan); 4613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&is_nan); 4623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (CpuFeatures::IsSupported(SSE2) && specialize_for_processor) { 4633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CpuFeatures::Scope use_sse2(SSE2); 4643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movdbl(scratch2, Operand::StaticVariable(canonical_nan_reference)); 4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 4663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch fld_d(Operand::StaticVariable(canonical_nan_reference)); 4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch jmp(&have_double_value, Label::kNear); 4693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&smi_value); 4713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Value is a smi. Convert to a double and store. 4723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Preserve original value. 4733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(scratch1, maybe_number); 4743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiUntag(scratch1); 4753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (CpuFeatures::IsSupported(SSE2) && specialize_for_processor) { 4763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CpuFeatures::Scope fscope(SSE2); 4773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cvtsi2sd(scratch2, scratch1); 4783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movdbl(FieldOperand(elements, key, times_4, FixedDoubleArray::kHeaderSize), 4793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch2); 4803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 4813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch push(scratch1); 4823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch fild_s(Operand(esp, 0)); 4833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch pop(scratch1); 4843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch fstp_d(FieldOperand(elements, key, times_4, FixedDoubleArray::kHeaderSize)); 4853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&done); 4873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 4883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CompareMap(Register obj, 4913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> map, 4923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* early_success, 4933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompareMapMode mode) { 4943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmp(FieldOperand(obj, HeapObject::kMapOffset), map); 4953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (mode == ALLOW_ELEMENT_TRANSITION_MAPS) { 4963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Map* transitioned_fast_element_map( 4973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch map->LookupElementsTransitionMap(FAST_ELEMENTS, NULL)); 4983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(transitioned_fast_element_map == NULL || 4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch map->elements_kind() != FAST_ELEMENTS); 5003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (transitioned_fast_element_map != NULL) { 5013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(equal, early_success, Label::kNear); 5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmp(FieldOperand(obj, HeapObject::kMapOffset), 5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map>(transitioned_fast_element_map)); 5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 5053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Map* transitioned_double_map( 5073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch map->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, NULL)); 5083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(transitioned_double_map == NULL || 5093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch map->elements_kind() == FAST_SMI_ONLY_ELEMENTS); 5103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (transitioned_double_map != NULL) { 5113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(equal, early_success, Label::kNear); 5123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmp(FieldOperand(obj, HeapObject::kMapOffset), 5133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map>(transitioned_double_map)); 5143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 5153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 5163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 5173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::CheckMap(Register obj, 5203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Handle<Map> map, 5213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Label* fail, 5223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiCheckType smi_check_type, 5233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompareMapMode mode) { 524257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (smi_check_type == DO_SMI_CHECK) { 525257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch JumpIfSmi(obj, fail); 5263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 5273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label success; 5293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompareMap(obj, map, &success, mode); 5303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu j(not_equal, fail); 5313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&success); 5323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 5333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 5343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 535257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::DispatchMap(Register obj, 536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Map> map, 537257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> success, 538257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SmiCheckType smi_check_type) { 539257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label fail; 540257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (smi_check_type == DO_SMI_CHECK) { 541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch JumpIfSmi(obj, &fail); 542257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 543257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cmp(FieldOperand(obj, HeapObject::kMapOffset), Immediate(map)); 544257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(equal, success); 545257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 546257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bind(&fail); 547257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 548257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 549257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 550e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeCondition MacroAssembler::IsObjectStringType(Register heap_object, 551e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register map, 552e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register instance_type) { 553e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke mov(map, FieldOperand(heap_object, HeapObject::kMapOffset)); 554e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset)); 55569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kNotStringTag != 0); 556e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke test(instance_type, Immediate(kIsNotStringMask)); 557e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return zero; 558e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 559e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 560e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 5617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid MacroAssembler::IsObjectJSObjectType(Register heap_object, 5627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register map, 5637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch, 5647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label* fail) { 5657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch mov(map, FieldOperand(heap_object, HeapObject::kMapOffset)); 5667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch IsInstanceJSObjectType(map, scratch, fail); 5677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 5687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 5697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 5707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid MacroAssembler::IsInstanceJSObjectType(Register map, 5717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch, 5727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label* fail) { 5737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch movzx_b(scratch, FieldOperand(map, Map::kInstanceTypeOffset)); 5743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch sub(scratch, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); 5753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch cmp(scratch, 5763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch LAST_NONCALLABLE_SPEC_OBJECT_TYPE - FIRST_NONCALLABLE_SPEC_OBJECT_TYPE); 5777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch j(above, fail); 5787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 5797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 5807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::FCmp() { 5828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (CpuFeatures::IsSupported(CMOV)) { 5833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block fucomip(); 5843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch fstp(0); 5853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 5863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block fucompp(); 5873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block push(eax); 5883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block fnstsw_ax(); 5893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block sahf(); 5903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block pop(eax); 5913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5956ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::AbortIfNotNumber(Register object) { 596402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Label ok; 5973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch JumpIfSmi(object, &ok); 598402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu cmp(FieldOperand(object, HeapObject::kMapOffset), 59944f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()->factory()->heap_number_map()); 6006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Assert(equal, "Operand not a number"); 601402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu bind(&ok); 602402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 603402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 604402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 6056ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::AbortIfNotSmi(Register object) { 6066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block test(object, Immediate(kSmiTagMask)); 607756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Assert(equal, "Operand is not a smi"); 608756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick} 609756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 610756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 61180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::AbortIfNotString(Register object) { 61280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen test(object, Immediate(kSmiTagMask)); 61380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Assert(not_equal, "Operand is not a string"); 61480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen push(object); 61580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen mov(object, FieldOperand(object, HeapObject::kMapOffset)); 61680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen CmpInstanceType(object, FIRST_NONSTRING_TYPE); 61780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen pop(object); 61880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Assert(below, "Operand is not a string"); 61980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 62080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 62180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 622756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid MacroAssembler::AbortIfSmi(Register object) { 623756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick test(object, Immediate(kSmiTagMask)); 624756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Assert(not_equal, "Operand is a smi"); 6256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 6266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 6276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::EnterFrame(StackFrame::Type type) { 629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(ebp); 6303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(ebp, esp); 631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(esi); 632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Immediate(Smi::FromInt(type))); 633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Immediate(CodeObject())); 63444f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 63544f0eee88ff00398ff7f715fab053374d808c90dSteve Block cmp(Operand(esp, 0), Immediate(isolate()->factory()->undefined_value())); 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(not_equal, "code object not properly patched"); 637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LeaveFrame(StackFrame::Type type) { 64244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmp(Operand(ebp, StandardFrameConstants::kMarkerOffset), 644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(Smi::FromInt(type))); 645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(equal, "stack frame types must match"); 646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block leave(); 648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 65080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 65180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::EnterExitFramePrologue() { 6523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the frame structure on the stack. 653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize); 654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize); 655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize); 656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(ebp); 6573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(ebp, esp); 658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 65980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Reserve room for entry stack pointer and push the code object. 660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize); 661402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu push(Immediate(0)); // Saved entry sp, patched before call. 662402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu push(Immediate(CodeObject())); // Accessed from ExitFrame::code_slot. 663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save the frame pointer and the context in top. 665589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress, 66644f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()); 667589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ExternalReference context_address(Isolate::kContextAddress, 66844f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()); 669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(Operand::StaticVariable(c_entry_fp_address), ebp); 670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(Operand::StaticVariable(context_address), esi); 671d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid MacroAssembler::EnterExitFrameEpilogue(int argc, bool save_doubles) { 675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Optionally save all XMM registers. 676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (save_doubles) { 677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CpuFeatures::Scope scope(SSE2); 678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int space = XMMRegister::kNumRegisters * kDoubleSize + argc * kPointerSize; 6793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch sub(esp, Immediate(space)); 6801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block const int offset = -2 * kPointerSize; 681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < XMMRegister::kNumRegisters; i++) { 682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch XMMRegister reg = XMMRegister::from_code(i); 683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch movdbl(Operand(ebp, offset - ((i + 1) * kDoubleSize)), reg); 684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 6863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch sub(esp, Immediate(argc * kPointerSize)); 687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the required frame alignment for the OS. 69044f0eee88ff00398ff7f715fab053374d808c90dSteve Block const int kFrameAlignment = OS::ActivationFrameAlignment(); 691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (kFrameAlignment > 0) { 692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(IsPowerOf2(kFrameAlignment)); 693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block and_(esp, -kFrameAlignment); 694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the saved entry sp. 697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(Operand(ebp, ExitFrameConstants::kSPOffset), esp); 698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid MacroAssembler::EnterExitFrame(bool save_doubles) { 70280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen EnterExitFramePrologue(); 703d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 7043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up argc and argv in callee-saved registers. 705d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; 7063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(edi, eax); 707d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block lea(esi, Operand(ebp, eax, times_4, offset)); 708d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 70944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Reserve space for argc, argv and isolate. 71044f0eee88ff00398ff7f715fab053374d808c90dSteve Block EnterExitFrameEpilogue(3, save_doubles); 711d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 712d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 713d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 7148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid MacroAssembler::EnterApiExitFrame(int argc) { 71580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen EnterExitFramePrologue(); 716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch EnterExitFrameEpilogue(argc, false); 717d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 718d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 719d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid MacroAssembler::LeaveExitFrame(bool save_doubles) { 721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Optionally restore all XMM registers. 722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (save_doubles) { 723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CpuFeatures::Scope scope(SSE2); 7241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block const int offset = -2 * kPointerSize; 725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < XMMRegister::kNumRegisters; i++) { 726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch XMMRegister reg = XMMRegister::from_code(i); 727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch movdbl(reg, Operand(ebp, offset - ((i + 1) * kDoubleSize))); 728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the return address from the stack and restore the frame pointer. 732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(ecx, Operand(ebp, 1 * kPointerSize)); 733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(ebp, Operand(ebp, 0 * kPointerSize)); 734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pop the arguments and the receiver from the caller stack. 736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lea(esp, Operand(esi, 1 * kPointerSize)); 737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Push the return address to get ready to return. 7398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang push(ecx); 7408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 7418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang LeaveExitFrameEpilogue(); 7428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang} 7438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 7448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid MacroAssembler::LeaveExitFrameEpilogue() { 745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore current context from top and clear it in debug mode. 746589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ExternalReference context_address(Isolate::kContextAddress, isolate()); 747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(esi, Operand::StaticVariable(context_address)); 748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(Operand::StaticVariable(context_address), Immediate(0)); 750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Clear the top frame. 753589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress, 75444f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()); 755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(Operand::StaticVariable(c_entry_fp_address), Immediate(0)); 756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid MacroAssembler::LeaveApiExitFrame() { 7603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(esp, ebp); 7618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang pop(ebp); 7628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 7638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang LeaveExitFrameEpilogue(); 7648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang} 7658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 7668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 7673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::PushTryHandler(StackHandler::Kind kind, 7683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int handler_index) { 769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Adjust this code if not the case. 77069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); 77169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); 7723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); 7733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); 7743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); 7753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); 7763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We will build up the handler from the bottom by pushing on the stack. 7783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // First push the frame pointer and context. 7793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (kind == StackHandler::JS_ENTRY) { 7803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The frame pointer does not point to a JS frame so we save NULL for 7813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ebp. We expect the code throwing an exception to check ebp before 7823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // dereferencing it to restore the context. 78385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch push(Immediate(0)); // NULL frame pointer. 78485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch push(Immediate(Smi::FromInt(0))); // No context. 7853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 7863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch push(ebp); 7873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch push(esi); 788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 7893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Push the state and the code object. 7903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch unsigned state = 7913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StackHandler::IndexField::encode(handler_index) | 7923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StackHandler::KindField::encode(kind); 7933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch push(Immediate(state)); 7943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Push(CodeObject()); 7953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Link the current handler as the next handler. 7973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference handler_address(Isolate::kHandlerAddress, isolate()); 7983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch push(Operand::StaticVariable(handler_address)); 7993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set this new handler as the current one. 8003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(Operand::StaticVariable(handler_address), esp); 801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 804e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::PopTryHandler() { 80569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); 8063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference handler_address(Isolate::kHandlerAddress, isolate()); 8073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch pop(Operand::StaticVariable(handler_address)); 8083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(esp, Immediate(StackHandlerConstants::kSize - kPointerSize)); 8093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 8103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::JumpToHandlerEntry() { 8133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Compute the handler entry address and jump to it. The handler table is 8143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a fixed array of (smi-tagged) code offsets. 8153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // eax = exception, edi = code object, edx = state. 8163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(ebx, FieldOperand(edi, Code::kHandlerTableOffset)); 8173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch shr(edx, StackHandler::kKindWidth); 8183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(edx, FieldOperand(ebx, edx, times_4, FixedArray::kHeaderSize)); 8193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiUntag(edx); 8203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lea(edi, FieldOperand(edi, edx, times_1, Code::kHeaderSize)); 8213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch jmp(edi); 822e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 823e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 824e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 825e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::Throw(Register value) { 826e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Adjust this code if not the case. 82769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); 82869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); 8293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); 8303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); 8313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); 8323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); 8333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The exception is expected in eax. 835e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!value.is(eax)) { 836e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch mov(eax, value); 837e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 8383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Drop the stack pointer to the top of the top handler. 8393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference handler_address(Isolate::kHandlerAddress, isolate()); 84085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch mov(esp, Operand::StaticVariable(handler_address)); 8413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Restore the next handler. 84285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch pop(Operand::StaticVariable(handler_address)); 8433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Remove the code object and state, compute the handler address in edi. 8453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch pop(edi); // Code object. 8463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch pop(edx); // Index and state. 8473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Restore the context and frame pointer. 84969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch pop(esi); // Context. 85069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch pop(ebp); // Frame pointer. 851e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 85269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // If the handler is a JS frame, restore the context to the frame. 8533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // (kind == ENTRY) == (ebp == 0) == (esi == 0), so we could test either 8543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ebp or esi. 855257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label skip; 8563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test(esi, esi); 8573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(zero, &skip, Label::kNear); 85869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi); 859e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch bind(&skip); 860e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 8613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JumpToHandlerEntry(); 862e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 863e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 864e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 8653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::ThrowUncatchable(Register value) { 866e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Adjust this code if not the case. 86769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); 86869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); 8693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); 8703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); 8713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); 8723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); 873e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 8743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The exception is expected in eax. 8755d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (!value.is(eax)) { 876592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch mov(eax, value); 877e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 8783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Drop the stack pointer to the top of the top stack handler. 8793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference handler_address(Isolate::kHandlerAddress, isolate()); 88085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch mov(esp, Operand::StaticVariable(handler_address)); 881592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 8823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Unwind the handlers until the top ENTRY handler is found. 8833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label fetch_next, check_kind; 8843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch jmp(&check_kind, Label::kNear); 8853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&fetch_next); 8863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(esp, Operand(esp, StackHandlerConstants::kNextOffset)); 887592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 8883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&check_kind); 8893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(StackHandler::JS_ENTRY == 0); 8903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test(Operand(esp, StackHandlerConstants::kStateOffset), 8913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(StackHandler::KindField::kMask)); 8923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(not_zero, &fetch_next); 89385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 8943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set the top handler address to next handler past the top ENTRY handler. 8953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch pop(Operand::StaticVariable(handler_address)); 89685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 8973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Remove the code object and state, compute the handler address in edi. 8983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch pop(edi); // Code object. 8993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch pop(edx); // Index and state. 900e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 9013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Clear the context pointer and frame pointer (0 was saved in the handler). 9023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch pop(esi); 903e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch pop(ebp); 904e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 9053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JumpToHandlerEntry(); 906e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 907e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 908e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, 910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label same_contexts; 913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!holder_reg.is(scratch)); 915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load current lexical context from the stack frame. 917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(scratch, Operand(ebp, StandardFrameConstants::kContextOffset)); 918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // When generating debug code, make sure the lexical context is set. 92044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 9213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmp(scratch, Immediate(0)); 922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(not_equal, "we should not have an empty lexical context"); 923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the global context of the current context. 925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; 926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(scratch, FieldOperand(scratch, offset)); 927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(scratch, FieldOperand(scratch, GlobalObject::kGlobalContextOffset)); 928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check the context is a global context. 93044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(scratch); 932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Read the first word and compare to global_context_map. 933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); 93444f0eee88ff00398ff7f715fab053374d808c90dSteve Block cmp(scratch, isolate()->factory()->global_context_map()); 935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(equal, "JSGlobalObject::global_context should be a global context."); 936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pop(scratch); 937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if both contexts are the same. 940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmp(scratch, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); 941257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(equal, &same_contexts); 942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compare security tokens, save holder_reg on the stack so we can use it 944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // as a temporary register. 945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // TODO(119): avoid push(holder_reg)/pop(holder_reg) 947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(holder_reg); 948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the security token in the calling global object is 949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // compatible with the security token in the receiving global 950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // object. 951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(holder_reg, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); 952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check the context is a global context. 95444f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 95544f0eee88ff00398ff7f715fab053374d808c90dSteve Block cmp(holder_reg, isolate()->factory()->null_value()); 956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(not_equal, "JSGlobalProxy::context() should not be null."); 957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(holder_reg); 959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Read the first word and compare to global_context_map(), 960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(holder_reg, FieldOperand(holder_reg, HeapObject::kMapOffset)); 96144f0eee88ff00398ff7f715fab053374d808c90dSteve Block cmp(holder_reg, isolate()->factory()->global_context_map()); 962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(equal, "JSGlobalObject::global_context should be a global context."); 963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pop(holder_reg); 964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int token_offset = Context::kHeaderSize + 967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Context::SECURITY_TOKEN_INDEX * kPointerSize; 968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(scratch, FieldOperand(scratch, token_offset)); 969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmp(scratch, FieldOperand(holder_reg, token_offset)); 970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pop(holder_reg); 971257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(not_equal, miss); 972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&same_contexts); 974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 977c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch// Compute the hash code from the untagged key. This must be kept in sync 978c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch// with ComputeIntegerHash in utils.h. 979c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch// 980c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch// Note: r0 will contain hash code 981c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdochvoid MacroAssembler::GetNumberHash(Register r0, Register scratch) { 982c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // Xor original key with a seed. 983c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch if (Serializer::enabled()) { 9843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference roots_array_start = 9853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference::roots_array_start(isolate()); 986c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch mov(scratch, Immediate(Heap::kHashSeedRootIndex)); 9873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(scratch, 9883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand::StaticArray(scratch, times_pointer_size, roots_array_start)); 989c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch SmiUntag(scratch); 9903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch xor_(r0, scratch); 991c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch } else { 992c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch int32_t seed = isolate()->heap()->HashSeed(); 9933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch xor_(r0, Immediate(seed)); 994c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch } 995c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 996c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // hash = ~hash + (hash << 15); 997c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch mov(scratch, r0); 998c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch not_(r0); 999c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch shl(scratch, 15); 10003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(r0, scratch); 1001c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // hash = hash ^ (hash >> 12); 1002c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch mov(scratch, r0); 1003c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch shr(scratch, 12); 10043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch xor_(r0, scratch); 1005c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // hash = hash + (hash << 2); 1006c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch lea(r0, Operand(r0, r0, times_4, 0)); 1007c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // hash = hash ^ (hash >> 4); 1008c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch mov(scratch, r0); 1009c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch shr(scratch, 4); 10103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch xor_(r0, scratch); 1011c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // hash = hash * 2057; 1012c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch imul(r0, r0, 2057); 1013c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // hash = hash ^ (hash >> 16); 1014c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch mov(scratch, r0); 1015c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch shr(scratch, 16); 10163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch xor_(r0, scratch); 1017c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch} 1018c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 1019c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 1020c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 10213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::LoadFromNumberDictionary(Label* miss, 10223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register elements, 10233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register key, 10243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register r0, 10253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register r1, 10263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register r2, 10273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register result) { 10283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Register use: 10293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // 10303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // elements - holds the slow-case elements of the receiver and is unchanged. 10313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // 10323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // key - holds the smi key on entry and is unchanged. 10333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // 10343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Scratch registers: 10353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // 10363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // r0 - holds the untagged key on entry and holds the hash once computed. 10373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // 10383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // r1 - used to hold the capacity mask of the dictionary 10393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // 10403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // r2 - used for the index into the dictionary. 10413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // 10423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // result - holds the result on exit if the load succeeds and we fall through. 10433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 10443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label done; 10453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 1046c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch GetNumberHash(r0, r1); 10473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 10483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Compute capacity mask. 1049c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch mov(r1, FieldOperand(elements, SeededNumberDictionary::kCapacityOffset)); 10503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch shr(r1, kSmiTagSize); // convert smi to int 10513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch dec(r1); 10523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 10533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Generate an unrolled loop that performs a few probes before giving up. 10543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch const int kProbes = 4; 10553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch for (int i = 0; i < kProbes; i++) { 10563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Use r2 for index calculations and keep the hash intact in r0. 10573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch mov(r2, r0); 10583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Compute the masked index: (hash + i + i * i) & mask. 10593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (i > 0) { 10603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(r2, Immediate(SeededNumberDictionary::GetProbeOffset(i))); 10613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 10623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(r2, r1); 10633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 10643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Scale the index by multiplying by the entry size. 1065c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch ASSERT(SeededNumberDictionary::kEntrySize == 3); 10663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3 10673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 10683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check if the key matches. 10693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch cmp(key, FieldOperand(elements, 10703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch r2, 10713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch times_pointer_size, 1072c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch SeededNumberDictionary::kElementsStartOffset)); 10733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (i != (kProbes - 1)) { 10743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch j(equal, &done); 10753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 10763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch j(not_equal, miss); 10773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 10783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 10793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 10803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bind(&done); 10813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check that the value is a normal propety. 10823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch const int kDetailsOffset = 1083c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize; 10843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT_EQ(NORMAL, 0); 10853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset), 1086589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Immediate(PropertyDetails::TypeField::kMask << kSmiTagSize)); 10873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch j(not_zero, miss); 10883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 10893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Get the value at the masked, scaled index. 10903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch const int kValueOffset = 1091c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch SeededNumberDictionary::kElementsStartOffset + kPointerSize; 10923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch mov(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); 10933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 10943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 10953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LoadAllocationTopHelper(Register result, 1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags) { 1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_top = 110044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::new_space_allocation_top_address(isolate()); 1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Just return if allocation top is already known. 1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((flags & RESULT_CONTAINS_TOP) != 0) { 1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // No use of scratch if allocation top is provided. 1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(scratch.is(no_reg)); 1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Assert that result actually contains top on entry. 1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmp(result, Operand::StaticVariable(new_space_allocation_top)); 1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(equal, "Unexpected allocation top"); 1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Move address of new object to result. Use scratch register if available. 1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (scratch.is(no_reg)) { 1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(result, Operand::StaticVariable(new_space_allocation_top)); 1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 11183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(scratch, Immediate(new_space_allocation_top)); 1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(result, Operand(scratch, 0)); 1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::UpdateAllocationTopHelper(Register result_end, 1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch) { 112644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 1127d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block test(result_end, Immediate(kObjectAlignmentMask)); 1128d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Check(zero, "Unaligned allocation in new space"); 1129d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1130d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_top = 113244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::new_space_allocation_top_address(isolate()); 1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update new top. Use scratch if available. 1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (scratch.is(no_reg)) { 1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(Operand::StaticVariable(new_space_allocation_top), result_end); 1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(Operand(scratch, 0), result_end); 1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(int object_size, 1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result_end, 1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required, 1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags) { 11495913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!FLAG_inline_new) { 115044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 11515913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // Trash the registers to simulate an allocation failure. 11525913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck mov(result, Immediate(0x7091)); 11535913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (result_end.is_valid()) { 11545913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck mov(result_end, Immediate(0x7191)); 11555913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 11565913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (scratch.is_valid()) { 11575913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck mov(scratch, Immediate(0x7291)); 11585913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 11595913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 11605913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck jmp(gc_required); 11615913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck return; 11625913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!result.is(result_end)); 1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load address of new object into result. 11668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang LoadAllocationTopHelper(result, scratch, flags); 1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1168bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Register top_reg = result_end.is_valid() ? result_end : result; 1169bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate new top and bail out if new space is exhausted. 1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_limit = 117244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::new_space_allocation_limit_address(isolate()); 1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 11741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (!top_reg.is(result)) { 11751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block mov(top_reg, result); 1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 11773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(top_reg, Immediate(object_size)); 1178257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(carry, gc_required); 1179bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch cmp(top_reg, Operand::StaticVariable(new_space_allocation_limit)); 1180257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(above, gc_required); 1181e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1182e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Update allocation top. 1183bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch UpdateAllocationTopHelper(top_reg, scratch); 1184bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 1185bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Tag result if requested. 1186bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if (top_reg.is(result)) { 1187bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if ((flags & TAG_OBJECT) != 0) { 11883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch sub(result, Immediate(object_size - kHeapObjectTag)); 1189bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } else { 11903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch sub(result, Immediate(object_size)); 1191bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } 1192bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } else if ((flags & TAG_OBJECT) != 0) { 11933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(result, Immediate(kHeapObjectTag)); 1194bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } 1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(int header_size, 1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ScaleFactor element_size, 1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register element_count, 1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result_end, 1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required, 1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags) { 12065913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!FLAG_inline_new) { 120744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 12085913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // Trash the registers to simulate an allocation failure. 12095913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck mov(result, Immediate(0x7091)); 12105913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck mov(result_end, Immediate(0x7191)); 12115913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (scratch.is_valid()) { 12125913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck mov(scratch, Immediate(0x7291)); 12135913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 12145913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // Register element_count is not modified by the function. 12155913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 12165913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck jmp(gc_required); 12175913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck return; 12185913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!result.is(result_end)); 1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load address of new object into result. 12228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang LoadAllocationTopHelper(result, scratch, flags); 1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate new top and bail out if new space is exhausted. 1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_limit = 122644f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::new_space_allocation_limit_address(isolate()); 12271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 12281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // We assume that element_count*element_size + header_size does not 12291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // overflow. 12301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block lea(result_end, Operand(element_count, element_size, header_size)); 12313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(result_end, result); 12321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block j(carry, gc_required); 1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmp(result_end, Operand::StaticVariable(new_space_allocation_limit)); 1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(above, gc_required); 1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Tag result if requested. 1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((flags & TAG_OBJECT) != 0) { 1238e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke lea(result, Operand(result, kHeapObjectTag)); 1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1240e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1241e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Update allocation top. 1242e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UpdateAllocationTopHelper(result_end, scratch); 1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(Register object_size, 1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result_end, 1249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required, 1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags) { 12525913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!FLAG_inline_new) { 125344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 12545913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // Trash the registers to simulate an allocation failure. 12555913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck mov(result, Immediate(0x7091)); 12565913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck mov(result_end, Immediate(0x7191)); 12575913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (scratch.is_valid()) { 12585913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck mov(scratch, Immediate(0x7291)); 12595913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 12605913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // object_size is left unchanged by this function. 12615913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 12625913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck jmp(gc_required); 12635913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck return; 12645913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!result.is(result_end)); 1266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load address of new object into result. 12688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang LoadAllocationTopHelper(result, scratch, flags); 1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate new top and bail out if new space is exhausted. 1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_limit = 127244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::new_space_allocation_limit_address(isolate()); 1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!object_size.is(result_end)) { 1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(result_end, object_size); 1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 12763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(result_end, result); 1277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(carry, gc_required); 1278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmp(result_end, Operand::StaticVariable(new_space_allocation_limit)); 1279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(above, gc_required); 1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Tag result if requested. 1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((flags & TAG_OBJECT) != 0) { 1283e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke lea(result, Operand(result, kHeapObjectTag)); 1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1285e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1286e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Update allocation top. 1287e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UpdateAllocationTopHelper(result_end, scratch); 1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::UndoAllocationInNewSpace(Register object) { 1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference new_space_allocation_top = 129344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::new_space_allocation_top_address(isolate()); 1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure the object has no tag before resetting top. 12963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(object, Immediate(~kHeapObjectTagMask)); 1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmp(object, Operand::StaticVariable(new_space_allocation_top)); 1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Check(below, "Undo allocation of non allocated memory"); 1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(Operand::StaticVariable(new_space_allocation_top), object); 1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::AllocateHeapNumber(Register result, 13063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register scratch1, 13073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Register scratch2, 13083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label* gc_required) { 13093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Allocate heap number in new space. 13103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block AllocateInNewSpace(HeapNumber::kSize, 13113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block result, 13123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block scratch1, 13133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block scratch2, 13143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block gc_required, 13153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block TAG_OBJECT); 13163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Set the map. 13183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block mov(FieldOperand(result, HeapObject::kMapOffset), 131944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Immediate(isolate()->factory()->heap_number_map())); 13203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 13213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1323d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::AllocateTwoByteString(Register result, 1324d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register length, 1325d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch1, 1326d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch2, 1327d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch3, 1328d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label* gc_required) { 1329d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Calculate the number of bytes needed for the characters in the string while 1330d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // observing object alignment. 1331d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); 1332d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(kShortSize == 2); 1333e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // scratch1 = length * 2 + kObjectAlignmentMask. 1334e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke lea(scratch1, Operand(length, length, times_1, kObjectAlignmentMask)); 13353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(scratch1, Immediate(~kObjectAlignmentMask)); 1336d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1337d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Allocate two byte string in new space. 1338d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block AllocateInNewSpace(SeqTwoByteString::kHeaderSize, 1339d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block times_1, 1340d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block scratch1, 1341d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result, 1342d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block scratch2, 1343d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block scratch3, 1344d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block gc_required, 1345d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block TAG_OBJECT); 1346d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1347d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Set the map, length and hash field. 1348d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mov(FieldOperand(result, HeapObject::kMapOffset), 134944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Immediate(isolate()->factory()->string_map())); 13506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block mov(scratch1, length); 13516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block SmiTag(scratch1); 13526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block mov(FieldOperand(result, String::kLengthOffset), scratch1); 1353d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mov(FieldOperand(result, String::kHashFieldOffset), 1354d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Immediate(String::kEmptyHashField)); 1355d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1356d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1357d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1358d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::AllocateAsciiString(Register result, 1359d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register length, 1360d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch1, 1361d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch2, 1362d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch3, 1363d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label* gc_required) { 1364d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Calculate the number of bytes needed for the characters in the string while 1365d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // observing object alignment. 1366d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0); 1367d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mov(scratch1, length); 1368d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(kCharSize == 1); 13693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(scratch1, Immediate(kObjectAlignmentMask)); 13703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(scratch1, Immediate(~kObjectAlignmentMask)); 1371d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 13723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Allocate ASCII string in new space. 1373d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block AllocateInNewSpace(SeqAsciiString::kHeaderSize, 1374d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block times_1, 1375d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block scratch1, 1376d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result, 1377d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block scratch2, 1378d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block scratch3, 1379d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block gc_required, 1380d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block TAG_OBJECT); 1381d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1382d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Set the map, length and hash field. 1383d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mov(FieldOperand(result, HeapObject::kMapOffset), 138444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Immediate(isolate()->factory()->ascii_string_map())); 13856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block mov(scratch1, length); 13866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block SmiTag(scratch1); 13876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block mov(FieldOperand(result, String::kLengthOffset), scratch1); 1388d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mov(FieldOperand(result, String::kHashFieldOffset), 1389d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Immediate(String::kEmptyHashField)); 1390d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1391d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1392d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 13939ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrickvoid MacroAssembler::AllocateAsciiString(Register result, 13949ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick int length, 13959ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick Register scratch1, 13969ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick Register scratch2, 13979ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick Label* gc_required) { 13989ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick ASSERT(length > 0); 13999ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick 14003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Allocate ASCII string in new space. 14019ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick AllocateInNewSpace(SeqAsciiString::SizeFor(length), 14029ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick result, 14039ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick scratch1, 14049ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick scratch2, 14059ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick gc_required, 14069ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick TAG_OBJECT); 14079ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick 14089ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick // Set the map, length and hash field. 14099ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick mov(FieldOperand(result, HeapObject::kMapOffset), 141044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Immediate(isolate()->factory()->ascii_string_map())); 14119ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick mov(FieldOperand(result, String::kLengthOffset), 14129ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick Immediate(Smi::FromInt(length))); 14139ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick mov(FieldOperand(result, String::kHashFieldOffset), 14149ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick Immediate(String::kEmptyHashField)); 14159ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick} 14169ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick 14179ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick 1418589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid MacroAssembler::AllocateTwoByteConsString(Register result, 1419d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch1, 1420d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch2, 1421d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label* gc_required) { 1422d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Allocate heap number in new space. 1423d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block AllocateInNewSpace(ConsString::kSize, 1424d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result, 1425d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block scratch1, 1426d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block scratch2, 1427d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block gc_required, 1428d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block TAG_OBJECT); 1429d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1430d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Set the map. The other fields are left uninitialized. 1431d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mov(FieldOperand(result, HeapObject::kMapOffset), 143244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Immediate(isolate()->factory()->cons_string_map())); 1433d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1434d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1435d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1436d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::AllocateAsciiConsString(Register result, 1437d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch1, 1438d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register scratch2, 1439d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label* gc_required) { 1440d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Allocate heap number in new space. 1441d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block AllocateInNewSpace(ConsString::kSize, 1442d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result, 1443d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block scratch1, 1444d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block scratch2, 1445d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block gc_required, 1446d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block TAG_OBJECT); 1447d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1448d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Set the map. The other fields are left uninitialized. 1449d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mov(FieldOperand(result, HeapObject::kMapOffset), 145044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Immediate(isolate()->factory()->cons_ascii_string_map())); 1451d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1452d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1453b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1454589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid MacroAssembler::AllocateTwoByteSlicedString(Register result, 145569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Register scratch1, 145669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Register scratch2, 145769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Label* gc_required) { 145869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Allocate heap number in new space. 145969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch AllocateInNewSpace(SlicedString::kSize, 146069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch result, 146169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch scratch1, 146269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch scratch2, 146369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch gc_required, 146469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch TAG_OBJECT); 146569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 146669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Set the map. The other fields are left uninitialized. 146769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch mov(FieldOperand(result, HeapObject::kMapOffset), 146869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Immediate(isolate()->factory()->sliced_string_map())); 146969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch} 147069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 147169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 147269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid MacroAssembler::AllocateAsciiSlicedString(Register result, 147369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Register scratch1, 147469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Register scratch2, 147569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Label* gc_required) { 147669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Allocate heap number in new space. 147769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch AllocateInNewSpace(SlicedString::kSize, 147869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch result, 147969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch scratch1, 148069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch scratch2, 148169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch gc_required, 148269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch TAG_OBJECT); 148369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 148469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Set the map. The other fields are left uninitialized. 148569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch mov(FieldOperand(result, HeapObject::kMapOffset), 148669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Immediate(isolate()->factory()->sliced_ascii_string_map())); 148769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch} 148869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 148969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 1490b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// Copy memory, byte-by-byte, from source to destination. Not optimized for 1491b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// long or aligned copies. The contents of scratch and length are destroyed. 1492b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// Source and destination are incremented by length. 1493b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// Many variants of movsb, loop unrolling, word moves, and indexed operands 1494b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// have been tried here already, and this is fastest. 1495b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// A simpler loop is faster on small copies, but 30% slower on large ones. 1496b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// The cld() instruction must have been emitted, to set the direction flag(), 1497b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// before calling this function. 1498b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid MacroAssembler::CopyBytes(Register source, 1499b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register destination, 1500b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register length, 1501b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register scratch) { 1502b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label loop, done, short_string, short_loop; 1503b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Experimentation shows that the short string loop is faster if length < 10. 15043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmp(length, Immediate(10)); 1505b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch j(less_equal, &short_string); 1506b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1507b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(source.is(esi)); 1508b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(destination.is(edi)); 1509b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(length.is(ecx)); 1510b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1511b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Because source is 4-byte aligned in our uses of this function, 1512b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // we keep source aligned for the rep_movs call by copying the odd bytes 1513b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // at the end of the ranges. 1514b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch mov(scratch, Operand(source, length, times_1, -4)); 1515b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch mov(Operand(destination, length, times_1, -4), scratch); 1516b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch mov(scratch, ecx); 1517b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch shr(ecx, 2); 1518b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch rep_movs(); 15193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(scratch, Immediate(0x3)); 15203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(destination, scratch); 1521b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch jmp(&done); 1522b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1523b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch bind(&short_string); 15243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test(length, length); 1525b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch j(zero, &done); 1526b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1527b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch bind(&short_loop); 1528b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch mov_b(scratch, Operand(source, 0)); 1529b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch mov_b(Operand(destination, 0), scratch); 1530b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch inc(source); 1531b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch inc(destination); 1532b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch dec(length); 1533b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch j(not_zero, &short_loop); 1534b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1535b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch bind(&done); 15368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang} 15378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 1538d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 15393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::InitializeFieldsWithFiller(Register start_offset, 15403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register end_offset, 15413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register filler) { 15423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label loop, entry; 15433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch jmp(&entry); 15443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&loop); 15453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(Operand(start_offset, 0), filler); 15463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(start_offset, Immediate(kPointerSize)); 15473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&entry); 15483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmp(start_offset, end_offset); 15493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(less, &loop); 15503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 15513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::BooleanBitTest(Register object, 15543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int field_offset, 15553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int bit_index) { 15563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bit_index += kSmiTagSize + kSmiShiftSize; 15573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(IsPowerOf2(kBitsPerByte)); 15583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int byte_index = bit_index / kBitsPerByte; 15593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int byte_bit_index = bit_index & (kBitsPerByte - 1); 15603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test_b(FieldOperand(object, field_offset + byte_index), 15613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static_cast<byte>(1 << byte_bit_index)); 15623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 15633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::NegativeZeroTest(Register result, 1567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register op, 1568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* then_label) { 1569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label ok; 15703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test(result, result); 1571257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(not_zero, &ok); 15723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test(op, op); 1573257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(sign, then_label); 1574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&ok); 1575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::NegativeZeroTest(Register result, 1579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register op1, 1580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register op2, 1581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 1582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* then_label) { 1583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label ok; 15843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test(result, result); 1585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(not_zero, &ok); 15863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(scratch, op1); 15873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch or_(scratch, op2); 1588257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(sign, then_label); 1589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&ok); 1590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::TryGetFunctionPrototype(Register function, 1594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 1595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 15963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss, 15973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool miss_on_bound_function) { 1598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 15993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch JumpIfSmi(function, miss); 1600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the function really is a function. 1602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CmpObjectType(function, JS_FUNCTION_TYPE, result); 1603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(not_equal, miss); 1604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (miss_on_bound_function) { 16063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If a bound function, go to miss label. 16073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(scratch, 16083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldOperand(function, JSFunction::kSharedFunctionInfoOffset)); 16093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch BooleanBitTest(scratch, SharedFunctionInfo::kCompilerHintsOffset, 16103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SharedFunctionInfo::kBoundFunction); 16113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(not_zero, miss); 16123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 16133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure that the function has an instance prototype. 1615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label non_instance; 1616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block movzx_b(scratch, FieldOperand(result, Map::kBitFieldOffset)); 1617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block test(scratch, Immediate(1 << Map::kHasNonInstancePrototype)); 1618257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(not_zero, &non_instance); 1619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the prototype or initial map from the function. 1621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(result, 1622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 1623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the prototype or initial map is the hole, don't return it and 1625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // simply miss the cache instead. This will allow us to allocate a 1626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // prototype object on-demand in the runtime system. 16273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmp(result, Immediate(isolate()->factory()->the_hole_value())); 1628257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(equal, miss); 1629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the function does not have an initial map, we're done. 1631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label done; 1632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CmpObjectType(result, MAP_TYPE, scratch); 1633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(not_equal, &done); 1634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the prototype from the initial map. 1636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(result, FieldOperand(result, Map::kPrototypeOffset)); 1637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block jmp(&done); 1638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Non-instance prototype: Fetch prototype from constructor field 1640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // in initial map. 1641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&non_instance); 1642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(result, FieldOperand(result, Map::kConstructorOffset)); 1643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // All done. 1645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&done); 1646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::CallStub(CodeStub* stub, unsigned ast_id) { 16503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(AllowThisStubCall(stub)); // Calls are not allowed in some stubs. 1651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id); 1652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1655d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::TailCallStub(CodeStub* stub) { 16563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe()); 1657d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block jmp(stub->GetCode(), RelocInfo::CODE_TARGET); 1658d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1659d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1660d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 166185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochvoid MacroAssembler::StubReturn(int argc) { 166285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch ASSERT(argc >= 1 && generating_stub()); 166385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch ret((argc - 1) * kPointerSize); 1664592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch} 1665592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 1666592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 16673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool MacroAssembler::AllowThisStubCall(CodeStub* stub) { 16683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!has_frame_ && stub->SometimesSetsUpAFrame()) return false; 16693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe(); 16703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 16713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 16723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::IllegalOperation(int num_arguments) { 1674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (num_arguments > 0) { 16753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(esp, Immediate(num_arguments * kPointerSize)); 1676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 167744f0eee88ff00398ff7f715fab053374d808c90dSteve Block mov(eax, Immediate(isolate()->factory()->undefined_value())); 1678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 168180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::IndexFromHash(Register hash, Register index) { 168280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // The assert checks that the constants for the maximum number of digits 168380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // for an array index cached in the hash field and the number of bits 168480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // reserved for it does not conflict. 168580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < 168680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen (1 << String::kArrayIndexValueBits)); 168780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // We want the smi-tagged index in key. kArrayIndexValueMask has zeros in 168880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // the low kHashShift bits. 168980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen and_(hash, String::kArrayIndexValueMask); 169080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen STATIC_ASSERT(String::kHashShift >= kSmiTagSize && kSmiTag == 0); 169180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (String::kHashShift > kSmiTagSize) { 169280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen shr(hash, String::kHashShift - kSmiTagSize); 169380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 169480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (!index.is(hash)) { 169580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen mov(index, hash); 169680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 169780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 169880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 169980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CallRuntime(Runtime::FunctionId id, int num_arguments) { 1701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CallRuntime(Runtime::FunctionForId(id), num_arguments); 1702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid MacroAssembler::CallRuntimeSaveDoubles(Runtime::FunctionId id) { 170644f0eee88ff00398ff7f715fab053374d808c90dSteve Block const Runtime::Function* function = Runtime::FunctionForId(id); 1707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Set(eax, Immediate(function->nargs)); 170844f0eee88ff00398ff7f715fab053374d808c90dSteve Block mov(ebx, Immediate(ExternalReference(function, isolate()))); 17093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CEntryStub ces(1, kSaveFPRegs); 1710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CallStub(&ces); 1711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1712b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1713b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 171444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CallRuntime(const Runtime::Function* f, 171544f0eee88ff00398ff7f715fab053374d808c90dSteve Block int num_arguments) { 1716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the expected number of arguments of the runtime function is 1717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // constant, we check that the actual number of arguments match the 1718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // expectation. 1719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (f->nargs >= 0 && f->nargs != num_arguments) { 1720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block IllegalOperation(num_arguments); 1721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 1722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 17244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // TODO(1236192): Most runtime routines don't need the number of 17254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // arguments passed in because it is constant. At some point we 17264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // should remove this need and make the runtime routine entry code 17274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // smarter. 17284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Set(eax, Immediate(num_arguments)); 172944f0eee88ff00398ff7f715fab053374d808c90dSteve Block mov(ebx, Immediate(ExternalReference(f, isolate()))); 17304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke CEntryStub ces(1); 17314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke CallStub(&ces); 1732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1735bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid MacroAssembler::CallExternalReference(ExternalReference ref, 1736bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch int num_arguments) { 1737bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch mov(eax, Immediate(num_arguments)); 1738bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch mov(ebx, Immediate(ref)); 1739bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 1740bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch CEntryStub stub(1); 1741bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch CallStub(&stub); 1742bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 1743bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 1744bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 17456ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::TailCallExternalReference(const ExternalReference& ext, 17466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int num_arguments, 17476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int result_size) { 1748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // TODO(1236192): Most runtime routines don't need the number of 1749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // arguments passed in because it is constant. At some point we 1750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // should remove this need and make the runtime routine entry code 1751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // smarter. 1752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Set(eax, Immediate(num_arguments)); 17536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JumpToExternalReference(ext); 17546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 17556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17576ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::TailCallRuntime(Runtime::FunctionId fid, 17586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int num_arguments, 17596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int result_size) { 176044f0eee88ff00398ff7f715fab053374d808c90dSteve Block TailCallExternalReference(ExternalReference(fid, isolate()), 176144f0eee88ff00398ff7f715fab053374d808c90dSteve Block num_arguments, 176244f0eee88ff00398ff7f715fab053374d808c90dSteve Block result_size); 1763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// If true, a Handle<T> returned by value from a function with cdecl calling 1767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// convention will be returned directly as a value of location_ field in a 1768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// register eax. 1769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// If false, it is returned as a pointer to a preallocated by caller memory 1770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// region. Pointer to this region should be passed to a function as an 1771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// implicit first argument. 1772e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#if defined(USING_BSD_ABI) || defined(__MINGW32__) || defined(__CYGWIN__) 1773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic const bool kReturnHandlesDirectly = true; 17745913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck#else 1775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic const bool kReturnHandlesDirectly = false; 17765913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck#endif 17775913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck 17785913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck 17795913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckOperand ApiParameterOperand(int index) { 1780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return Operand( 1781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch esp, (index + (kReturnHandlesDirectly ? 0 : 1)) * kPointerSize); 1782d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1783d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1784d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 17853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::PrepareCallApiFunction(int argc) { 1786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (kReturnHandlesDirectly) { 17878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang EnterApiExitFrame(argc); 1788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // When handles are returned directly we don't have to allocate extra 17895913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // space for and pass an out parameter. 17903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (emit_debug_code()) { 17913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch mov(esi, Immediate(BitCast<int32_t>(kZapValue))); 17923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 1793e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 17945913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // We allocate two additional slots: return value and pointer to it. 17958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang EnterApiExitFrame(argc + 2); 1796e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 17975913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // The argument slots are filled as follows: 17985913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // 17993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // n + 1: output slot 18005913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // n: arg n 18015913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // ... 18025913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // 1: arg1 18033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // 0: pointer to the output slot 18048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 18053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch lea(esi, Operand(esp, (argc + 1) * kPointerSize)); 18063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch mov(Operand(esp, 0 * kPointerSize), esi); 180744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 18083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch mov(Operand(esi, 0), Immediate(0)); 18098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 18105913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 18118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang} 18128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 1813e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 18143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CallApiFunctionAndReturn(Address function_address, 18153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int stack_space) { 18165913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck ExternalReference next_address = 18175913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck ExternalReference::handle_scope_next_address(); 18185913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck ExternalReference limit_address = 18195913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck ExternalReference::handle_scope_limit_address(); 18205913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck ExternalReference level_address = 18215913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck ExternalReference::handle_scope_level_address(); 1822e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 18235913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // Allocate HandleScope in callee-save registers. 18245913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck mov(ebx, Operand::StaticVariable(next_address)); 18255913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck mov(edi, Operand::StaticVariable(limit_address)); 18265913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck add(Operand::StaticVariable(level_address), Immediate(1)); 18275913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck 18283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Call the api function. 18293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch call(function_address, RelocInfo::RUNTIME_ENTRY); 1830e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!kReturnHandlesDirectly) { 18323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // PrepareCallApiFunction saved pointer to the output slot into 18333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // callee-save register esi. 18343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch mov(eax, Operand(esi, 0)); 18355913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 1836e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 18375913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Label empty_handle; 18385913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Label prologue; 18395913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Label promote_scheduled_exception; 18405913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Label delete_allocated_handles; 18415913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Label leave_exit_frame; 18425913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck 18435913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // Check if the result handle holds 0. 18443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test(eax, eax); 1845257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(zero, &empty_handle); 18465913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // It was non-zero. Dereference to get the result value. 18475913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck mov(eax, Operand(eax, 0)); 18485913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck bind(&prologue); 18495913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // No more valid handles (the result handle was the last one). Restore 18505913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // previous handle scope. 18515913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck mov(Operand::StaticVariable(next_address), ebx); 18525913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck sub(Operand::StaticVariable(level_address), Immediate(1)); 18535913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Assert(above_equal, "Invalid HandleScope level"); 18545913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck cmp(edi, Operand::StaticVariable(limit_address)); 1855257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(not_equal, &delete_allocated_handles); 18565913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck bind(&leave_exit_frame); 18575913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck 18585913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // Check if the function scheduled an exception. 18595913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck ExternalReference scheduled_exception_address = 186044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::scheduled_exception_address(isolate()); 18615913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck cmp(Operand::StaticVariable(scheduled_exception_address), 186244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Immediate(isolate()->factory()->the_hole_value())); 1863257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(not_equal, &promote_scheduled_exception); 18648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang LeaveApiExitFrame(); 18658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang ret(stack_space * kPointerSize); 18665913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck bind(&promote_scheduled_exception); 18673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TailCallRuntime(Runtime::kPromoteScheduledException, 0, 1); 18683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 18695913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck bind(&empty_handle); 18705913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // It was zero; the result is undefined. 187144f0eee88ff00398ff7f715fab053374d808c90dSteve Block mov(eax, isolate()->factory()->undefined_value()); 18725913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck jmp(&prologue); 18735913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck 18745913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck // HandleScope limit has changed. Delete allocated extensions. 187544f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference delete_extensions = 187644f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::delete_handle_scope_extensions(isolate()); 18775913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck bind(&delete_allocated_handles); 18785913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck mov(Operand::StaticVariable(limit_address), edi); 18795913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck mov(edi, eax); 188044f0eee88ff00398ff7f715fab053374d808c90dSteve Block mov(Operand(esp, 0), Immediate(ExternalReference::isolate_address())); 188144f0eee88ff00398ff7f715fab053374d808c90dSteve Block mov(eax, Immediate(delete_extensions)); 18823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch call(eax); 18835913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck mov(eax, edi); 18845913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck jmp(&leave_exit_frame); 1885d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1886d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1887d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 18886ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::JumpToExternalReference(const ExternalReference& ext) { 1889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the entry point and jump to the C entry runtime stub. 1890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(ebx, Immediate(ext)); 1891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CEntryStub ces(1); 1892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block jmp(ces.GetCode(), RelocInfo::CODE_TARGET); 1893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1896257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SetCallKind(Register dst, CallKind call_kind) { 1897257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This macro takes the dst register to make the code more readable 1898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // at the call sites. However, the dst register has to be ecx to 1899257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // follow the calling convention which requires the call type to be 1900257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // in ecx. 1901257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(dst.is(ecx)); 1902257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (call_kind == CALL_AS_FUNCTION) { 1903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Set to some non-zero smi by updating the least significant 1904257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // byte. 19053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov_b(dst, 1 << kSmiTagSize); 1906257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1907257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Set to smi zero by clearing the register. 19083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch xor_(dst, dst); 1909257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1910257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1911257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1912257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokePrologue(const ParameterCount& expected, 1914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 1915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> code_constant, 1916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const Operand& code_operand, 1917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* done, 19183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool* definitely_mismatches, 1919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InvokeFlag flag, 1920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance done_near, 1921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const CallWrapper& call_wrapper, 1922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKind call_kind) { 1923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool definitely_matches = false; 19243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *definitely_mismatches = false; 1925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label invoke; 1926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (expected.is_immediate()) { 1927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(actual.is_immediate()); 1928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (expected.immediate() == actual.immediate()) { 1929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block definitely_matches = true; 1930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(eax, actual.immediate()); 1932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel; 1933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (expected.immediate() == sentinel) { 1934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Don't worry about adapting arguments for builtins that 1935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // don't want that done. Skip adaption code by making it look 1936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // like we have a match between expected and actual number of 1937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // arguments. 1938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block definitely_matches = true; 1939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 19403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *definitely_mismatches = true; 1941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(ebx, expected.immediate()); 1942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (actual.is_immediate()) { 1946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Expected is in register, actual is immediate. This is the 1947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // case when we invoke function values without going through the 1948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // IC mechanism. 1949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmp(expected.reg(), actual.immediate()); 1950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(equal, &invoke); 1951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(expected.reg().is(ebx)); 1952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(eax, actual.immediate()); 1953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (!expected.reg().is(actual.reg())) { 1954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Both expected and actual are in (different) registers. This 1955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is the case when we invoke functions using call and apply. 19563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmp(expected.reg(), actual.reg()); 1957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block j(equal, &invoke); 1958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(actual.reg().is(eax)); 1959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(expected.reg().is(ebx)); 1960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!definitely_matches) { 1964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> adaptor = 196544f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()->builtins()->ArgumentsAdaptorTrampoline(); 1966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!code_constant.is_null()) { 1967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(edx, Immediate(code_constant)); 19683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(edx, Immediate(Code::kHeaderSize - kHeapObjectTag)); 1969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (!code_operand.is_reg(edx)) { 1970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(edx, code_operand); 1971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (flag == CALL_FUNCTION) { 1974257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch call_wrapper.BeforeCall(CallSize(adaptor, RelocInfo::CODE_TARGET)); 1975257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SetCallKind(ecx, call_kind); 1976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block call(adaptor, RelocInfo::CODE_TARGET); 1977257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch call_wrapper.AfterCall(); 19783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!*definitely_mismatches) { 19793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch jmp(done, done_near); 19803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1982257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SetCallKind(ecx, call_kind); 1983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block jmp(adaptor, RelocInfo::CODE_TARGET); 1984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&invoke); 1986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeCode(const Operand& code, 1991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& expected, 1992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 1993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InvokeFlag flag, 1994257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const CallWrapper& call_wrapper, 1995257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKind call_kind) { 19963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // You can't call a function without a valid frame. 19973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(flag == JUMP_FUNCTION || has_frame()); 19983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1999257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 20003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool definitely_mismatches = false; 2001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InvokePrologue(expected, actual, Handle<Code>::null(), code, 20023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &done, &definitely_mismatches, flag, Label::kNear, 20033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch call_wrapper, call_kind); 20043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!definitely_mismatches) { 20053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (flag == CALL_FUNCTION) { 20063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch call_wrapper.BeforeCall(CallSize(code)); 20073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SetCallKind(ecx, call_kind); 20083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch call(code); 20093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch call_wrapper.AfterCall(); 20103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 20113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(flag == JUMP_FUNCTION); 20123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SetCallKind(ecx, call_kind); 20133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch jmp(code); 20143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 20153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&done); 2016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeCode(Handle<Code> code, 2021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& expected, 2022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 2023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::Mode rmode, 2024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InvokeFlag flag, 2025257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const CallWrapper& call_wrapper, 2026257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKind call_kind) { 20273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // You can't call a function without a valid frame. 20283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(flag == JUMP_FUNCTION || has_frame()); 20293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2030257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 20313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand dummy(eax, 0); 20323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool definitely_mismatches = false; 20333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch InvokePrologue(expected, actual, code, dummy, &done, &definitely_mismatches, 20343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch flag, Label::kNear, call_wrapper, call_kind); 20353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!definitely_mismatches) { 20363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (flag == CALL_FUNCTION) { 20373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch call_wrapper.BeforeCall(CallSize(code, rmode)); 20383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SetCallKind(ecx, call_kind); 20393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch call(code, rmode); 20403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch call_wrapper.AfterCall(); 20413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 20423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(flag == JUMP_FUNCTION); 20433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SetCallKind(ecx, call_kind); 20443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch jmp(code, rmode); 20453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 20463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&done); 2047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeFunction(Register fun, 2052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 2053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InvokeFlag flag, 2054257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const CallWrapper& call_wrapper, 2055257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKind call_kind) { 20563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // You can't call a function without a valid frame. 20573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(flag == JUMP_FUNCTION || has_frame()); 20583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(fun.is(edi)); 2060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 2061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 2062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(ebx, FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset)); 20637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch SmiUntag(ebx); 2064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ParameterCount expected(ebx); 2066791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), 2067257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch expected, actual, flag, call_wrapper, call_kind); 2068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 20713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::InvokeFunction(Handle<JSFunction> function, 2072402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu const ParameterCount& actual, 2073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InvokeFlag flag, 2074257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const CallWrapper& call_wrapper, 2075257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKind call_kind) { 20763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // You can't call a function without a valid frame. 20773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(flag == JUMP_FUNCTION || has_frame()); 20783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2079402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Get the function and setup the context. 20803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LoadHeapObject(edi, function); 2081402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 2082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2083402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ParameterCount expected(function->shared()->formal_parameter_count()); 20843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We call indirectly through the code field in the function to 20853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // allow recompilation to take effect without changing any of the 20863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // call sites. 20873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), 20883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch expected, actual, flag, call_wrapper, call_kind); 2089402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 2090402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 2091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, 2093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InvokeFlag flag, 2094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const CallWrapper& call_wrapper) { 20953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // You can't call a builtin without a valid frame. 20963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(flag == JUMP_FUNCTION || has_frame()); 2097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Rely on the assertion to check that the number of provided 2099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // arguments match the expected number of arguments. Fake a 2100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // parameter count to avoid emitting code to do the check. 2101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ParameterCount expected(0); 2102791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block GetBuiltinFunction(edi, id); 2103791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), 2104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch expected, expected, flag, call_wrapper, CALL_AS_METHOD); 2105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 21073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2108791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockvoid MacroAssembler::GetBuiltinFunction(Register target, 2109791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block Builtins::JavaScript id) { 2110791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block // Load the JavaScript builtin function from the builtins object. 21116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block mov(target, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); 21126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block mov(target, FieldOperand(target, GlobalObject::kBuiltinsOffset)); 2113791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block mov(target, FieldOperand(target, 2114791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block JSBuiltinsObject::OffsetOfFunctionWithId(id))); 2115791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block} 21166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 21173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2118791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockvoid MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) { 2119791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block ASSERT(!target.is(edi)); 2120402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Load the JavaScript builtin function from the builtins object. 2121791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block GetBuiltinFunction(edi, id); 2122791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block // Load the code entry point from the function into the target register. 2123791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block mov(target, FieldOperand(edi, JSFunction::kCodeEntryOffset)); 2124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2127d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::LoadContext(Register dst, int context_chain_length) { 2128d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (context_chain_length > 0) { 2129d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Move up the chain of contexts to the context containing the slot. 21303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch mov(dst, Operand(esi, Context::SlotOffset(Context::PREVIOUS_INDEX))); 2131d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 1; i < context_chain_length; i++) { 21323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch mov(dst, Operand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX))); 2133d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 21341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 21351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Slot is in the current function context. Move it into the 21361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // destination register in case we store into it (the write barrier 21371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // cannot be allowed to destroy the context in esi). 21381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block mov(dst, esi); 21391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 21401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 21413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // We should not have found a with context by walking the context chain 21421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // (i.e., the static scope chain and runtime context chain do not agree). 21431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // A variable occurring in such a scope should have slot type LOOKUP and 21441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // not CONTEXT. 214544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 21463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch cmp(FieldOperand(dst, HeapObject::kMapOffset), 21473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch isolate()->factory()->with_context_map()); 21483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Check(not_equal, "Variable resolved to with context."); 2149d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2150d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2151d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2152d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 21533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::LoadTransitionedArrayMapConditional( 21543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind expected_kind, 21553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind transitioned_kind, 21563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register map_in_out, 21573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 21583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* no_map_match) { 21593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load the global or builtins object from the current context. 21603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(scratch, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); 21613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(scratch, FieldOperand(scratch, GlobalObject::kGlobalContextOffset)); 21623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 21633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that the function's map is the same as the expected cached map. 21643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int expected_index = 21653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Context::GetContextMapIndexFromElementsKind(expected_kind); 21663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmp(map_in_out, Operand(scratch, Context::SlotOffset(expected_index))); 21673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(not_equal, no_map_match); 21683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 21693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Use the transitioned cached map. 21703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int trans_index = 21713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Context::GetContextMapIndexFromElementsKind(transitioned_kind); 21723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(map_in_out, Operand(scratch, Context::SlotOffset(trans_index))); 21733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 21743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 21753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 21763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::LoadInitialArrayMap( 21773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register function_in, Register scratch, Register map_out) { 21783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!function_in.is(map_out)); 21793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label done; 21803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(map_out, FieldOperand(function_in, 21813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JSFunction::kPrototypeOrInitialMapOffset)); 21823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!FLAG_smi_only_arrays) { 21833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS, 21843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FAST_ELEMENTS, 21853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch map_out, 21863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 21873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &done); 21883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 21893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&done); 21903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 21913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 21923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 219380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::LoadGlobalFunction(int index, Register function) { 219480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Load the global or builtins object from the current context. 219580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen mov(function, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); 219680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Load the global context from the global or builtins object. 219780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen mov(function, FieldOperand(function, GlobalObject::kGlobalContextOffset)); 219880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Load the function from the global context. 219980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen mov(function, Operand(function, Context::SlotOffset(index))); 220080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 220180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 220280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 220380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::LoadGlobalFunctionInitialMap(Register function, 220480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Register map) { 220580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Load the initial map. The global functions all have initial maps. 220680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen mov(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 220744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 220880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label ok, fail; 2209257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CheckMap(map, isolate()->factory()->meta_map(), &fail, DO_SMI_CHECK); 221080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen jmp(&ok); 221180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen bind(&fail); 221280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Abort("Global functions must have initial map"); 221380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen bind(&ok); 221480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 221580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 221680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 2217d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2218e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Store the value in register src in the safepoint register stack 2219e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// slot for register dst. 2220e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Register src) { 2221e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch mov(SafepointRegisterSlot(dst), src); 2222e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2223e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2224e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2225e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Immediate src) { 2226e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch mov(SafepointRegisterSlot(dst), src); 2227e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2228e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2229e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2230e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) { 2231e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch mov(dst, SafepointRegisterSlot(src)); 2232e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2233e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2234e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2235e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochOperand MacroAssembler::SafepointRegisterSlot(Register reg) { 2236e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return Operand(esp, SafepointRegisterStackIndex(reg.code()) * kPointerSize); 2237e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2238e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2239e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochint MacroAssembler::SafepointRegisterStackIndex(int reg_code) { 2241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The registers are pushed starting with the lowest encoding, 2242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // which means that lowest encodings are furthest away from 2243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // the stack pointer. 2244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(reg_code >= 0 && reg_code < kNumSafepointRegisters); 2245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return kNumSafepointRegisters - reg_code - 1; 2246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 22493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::LoadHeapObject(Register result, 22503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<HeapObject> object) { 22513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (isolate()->heap()->InNewSpace(*object)) { 22523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell = 22533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate()->factory()->NewJSGlobalPropertyCell(object); 22543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(result, Operand::Cell(cell)); 22553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 22563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(result, object); 22573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 22583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 22593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 22603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 22613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::PushHeapObject(Handle<HeapObject> object) { 22623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (isolate()->heap()->InNewSpace(*object)) { 22633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell = 22643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate()->factory()->NewJSGlobalPropertyCell(object); 22653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch push(Operand::Cell(cell)); 22663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 22673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Push(object); 22683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 22693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 22703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 22713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Ret() { 2273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ret(0); 2274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 22771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::Ret(int bytes_dropped, Register scratch) { 22781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (is_uint16(bytes_dropped)) { 22791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ret(bytes_dropped); 22801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 22811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block pop(scratch); 22823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(esp, Immediate(bytes_dropped)); 22831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block push(scratch); 22841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ret(0); 22851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 22861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 22871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 22881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2289e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::Drop(int stack_elements) { 2290e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (stack_elements > 0) { 22913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(esp, Immediate(stack_elements * kPointerSize)); 2292e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2293e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 2294e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2295e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 22960d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::Move(Register dst, Register src) { 22970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!dst.is(src)) { 22980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen mov(dst, src); 22990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 23000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 23010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 23020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 2303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SetCounter(StatsCounter* counter, int value) { 2304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_native_code_counters && counter->Enabled()) { 2305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(Operand::StaticVariable(ExternalReference(counter)), Immediate(value)); 2306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::IncrementCounter(StatsCounter* counter, int value) { 2311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(value > 0); 2312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_native_code_counters && counter->Enabled()) { 2313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand operand = Operand::StaticVariable(ExternalReference(counter)); 2314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (value == 1) { 2315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inc(operand); 2316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 2317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block add(operand, Immediate(value)); 2318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::DecrementCounter(StatsCounter* counter, int value) { 2324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(value > 0); 2325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_native_code_counters && counter->Enabled()) { 2326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand operand = Operand::StaticVariable(ExternalReference(counter)); 2327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (value == 1) { 2328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block dec(operand); 2329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 2330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block sub(operand, Immediate(value)); 2331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2336d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid MacroAssembler::IncrementCounter(Condition cc, 2337d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke StatsCounter* counter, 2338d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke int value) { 2339d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ASSERT(value > 0); 2340d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (FLAG_native_code_counters && counter->Enabled()) { 2341d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label skip; 2342d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke j(NegateCondition(cc), &skip); 2343d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke pushfd(); 2344d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke IncrementCounter(counter, value); 2345d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke popfd(); 2346d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke bind(&skip); 2347d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 2348d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 2349d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 2350d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 2351d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid MacroAssembler::DecrementCounter(Condition cc, 2352d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke StatsCounter* counter, 2353d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke int value) { 2354d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ASSERT(value > 0); 2355d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (FLAG_native_code_counters && counter->Enabled()) { 2356d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label skip; 2357d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke j(NegateCondition(cc), &skip); 2358d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke pushfd(); 2359d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke DecrementCounter(counter, value); 2360d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke popfd(); 2361d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke bind(&skip); 2362d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 2363d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 2364d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 2365d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 2366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Assert(Condition cc, const char* msg) { 236744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) Check(cc, msg); 2368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2371756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid MacroAssembler::AssertFastElements(Register elements) { 237244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 237344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Factory* factory = isolate()->factory(); 2374756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Label ok; 2375756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick cmp(FieldOperand(elements, HeapObject::kMapOffset), 237644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Immediate(factory->fixed_array_map())); 2377756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick j(equal, &ok); 2378756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick cmp(FieldOperand(elements, HeapObject::kMapOffset), 23793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Immediate(factory->fixed_double_array_map())); 23803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch j(equal, &ok); 23813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch cmp(FieldOperand(elements, HeapObject::kMapOffset), 238244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Immediate(factory->fixed_cow_array_map())); 2383756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick j(equal, &ok); 2384756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Abort("JSObject with fast elements map has slow elements"); 2385756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick bind(&ok); 2386756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 2387756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick} 2388756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 2389756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 2390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Check(Condition cc, const char* msg) { 2391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label L; 2392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch j(cc, &L); 2393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Abort(msg); 2394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // will not return here 2395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&L); 2396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 23996ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::CheckStackAlignment() { 24006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int frame_alignment = OS::ActivationFrameAlignment(); 24016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int frame_alignment_mask = frame_alignment - 1; 24026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (frame_alignment > kPointerSize) { 24036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(IsPowerOf2(frame_alignment)); 24046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label alignment_as_expected; 24056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block test(esp, Immediate(frame_alignment_mask)); 24066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block j(zero, &alignment_as_expected); 24076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Abort if stack is not aligned. 24086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int3(); 24096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block bind(&alignment_as_expected); 24106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 24116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 24126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 24136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Abort(const char* msg) { 2415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We want to pass the msg string like a smi to avoid GC 2416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // problems, however msg is not guaranteed to be aligned 2417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // properly. Instead, we pass an aligned pointer that is 2418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // a proper v8 smi, but also pass the alignment difference 2419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // from the real pointer as a smi. 2420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block intptr_t p1 = reinterpret_cast<intptr_t>(msg); 2421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block intptr_t p0 = (p1 & ~kSmiTagMask) + kSmiTag; 2422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(reinterpret_cast<Object*>(p0)->IsSmi()); 2423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 2424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (msg != NULL) { 2425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RecordComment("Abort message: "); 2426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RecordComment(msg); 2427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 2429d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(eax); 2431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Immediate(p0)); 2432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block push(Immediate(reinterpret_cast<intptr_t>(Smi::FromInt(p1 - p0)))); 24333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Disable stub call restrictions to always allow calls to abort. 24343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!has_frame_) { 24353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We don't actually want to generate a pile of code for this, so just 24363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // claim there is a stack frame, without generating one. 24373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(this, StackFrame::NONE); 24383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallRuntime(Runtime::kAbort, 2); 24393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 24403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallRuntime(Runtime::kAbort, 2); 24413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // will not return here 2443d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int3(); 2444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::LoadInstanceDescriptors(Register map, 2448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register descriptors) { 2449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch mov(descriptors, 2450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FieldOperand(map, Map::kInstanceDescriptorsOrBitField3Offset)); 2451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label not_smi; 2452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch JumpIfNotSmi(descriptors, ¬_smi); 2453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch mov(descriptors, isolate()->factory()->empty_descriptor_array()); 2454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bind(¬_smi); 2455756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick} 2456756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 2457756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 24580d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::LoadPowerOf2(XMMRegister dst, 24590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register scratch, 24600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int power) { 24610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(is_uintn(power + HeapNumber::kExponentBias, 24620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen HeapNumber::kExponentBits)); 24630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen mov(scratch, Immediate(power + HeapNumber::kExponentBias)); 24643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movd(dst, scratch); 24650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen psllq(dst, HeapNumber::kMantissaBits); 24660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 24670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 24680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 2469402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii( 2470402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register instance_type, 2471402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register scratch, 24726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label* failure) { 2473402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (!scratch.is(instance_type)) { 2474402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu mov(scratch, instance_type); 2475402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 2476402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu and_(scratch, 2477402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask); 2478402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu cmp(scratch, kStringTag | kSeqStringTag | kAsciiStringTag); 2479402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu j(not_equal, failure); 2480402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 2481402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 2482402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 2483d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register object1, 2484d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Register object2, 2485d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Register scratch1, 2486d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Register scratch2, 2487d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label* failure) { 2488d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Check that both objects are not smis. 248969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 24903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(scratch1, object1); 24913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(scratch1, object2); 24923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch JumpIfSmi(scratch1, failure); 2493d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 2494d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Load instance type for both strings. 2495d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke mov(scratch1, FieldOperand(object1, HeapObject::kMapOffset)); 2496d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke mov(scratch2, FieldOperand(object2, HeapObject::kMapOffset)); 2497d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke movzx_b(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset)); 2498d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke movzx_b(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset)); 2499d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 25003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that both are flat ASCII strings. 2501d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke const int kFlatAsciiStringMask = 2502d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; 2503d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke const int kFlatAsciiStringTag = ASCII_STRING_TYPE; 2504d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Interleave bits from both instance types and compare them in one check. 2505d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ASSERT_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3)); 2506d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke and_(scratch1, kFlatAsciiStringMask); 2507d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke and_(scratch2, kFlatAsciiStringMask); 2508d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke lea(scratch1, Operand(scratch1, scratch2, times_8, 0)); 2509d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke cmp(scratch1, kFlatAsciiStringTag | (kFlatAsciiStringTag << 3)); 2510d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke j(not_equal, failure); 2511d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 2512d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 2513d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 25146ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::PrepareCallCFunction(int num_arguments, Register scratch) { 25158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int frame_alignment = OS::ActivationFrameAlignment(); 25168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (frame_alignment != 0) { 25176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Make stack end at alignment and make room for num_arguments words 25186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // and the original value of esp. 25196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block mov(scratch, esp); 25203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch sub(esp, Immediate((num_arguments + 1) * kPointerSize)); 25218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(IsPowerOf2(frame_alignment)); 25228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch and_(esp, -frame_alignment); 25236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block mov(Operand(esp, num_arguments * kPointerSize), scratch); 25246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 25253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch sub(esp, Immediate(num_arguments * kPointerSize)); 25266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 25276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 25286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 25296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 25306ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::CallCFunction(ExternalReference function, 25316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int num_arguments) { 25326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Trashing eax is ok as it will be the return value. 25333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(eax, Immediate(function)); 25346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block CallCFunction(eax, num_arguments); 25356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 25366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 25376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 25386ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::CallCFunction(Register function, 25396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int num_arguments) { 25403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(has_frame()); 25416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check stack alignment. 254244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (emit_debug_code()) { 25436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block CheckStackAlignment(); 25446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 25456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 25463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch call(function); 25476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (OS::ActivationFrameAlignment() != 0) { 25486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block mov(esp, Operand(esp, num_arguments * kPointerSize)); 25496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 25503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(esp, Immediate(num_arguments * kPointerSize)); 25516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 25526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 25536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 25546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 25553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool AreAliased(Register r1, Register r2, Register r3, Register r4) { 25563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (r1.is(r2)) return true; 25573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (r1.is(r3)) return true; 25583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (r1.is(r4)) return true; 25593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (r2.is(r3)) return true; 25603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (r2.is(r4)) return true; 25613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (r3.is(r4)) return true; 25623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return false; 25633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 25643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 25653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCodePatcher::CodePatcher(byte* address, int size) 25678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch : address_(address), 25688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch size_(size), 25698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch masm_(Isolate::Current(), address, size + Assembler::kGap) { 2570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Create a new macro assembler pointing to the address of the code to patch. 2571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The size is adjusted with kGap on order for the assembler to generate size 2572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // bytes of instructions without failing with buffer size constraints. 2573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); 2574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCodePatcher::~CodePatcher() { 2578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Indicate that code has changed. 2579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CPU::FlushICache(address_, size_); 2580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the code was patched as expected. 2582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(masm_.pc_ == address_ + size_); 2583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); 2584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckPageFlag( 25883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object, 25893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 25903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int mask, 25913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition cc, 25923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* condition_met, 25933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance condition_met_distance) { 25943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(cc == zero || cc == not_zero); 25953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (scratch.is(object)) { 25963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(scratch, Immediate(~Page::kPageAlignmentMask)); 25973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 25983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(scratch, Immediate(~Page::kPageAlignmentMask)); 25993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(scratch, object); 26003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 26013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (mask < (1 << kBitsPerByte)) { 26023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test_b(Operand(scratch, MemoryChunk::kFlagsOffset), 26033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static_cast<uint8_t>(mask)); 26043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 26053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test(Operand(scratch, MemoryChunk::kFlagsOffset), Immediate(mask)); 26063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 26073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(cc, condition_met, condition_met_distance); 26083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 26093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 26103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 26113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::JumpIfBlack(Register object, 26123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch0, 26133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1, 26143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* on_black, 26153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance on_black_near) { 26163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HasColor(object, scratch0, scratch1, 26173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch on_black, on_black_near, 26183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1, 0); // kBlackBitPattern. 26193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0); 26203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 26213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 26223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 26233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::HasColor(Register object, 26243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register bitmap_scratch, 26253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register mask_scratch, 26263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* has_color, 26273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance has_color_distance, 26283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int first_bit, 26293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int second_bit) { 26303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!AreAliased(object, bitmap_scratch, mask_scratch, ecx)); 26313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 26323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GetMarkBits(object, bitmap_scratch, mask_scratch); 26333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 26343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label other_color, word_boundary; 26353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize)); 26363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(first_bit == 1 ? zero : not_zero, &other_color, Label::kNear); 26373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(mask_scratch, mask_scratch); // Shift left 1 by adding. 26383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(zero, &word_boundary, Label::kNear); 26393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize)); 26403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(second_bit == 1 ? not_zero : zero, has_color, has_color_distance); 26413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch jmp(&other_color, Label::kNear); 26423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 26433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&word_boundary); 26443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test_b(Operand(bitmap_scratch, MemoryChunk::kHeaderSize + kPointerSize), 1); 26453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 26463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(second_bit == 1 ? not_zero : zero, has_color, has_color_distance); 26473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&other_color); 26483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 26493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 26503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 26513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::GetMarkBits(Register addr_reg, 26523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register bitmap_reg, 26533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register mask_reg) { 26543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!AreAliased(addr_reg, mask_reg, bitmap_reg, ecx)); 26553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(bitmap_reg, Immediate(~Page::kPageAlignmentMask)); 26563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(bitmap_reg, addr_reg); 26573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(ecx, addr_reg); 26583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int shift = 26593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Bitmap::kBitsPerCellLog2 + kPointerSizeLog2 - Bitmap::kBytesPerCellLog2; 26603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch shr(ecx, shift); 26613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(ecx, 26623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (Page::kPageAlignmentMask >> shift) & ~(Bitmap::kBytesPerCell - 1)); 26633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 26643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(bitmap_reg, ecx); 26653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(ecx, addr_reg); 26663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch shr(ecx, kPointerSizeLog2); 26673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(ecx, (1 << Bitmap::kBitsPerCellLog2) - 1); 26683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(mask_reg, Immediate(1)); 26693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch shl_cl(mask_reg); 26703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 26713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 26723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 26733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::EnsureNotWhite( 26743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register value, 26753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register bitmap_scratch, 26763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register mask_scratch, 26773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* value_is_white_and_not_data, 26783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::Distance distance) { 26793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!AreAliased(value, bitmap_scratch, mask_scratch, ecx)); 26803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GetMarkBits(value, bitmap_scratch, mask_scratch); 26813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 26823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If the value is black or grey we don't need to do anything. 26833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(strcmp(Marking::kWhiteBitPattern, "00") == 0); 26843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0); 26853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(strcmp(Marking::kGreyBitPattern, "11") == 0); 26863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(strcmp(Marking::kImpossibleBitPattern, "01") == 0); 26873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 26883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label done; 26893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 26903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Since both black and grey have a 1 in the first position and white does 26913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // not have a 1 there we only need to check one bit. 26923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize)); 26933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(not_zero, &done, Label::kNear); 26943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 26953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_debug_code) { 26963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for impossible bit pattern. 26973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label ok; 26983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch push(mask_scratch); 26993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // shl. May overflow making the check conservative. 27003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(mask_scratch, mask_scratch); 27013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize)); 27023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(zero, &ok, Label::kNear); 27033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int3(); 27043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&ok); 27053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch pop(mask_scratch); 27063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 27073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Value is white. We check whether it is data that doesn't need scanning. 27093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Currently only checks for HeapNumber and non-cons strings. 27103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register map = ecx; // Holds map while checking type. 27113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register length = ecx; // Holds length of object after checking type. 27123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label not_heap_number; 27133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label is_data_object; 27143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for heap-number 27163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(map, FieldOperand(value, HeapObject::kMapOffset)); 27173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmp(map, FACTORY->heap_number_map()); 27183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(not_equal, ¬_heap_number, Label::kNear); 27193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(length, Immediate(HeapNumber::kSize)); 27203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch jmp(&is_data_object, Label::kNear); 27213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(¬_heap_number); 27233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for strings. 27243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1); 27253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(kNotStringTag == 0x80 && kIsNotStringMask == 0x80); 27263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If it's a string and it's not a cons string then it's an object containing 27273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // no GC pointers. 27283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register instance_type = ecx; 27293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset)); 27303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test_b(instance_type, kIsIndirectStringMask | kIsNotStringMask); 27313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(not_zero, value_is_white_and_not_data); 27323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // It's a non-indirect (non-cons and non-slice) string. 27333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If it's external, the length is just ExternalString::kSize. 27343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Otherwise it's String::kHeaderSize + string->length() * (1 or 2). 27353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label not_external; 27363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // External strings are the only ones with the kExternalStringTag bit 27373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // set. 27383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_EQ(0, kSeqStringTag & kExternalStringTag); 27393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_EQ(0, kConsStringTag & kExternalStringTag); 27403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test_b(instance_type, kExternalStringTag); 27413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(zero, ¬_external, Label::kNear); 27423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(length, Immediate(ExternalString::kSize)); 27433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch jmp(&is_data_object, Label::kNear); 27443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(¬_external); 27463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Sequential string, either ASCII or UC16. 27473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(kAsciiStringTag == 0x04); 27483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(length, Immediate(kStringEncodingMask)); 27493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch xor_(length, Immediate(kStringEncodingMask)); 27503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(length, Immediate(0x04)); 27513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Value now either 4 (if ASCII) or 8 (if UC16), i.e., char-size shifted 27523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // by 2. If we multiply the string length as smi by this, it still 27533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // won't overflow a 32-bit value. 27543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_EQ(SeqAsciiString::kMaxSize, SeqTwoByteString::kMaxSize); 27553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(SeqAsciiString::kMaxSize <= 27563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static_cast<int>(0xffffffffu >> (2 + kSmiTagSize))); 27573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch imul(length, FieldOperand(value, String::kLengthOffset)); 27583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch shr(length, 2 + kSmiTagSize + kSmiShiftSize); 27593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(length, Immediate(SeqString::kHeaderSize + kObjectAlignmentMask)); 27603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(length, Immediate(~kObjectAlignmentMask)); 27613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&is_data_object); 27633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Value is a data object, and it is white. Mark it black. Since we know 27643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // that the object is white we can make it black by flipping one bit. 27653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch or_(Operand(bitmap_scratch, MemoryChunk::kHeaderSize), mask_scratch); 27663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch and_(bitmap_scratch, Immediate(~Page::kPageAlignmentMask)); 27683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch add(Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset), 27693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch length); 27703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_debug_code) { 27713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(length, Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset)); 27723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmp(length, Operand(bitmap_scratch, MemoryChunk::kSizeOffset)); 27733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Check(less_equal, "Live Bytes Count overflow chunk size"); 27743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 27753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&done); 27773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 27783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckEnumCache(Label* call_runtime) { 27813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label next; 27823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(ecx, eax); 27833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&next); 27843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that there are no elements. Register ecx contains the 27863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // current JS object we've reached through the prototype chain. 27873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmp(FieldOperand(ecx, JSObject::kElementsOffset), 27883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate()->factory()->empty_fixed_array()); 27893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(not_equal, call_runtime); 27903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that instance descriptors are not empty so that we can 27923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // check for an enum cache. Leave the map in ebx for the subsequent 27933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // prototype load. 27943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset)); 27953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(edx, FieldOperand(ebx, Map::kInstanceDescriptorsOrBitField3Offset)); 27963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JumpIfSmi(edx, call_runtime); 27973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that there is an enum cache in the non-empty instance 27993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // descriptors (edx). This is the case if the next enumeration 28003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // index field does not contain a smi. 28013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(edx, FieldOperand(edx, DescriptorArray::kEnumerationIndexOffset)); 28023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JumpIfSmi(edx, call_runtime); 28033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 28043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // For all objects but the receiver, check that the cache is empty. 28053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label check_prototype; 28063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmp(ecx, eax); 28073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(equal, &check_prototype, Label::kNear); 28083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(edx, FieldOperand(edx, DescriptorArray::kEnumCacheBridgeCacheOffset)); 28093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmp(edx, isolate()->factory()->empty_fixed_array()); 28103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(not_equal, call_runtime); 28113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 28123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load the prototype from the map and loop if non-null. 28133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bind(&check_prototype); 28143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset)); 28153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmp(ecx, isolate()->factory()->null_value()); 28163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch j(not_equal, &next); 28173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 28183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 2820f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2821f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_IA32 2822