1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2011 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifndef V8_X87_CODE_STUBS_X87_H_ 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define V8_X87_CODE_STUBS_X87_H_ 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 { 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal { 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ArrayNativeCode(MacroAssembler* masm, 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool construct_call, 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* call_generic_code); 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass StringHelper : public AllStatic { 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Generate code for copying characters using the rep movs instruction. 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Copies ecx characters from esi to edi. Copying of overlapping regions is 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // not supported. 22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static void GenerateCopyCharacters(MacroAssembler* masm, 23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register dest, 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register src, 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register count, 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch, 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch String::Encoding encoding); 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compares two flat one byte strings and returns result in eax. 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static void GenerateCompareFlatOneByteStrings(MacroAssembler* masm, 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register left, Register right, 32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1, 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2, 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch3); 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compares two flat one byte strings for equality and returns result in eax. 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static void GenerateFlatOneByteStringEquals(MacroAssembler* masm, 38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register left, Register right, 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1, 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2); 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static void GenerateOneByteCharsCompareLoop( 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, Register left, Register right, Register length, 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch, Label* chars_not_equal, 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label::Distance chars_not_equal_near = Label::kFar); 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper); 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass NameDictionaryLookupStub: public PlatformCodeStub { 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch enum LookupMode { POSITIVE_LOOKUP, NEGATIVE_LOOKUP }; 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionaryLookupStub(Isolate* isolate, Register dictionary, 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result, Register index, LookupMode mode) 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : PlatformCodeStub(isolate) { 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch minor_key_ = DictionaryBits::encode(dictionary.code()) | 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ResultBits::encode(result.code()) | 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IndexBits::encode(index.code()) | LookupModeBits::encode(mode); 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static void GenerateNegativeLookup(MacroAssembler* masm, 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* miss, 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* done, 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register properties, 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Name> name, 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register r0); 70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static void GeneratePositiveLookup(MacroAssembler* masm, 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* miss, 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* done, 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register elements, 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register name, 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register r0, 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register r1); 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual bool SometimesSetsUpAFrame() { return false; } 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kInlinedProbes = 4; 83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kTotalProbes = 20; 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kCapacityOffset = 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionary::kHeaderSize + 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionary::kCapacityIndex * kPointerSize; 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kElementsStartOffset = 90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionary::kHeaderSize + 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionary::kElementsStartIndex * kPointerSize; 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register dictionary() const { 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return Register::from_code(DictionaryBits::decode(minor_key_)); 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result() const { 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return Register::from_code(ResultBits::decode(minor_key_)); 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register index() const { 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return Register::from_code(IndexBits::decode(minor_key_)); 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LookupMode mode() const { return LookupModeBits::decode(minor_key_); } 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch class DictionaryBits: public BitField<int, 0, 3> {}; 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch class ResultBits: public BitField<int, 3, 3> {}; 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch class IndexBits: public BitField<int, 6, 3> {}; 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch class LookupModeBits: public BitField<LookupMode, 9, 1> {}; 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR(); 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DEFINE_PLATFORM_CODE_STUB(NameDictionaryLookup, PlatformCodeStub); 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass RecordWriteStub: public PlatformCodeStub { 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordWriteStub(Isolate* isolate, Register object, Register value, 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register address, RememberedSetAction remembered_set_action, 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SaveFPRegsMode fp_mode) 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : PlatformCodeStub(isolate), 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch regs_(object, // An input reg. 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch address, // An input reg. 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch value) { // One scratch reg. 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch minor_key_ = ObjectBits::encode(object.code()) | 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ValueBits::encode(value.code()) | 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AddressBits::encode(address.code()) | 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RememberedSetActionBits::encode(remembered_set_action) | 130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SaveFPRegsModeBits::encode(fp_mode); 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordWriteStub(uint32_t key, Isolate* isolate) 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : PlatformCodeStub(key, isolate), regs_(object(), address(), value()) {} 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch enum Mode { 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STORE_BUFFER_ONLY, 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch INCREMENTAL, 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch INCREMENTAL_COMPACTION 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual bool SometimesSetsUpAFrame() { return false; } 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const byte kTwoByteNopInstruction = 0x3c; // Cmpb al, #imm8. 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const byte kTwoByteJumpInstruction = 0xeb; // Jmp #imm8. 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const byte kFiveByteNopInstruction = 0x3d; // Cmpl eax, #imm32. 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const byte kFiveByteJumpInstruction = 0xe9; // Jmp #imm32. 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static Mode GetMode(Code* stub) { 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch byte first_instruction = stub->instruction_start()[0]; 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch byte second_instruction = stub->instruction_start()[2]; 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (first_instruction == kTwoByteJumpInstruction) { 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return INCREMENTAL; 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(first_instruction == kTwoByteNopInstruction); 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (second_instruction == kFiveByteJumpInstruction) { 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return INCREMENTAL_COMPACTION; 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(second_instruction == kFiveByteNopInstruction); 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return STORE_BUFFER_ONLY; 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static void Patch(Code* stub, Mode mode) { 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (mode) { 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case STORE_BUFFER_ONLY: 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(GetMode(stub) == INCREMENTAL || 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GetMode(stub) == INCREMENTAL_COMPACTION); 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stub->instruction_start()[0] = kTwoByteNopInstruction; 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stub->instruction_start()[2] = kFiveByteNopInstruction; 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case INCREMENTAL: 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(GetMode(stub) == STORE_BUFFER_ONLY); 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stub->instruction_start()[0] = kTwoByteJumpInstruction; 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case INCREMENTAL_COMPACTION: 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(GetMode(stub) == STORE_BUFFER_ONLY); 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stub->instruction_start()[0] = kTwoByteNopInstruction; 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stub->instruction_start()[2] = kFiveByteJumpInstruction; 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(GetMode(stub) == mode); 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CpuFeatures::FlushICache(stub->instruction_start(), 7); 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR(); 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This is a helper class for freeing up 3 scratch registers, where the third 195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is always ecx (needed for shift operations). The input is two registers 196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // that must be preserved and one scratch register provided by the caller. 197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch class RegisterAllocation { 198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RegisterAllocation(Register object, 200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register address, 201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch0) 202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : object_orig_(object), 203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch address_orig_(address), 204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch scratch0_orig_(scratch0), 205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch object_(object), 206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch address_(address), 207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch scratch0_(scratch0) { 208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!AreAliased(scratch0, object, address, no_reg)); 209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch scratch1_ = GetRegThatIsNotEcxOr(object_, address_, scratch0_); 210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (scratch0.is(ecx)) { 211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch scratch0_ = GetRegThatIsNotEcxOr(object_, address_, scratch1_); 212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (object.is(ecx)) { 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch object_ = GetRegThatIsNotEcxOr(address_, scratch0_, scratch1_); 215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (address.is(ecx)) { 217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch address_ = GetRegThatIsNotEcxOr(object_, scratch0_, scratch1_); 218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!AreAliased(scratch0_, object_, address_, ecx)); 220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Save(MacroAssembler* masm) { 223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!address_orig_.is(object_)); 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(object_.is(object_orig_) || address_.is(address_orig_)); 225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!AreAliased(object_, address_, scratch1_, scratch0_)); 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!AreAliased(object_orig_, address_, scratch1_, scratch0_)); 227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!AreAliased(object_, address_orig_, scratch1_, scratch0_)); 228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We don't have to save scratch0_orig_ because it was given to us as 229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // a scratch register. But if we had to switch to a different reg then 230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // we should save the new scratch0_. 231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!scratch0_.is(scratch0_orig_)) masm->push(scratch0_); 232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!ecx.is(scratch0_orig_) && 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !ecx.is(object_orig_) && 234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !ecx.is(address_orig_)) { 235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->push(ecx); 236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->push(scratch1_); 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!address_.is(address_orig_)) { 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->push(address_); 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->mov(address_, address_orig_); 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!object_.is(object_orig_)) { 243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->push(object_); 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->mov(object_, object_orig_); 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Restore(MacroAssembler* masm) { 249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // These will have been preserved the entire time, so we just need to move 250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // them back. Only in one case is the orig_ reg different from the plain 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // one, since only one of them can alias with ecx. 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!object_.is(object_orig_)) { 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->mov(object_orig_, object_); 254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->pop(object_); 255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!address_.is(address_orig_)) { 257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->mov(address_orig_, address_); 258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->pop(address_); 259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->pop(scratch1_); 261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!ecx.is(scratch0_orig_) && 262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !ecx.is(object_orig_) && 263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !ecx.is(address_orig_)) { 264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->pop(ecx); 265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!scratch0_.is(scratch0_orig_)) masm->pop(scratch0_); 267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If we have to call into C then we need to save and restore all caller- 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // saved registers that were not already preserved. The caller saved 271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // registers are eax, ecx and edx. The three scratch registers (incl. ecx) 272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // will be restored by other means so we don't bother pushing them here. 273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void SaveCallerSaveRegisters(MacroAssembler* masm, SaveFPRegsMode mode) { 274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!scratch0_.is(eax) && !scratch1_.is(eax)) masm->push(eax); 275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!scratch0_.is(edx) && !scratch1_.is(edx)) masm->push(edx); 276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (mode == kSaveFPRegs) { 277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save FPU state in m108byte. 278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->sub(esp, Immediate(108)); 279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->fnsave(Operand(esp, 0)); 280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline void RestoreCallerSaveRegisters(MacroAssembler* masm, 284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SaveFPRegsMode mode) { 285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (mode == kSaveFPRegs) { 286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore FPU state in m108byte. 287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->frstor(Operand(esp, 0)); 288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->add(esp, Immediate(108)); 289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!scratch0_.is(edx) && !scratch1_.is(edx)) masm->pop(edx); 291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!scratch0_.is(eax) && !scratch1_.is(eax)) masm->pop(eax); 292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline Register object() { return object_; } 295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline Register address() { return address_; } 296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline Register scratch0() { return scratch0_; } 297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline Register scratch1() { return scratch1_; } 298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object_orig_; 301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register address_orig_; 302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch0_orig_; 303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object_; 304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register address_; 305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch0_; 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1_; 307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Third scratch register is always ecx. 308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register GetRegThatIsNotEcxOr(Register r1, 310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register r2, 311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register r3) { 312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < Register::NumAllocatableRegisters(); i++) { 313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register candidate = Register::FromAllocationIndex(i); 314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (candidate.is(ecx)) continue; 315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (candidate.is(r1)) continue; 316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (candidate.is(r2)) continue; 317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (candidate.is(r3)) continue; 318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return candidate; 319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return no_reg; 322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch friend class RecordWriteStub; 324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch enum OnNoNeedToInformIncrementalMarker { 327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kReturnOnNoNeedToInformIncrementalMarker, 328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kUpdateRememberedSetOnNoNeedToInformIncrementalMarker 329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual inline Major MajorKey() const FINAL OVERRIDE { return RecordWrite; } 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual void Generate(MacroAssembler* masm) OVERRIDE; 334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void GenerateIncremental(MacroAssembler* masm, Mode mode); 335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void CheckNeedsToInformIncrementalMarker( 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, 337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OnNoNeedToInformIncrementalMarker on_no_need, 338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Mode mode); 339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void InformIncrementalMarker(MacroAssembler* masm); 340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Activate(Code* code) { 342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch code->GetHeap()->incremental_marking()->ActivateGeneratedStub(code); 343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object() const { 346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return Register::from_code(ObjectBits::decode(minor_key_)); 347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value() const { 350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return Register::from_code(ValueBits::decode(minor_key_)); 351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register address() const { 354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return Register::from_code(AddressBits::decode(minor_key_)); 355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RememberedSetAction remembered_set_action() const { 358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return RememberedSetActionBits::decode(minor_key_); 359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SaveFPRegsMode save_fp_regs_mode() const { 362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return SaveFPRegsModeBits::decode(minor_key_); 363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch class ObjectBits: public BitField<int, 0, 3> {}; 366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch class ValueBits: public BitField<int, 3, 3> {}; 367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch class AddressBits: public BitField<int, 6, 3> {}; 368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch class RememberedSetActionBits: public BitField<RememberedSetAction, 9, 1> {}; 369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch class SaveFPRegsModeBits : public BitField<SaveFPRegsMode, 10, 1> {}; 370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RegisterAllocation regs_; 372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DISALLOW_COPY_AND_ASSIGN(RecordWriteStub); 374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} } // namespace v8::internal 378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // V8_X87_CODE_STUBS_X87_H_ 380