13ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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. 480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#ifndef V8_IA32_CODE_STUBS_IA32_H_ 680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#define V8_IA32_CODE_STUBS_IA32_H_ 780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsennamespace v8 { 980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsennamespace internal { 1080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ArrayNativeCode(MacroAssembler* masm, 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool construct_call, 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* call_generic_code); 1580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenclass StringHelper : public AllStatic { 1880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen public: 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compares two flat one byte strings and returns result in eax. 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static void GenerateCompareFlatOneByteStrings(MacroAssembler* masm, 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register left, Register right, 22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1, 23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2, 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch3); 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compares two flat one byte strings for equality and returns result in eax. 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static void GenerateFlatOneByteStringEquals(MacroAssembler* masm, 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register left, Register right, 2980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Register scratch1, 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2); 3180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 32257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private: 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static void GenerateOneByteCharsCompareLoop( 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, Register left, Register right, Register length, 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch, Label* chars_not_equal, 36257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance chars_not_equal_near = Label::kFar); 3780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper); 3980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}; 4080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 41257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass NameDictionaryLookupStub: public PlatformCodeStub { 43257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch public: 44257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch enum LookupMode { POSITIVE_LOOKUP, NEGATIVE_LOOKUP }; 45257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionaryLookupStub(Isolate* isolate, Register dictionary, 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result, Register index, LookupMode mode) 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : PlatformCodeStub(isolate) { 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch minor_key_ = DictionaryBits::encode(dictionary.code()) | 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ResultBits::encode(result.code()) | 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IndexBits::encode(index.code()) | LookupModeBits::encode(mode); 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 53257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static void GenerateNegativeLookup(MacroAssembler* masm, 553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss, 563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* done, 573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register properties, 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Name> name, 593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register r0); 60257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 61014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool SometimesSetsUpAFrame() override { return false; } 623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 63257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private: 64257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static const int kInlinedProbes = 4; 65257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static const int kTotalProbes = 20; 66257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 67257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static const int kCapacityOffset = 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionary::kHeaderSize + 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionary::kCapacityIndex * kPointerSize; 70257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 71257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static const int kElementsStartOffset = 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionary::kHeaderSize + 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionary::kElementsStartIndex * kPointerSize; 74257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register dictionary() const { 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return Register::from_code(DictionaryBits::decode(minor_key_)); 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 78257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result() const { 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return Register::from_code(ResultBits::decode(minor_key_)); 81257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 82257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register index() const { 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return Register::from_code(IndexBits::decode(minor_key_)); 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LookupMode mode() const { return LookupModeBits::decode(minor_key_); } 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 89257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch class DictionaryBits: public BitField<int, 0, 3> {}; 90257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch class ResultBits: public BitField<int, 3, 3> {}; 91257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch class IndexBits: public BitField<int, 6, 3> {}; 92257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch class LookupModeBits: public BitField<LookupMode, 9, 1> {}; 93257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR(); 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DEFINE_PLATFORM_CODE_STUB(NameDictionaryLookup, PlatformCodeStub); 96257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}; 97257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 98257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass RecordWriteStub: public PlatformCodeStub { 1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public: 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordWriteStub(Isolate* isolate, 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object, 1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register value, 1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register address, 1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RememberedSetAction remembered_set_action, 1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SaveFPRegsMode fp_mode) 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : PlatformCodeStub(isolate), 1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch regs_(object, // An input reg. 1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch address, // An input reg. 1103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value) { // One scratch reg. 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch minor_key_ = ObjectBits::encode(object.code()) | 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ValueBits::encode(value.code()) | 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AddressBits::encode(address.code()) | 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RememberedSetActionBits::encode(remembered_set_action) | 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SaveFPRegsModeBits::encode(fp_mode); 1163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordWriteStub(uint32_t key, Isolate* isolate) 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : PlatformCodeStub(key, isolate), regs_(object(), address(), value()) {} 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch enum Mode { 1223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STORE_BUFFER_ONLY, 1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch INCREMENTAL, 1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch INCREMENTAL_COMPACTION 1253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch }; 1263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool SometimesSetsUpAFrame() override { return false; } 1283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const byte kTwoByteNopInstruction = 0x3c; // Cmpb al, #imm8. 1303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const byte kTwoByteJumpInstruction = 0xeb; // Jmp #imm8. 1313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const byte kFiveByteNopInstruction = 0x3d; // Cmpl eax, #imm32. 1333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const byte kFiveByteJumpInstruction = 0xe9; // Jmp #imm32. 1343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static Mode GetMode(Code* stub) { 1363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch byte first_instruction = stub->instruction_start()[0]; 1373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch byte second_instruction = stub->instruction_start()[2]; 1383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (first_instruction == kTwoByteJumpInstruction) { 1403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return INCREMENTAL; 1413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(first_instruction == kTwoByteNopInstruction); 1443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (second_instruction == kFiveByteJumpInstruction) { 1463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return INCREMENTAL_COMPACTION; 1473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(second_instruction == kFiveByteNopInstruction); 1503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return STORE_BUFFER_ONLY; 1523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static void Patch(Code* stub, Mode mode) { 1553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch switch (mode) { 1563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case STORE_BUFFER_ONLY: 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(GetMode(stub) == INCREMENTAL || 1583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GetMode(stub) == INCREMENTAL_COMPACTION); 1593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch stub->instruction_start()[0] = kTwoByteNopInstruction; 1603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch stub->instruction_start()[2] = kFiveByteNopInstruction; 1613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 1623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case INCREMENTAL: 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(GetMode(stub) == STORE_BUFFER_ONLY); 1643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch stub->instruction_start()[0] = kTwoByteJumpInstruction; 1653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 1663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case INCREMENTAL_COMPACTION: 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(GetMode(stub) == STORE_BUFFER_ONLY); 1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch stub->instruction_start()[0] = kTwoByteNopInstruction; 1693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch stub->instruction_start()[2] = kFiveByteJumpInstruction; 1703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 1713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(GetMode(stub) == mode); 173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Assembler::FlushICache(stub->GetIsolate(), stub->instruction_start(), 7); 1743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR(); 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private: 1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // This is a helper class for freeing up 3 scratch registers, where the third 1803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // is always ecx (needed for shift operations). The input is two registers 1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // that must be preserved and one scratch register provided by the caller. 1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch class RegisterAllocation { 1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public: 1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RegisterAllocation(Register object, 1853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register address, 1863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch0) 1873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : object_orig_(object), 1883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch address_orig_(address), 1893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch0_orig_(scratch0), 1903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch object_(object), 1913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch address_(address), 1923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch0_(scratch0) { 193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!AreAliased(scratch0, object, address, no_reg)); 1943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch1_ = GetRegThatIsNotEcxOr(object_, address_, scratch0_); 1953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (scratch0.is(ecx)) { 1963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch0_ = GetRegThatIsNotEcxOr(object_, address_, scratch1_); 1973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (object.is(ecx)) { 1993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch object_ = GetRegThatIsNotEcxOr(address_, scratch0_, scratch1_); 2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (address.is(ecx)) { 2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch address_ = GetRegThatIsNotEcxOr(object_, scratch0_, scratch1_); 2033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!AreAliased(scratch0_, object_, address_, ecx)); 2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void Save(MacroAssembler* masm) { 208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!address_orig_.is(object_)); 209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(object_.is(object_orig_) || address_.is(address_orig_)); 210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!AreAliased(object_, address_, scratch1_, scratch0_)); 211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!AreAliased(object_orig_, address_, scratch1_, scratch0_)); 212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!AreAliased(object_, address_orig_, scratch1_, scratch0_)); 2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We don't have to save scratch0_orig_ because it was given to us as 2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a scratch register. But if we had to switch to a different reg then 2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // we should save the new scratch0_. 2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!scratch0_.is(scratch0_orig_)) masm->push(scratch0_); 2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!ecx.is(scratch0_orig_) && 2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch !ecx.is(object_orig_) && 2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch !ecx.is(address_orig_)) { 2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->push(ecx); 2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->push(scratch1_); 2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!address_.is(address_orig_)) { 2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->push(address_); 2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->mov(address_, address_orig_); 2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object_.is(object_orig_)) { 2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->push(object_); 2293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->mov(object_, object_orig_); 2303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void Restore(MacroAssembler* masm) { 2343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // These will have been preserved the entire time, so we just need to move 2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // them back. Only in one case is the orig_ reg different from the plain 2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // one, since only one of them can alias with ecx. 2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object_.is(object_orig_)) { 2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->mov(object_orig_, object_); 2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->pop(object_); 2403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!address_.is(address_orig_)) { 2423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->mov(address_orig_, address_); 2433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->pop(address_); 2443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->pop(scratch1_); 2463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!ecx.is(scratch0_orig_) && 2473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch !ecx.is(object_orig_) && 2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch !ecx.is(address_orig_)) { 2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->pop(ecx); 2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!scratch0_.is(scratch0_orig_)) masm->pop(scratch0_); 2523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If we have to call into C then we need to save and restore all caller- 2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // saved registers that were not already preserved. The caller saved 2563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // registers are eax, ecx and edx. The three scratch registers (incl. ecx) 2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // will be restored by other means so we don't bother pushing them here. 2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void SaveCallerSaveRegisters(MacroAssembler* masm, SaveFPRegsMode mode) { 259109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch masm->PushCallerSaved(mode, ecx, scratch0_, scratch1_); 2603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 262109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch inline void RestoreCallerSaveRegisters(MacroAssembler* masm, 2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SaveFPRegsMode mode) { 264109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch masm->PopCallerSaved(mode, ecx, scratch0_, scratch1_); 2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch inline Register object() { return object_; } 2683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch inline Register address() { return address_; } 2693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch inline Register scratch0() { return scratch0_; } 2703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch inline Register scratch1() { return scratch1_; } 2713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private: 2733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object_orig_; 2743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register address_orig_; 2753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch0_orig_; 2763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object_; 2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register address_; 2783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch0_; 2793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1_; 2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Third scratch register is always ecx. 2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register GetRegThatIsNotEcxOr(Register r1, 2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register r2, 2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register r3) { 285014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (int i = 0; i < Register::kNumRegisters; i++) { 28613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (RegisterConfiguration::Crankshaft()->IsAllocatableGeneralCode(i)) { 28713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Register candidate = Register::from_code(i); 288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (candidate.is(ecx)) continue; 289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (candidate.is(r1)) continue; 290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (candidate.is(r2)) continue; 291014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (candidate.is(r3)) continue; 292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return candidate; 293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch UNREACHABLE(); 2963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return no_reg; 2973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch friend class RecordWriteStub; 2993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch }; 3003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch enum OnNoNeedToInformIncrementalMarker { 3023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kReturnOnNoNeedToInformIncrementalMarker, 3033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kUpdateRememberedSetOnNoNeedToInformIncrementalMarker 304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 306014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch inline Major MajorKey() const final { return RecordWrite; } 307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 308014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void Generate(MacroAssembler* masm) override; 3093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void GenerateIncremental(MacroAssembler* masm, Mode mode); 3103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CheckNeedsToInformIncrementalMarker( 3113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler* masm, 3123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OnNoNeedToInformIncrementalMarker on_no_need, 3133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Mode mode); 314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void InformIncrementalMarker(MacroAssembler* masm); 3153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 316014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void Activate(Code* code) override { 317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch code->GetHeap()->incremental_marking()->ActivateGeneratedStub(code); 318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object() const { 321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return Register::from_code(ObjectBits::decode(minor_key_)); 3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value() const { 325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return Register::from_code(ValueBits::decode(minor_key_)); 326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register address() const { 329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return Register::from_code(AddressBits::decode(minor_key_)); 330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RememberedSetAction remembered_set_action() const { 333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return RememberedSetActionBits::decode(minor_key_); 334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SaveFPRegsMode save_fp_regs_mode() const { 337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return SaveFPRegsModeBits::decode(minor_key_); 3383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch class ObjectBits: public BitField<int, 0, 3> {}; 3413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch class ValueBits: public BitField<int, 3, 3> {}; 3423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch class AddressBits: public BitField<int, 6, 3> {}; 3433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch class RememberedSetActionBits: public BitField<RememberedSetAction, 9, 1> {}; 3443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch class SaveFPRegsModeBits: public BitField<SaveFPRegsMode, 10, 1> {}; 3453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RegisterAllocation regs_; 347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DISALLOW_COPY_AND_ASSIGN(RecordWriteStub); 3493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}; 3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 352014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 353014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 35480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 35580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#endif // V8_IA32_CODE_STUBS_IA32_H_ 356