1864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// Copyright 2011 the V8 project authors. All rights reserved. 2864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// Use of this source code is governed by a BSD-style license that can be 3864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// found in the LICENSE file. 4864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 5864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#ifndef V8_X87_CODE_STUBS_X87_H_ 6864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#define V8_X87_CODE_STUBS_X87_H_ 7864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 8864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgnamespace v8 { 9864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgnamespace internal { 10864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 11864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 12864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid ArrayNativeCode(MacroAssembler* masm, 13864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org bool construct_call, 14864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label* call_generic_code); 15864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 16864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 17864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgclass StringHelper : public AllStatic { 18864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org public: 19864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Generate code for copying characters using the rep movs instruction. 20864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Copies ecx characters from esi to edi. Copying of overlapping regions is 21864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // not supported. 228ddb15e9094939a28890ee8bbc7f7fa246ecea49machenbach@chromium.org static void GenerateCopyCharacters(MacroAssembler* masm, 238ddb15e9094939a28890ee8bbc7f7fa246ecea49machenbach@chromium.org Register dest, 248ddb15e9094939a28890ee8bbc7f7fa246ecea49machenbach@chromium.org Register src, 258ddb15e9094939a28890ee8bbc7f7fa246ecea49machenbach@chromium.org Register count, 268ddb15e9094939a28890ee8bbc7f7fa246ecea49machenbach@chromium.org Register scratch, 278ddb15e9094939a28890ee8bbc7f7fa246ecea49machenbach@chromium.org String::Encoding encoding); 28864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 29b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org // Compares two flat one byte strings and returns result in eax. 30b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org static void GenerateCompareFlatOneByteStrings(MacroAssembler* masm, 31b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org Register left, Register right, 32b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org Register scratch1, 33b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org Register scratch2, 34b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org Register scratch3); 35b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org 36b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org // Compares two flat one byte strings for equality and returns result in eax. 37b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org static void GenerateFlatOneByteStringEquals(MacroAssembler* masm, 389aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org Register left, Register right, 39864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register scratch1, 40b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org Register scratch2); 41864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 42864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org private: 43b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org static void GenerateOneByteCharsCompareLoop( 44b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org MacroAssembler* masm, Register left, Register right, Register length, 45b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org Register scratch, Label* chars_not_equal, 46864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label::Distance chars_not_equal_near = Label::kFar); 479aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org 489aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper); 49864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}; 50864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 51864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 52864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgclass NameDictionaryLookupStub: public PlatformCodeStub { 53864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org public: 54864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org enum LookupMode { POSITIVE_LOOKUP, NEGATIVE_LOOKUP }; 55864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 5642ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org NameDictionaryLookupStub(Isolate* isolate, Register dictionary, 5742ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org Register result, Register index, LookupMode mode) 5842ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org : PlatformCodeStub(isolate) { 5942ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org minor_key_ = DictionaryBits::encode(dictionary.code()) | 6042ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org ResultBits::encode(result.code()) | 6142ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org IndexBits::encode(index.code()) | LookupModeBits::encode(mode); 6242ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org } 63864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 64864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org static void GenerateNegativeLookup(MacroAssembler* masm, 65864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label* miss, 66864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label* done, 67864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register properties, 68864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Handle<Name> name, 69864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register r0); 70864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 71864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org static void GeneratePositiveLookup(MacroAssembler* masm, 72864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label* miss, 73864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label* done, 74864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register elements, 75864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register name, 76864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register r0, 77864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register r1); 78864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 79864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org virtual bool SometimesSetsUpAFrame() { return false; } 80864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 81864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org private: 82864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org static const int kInlinedProbes = 4; 83864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org static const int kTotalProbes = 20; 84864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 85864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org static const int kCapacityOffset = 86864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org NameDictionary::kHeaderSize + 87864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org NameDictionary::kCapacityIndex * kPointerSize; 88864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 89864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org static const int kElementsStartOffset = 90864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org NameDictionary::kHeaderSize + 91864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org NameDictionary::kElementsStartIndex * kPointerSize; 92864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 9342ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org Register dictionary() const { 9442ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org return Register::from_code(DictionaryBits::decode(minor_key_)); 9542ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org } 9642ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org 9742ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org Register result() const { 9842ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org return Register::from_code(ResultBits::decode(minor_key_)); 9942ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org } 100864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 10142ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org Register index() const { 10242ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org return Register::from_code(IndexBits::decode(minor_key_)); 103864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 104864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 10542ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org LookupMode mode() const { return LookupModeBits::decode(minor_key_); } 10642ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org 107864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org class DictionaryBits: public BitField<int, 0, 3> {}; 108864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org class ResultBits: public BitField<int, 3, 3> {}; 109864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org class IndexBits: public BitField<int, 6, 3> {}; 110864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org class LookupModeBits: public BitField<LookupMode, 9, 1> {}; 111864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 112b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR(); 1132c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org DEFINE_PLATFORM_CODE_STUB(NameDictionaryLookup, PlatformCodeStub); 114864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}; 115864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 116864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 117864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgclass RecordWriteStub: public PlatformCodeStub { 118864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org public: 11906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org RecordWriteStub(Isolate* isolate, Register object, Register value, 12006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org Register address, RememberedSetAction remembered_set_action, 12106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org SaveFPRegsMode fp_mode) 122864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org : PlatformCodeStub(isolate), 123864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org regs_(object, // An input reg. 124864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org address, // An input reg. 125864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org value) { // One scratch reg. 12642ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org minor_key_ = ObjectBits::encode(object.code()) | 12742ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org ValueBits::encode(value.code()) | 12842ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org AddressBits::encode(address.code()) | 12906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org RememberedSetActionBits::encode(remembered_set_action) | 13006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org SaveFPRegsModeBits::encode(fp_mode); 131864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 132864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1332c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org RecordWriteStub(uint32_t key, Isolate* isolate) 1342c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org : PlatformCodeStub(key, isolate), regs_(object(), address(), value()) {} 1352c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org 136864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org enum Mode { 137864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STORE_BUFFER_ONLY, 138864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org INCREMENTAL, 139864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org INCREMENTAL_COMPACTION 140864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org }; 141864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 142864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org virtual bool SometimesSetsUpAFrame() { return false; } 143864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 144864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org static const byte kTwoByteNopInstruction = 0x3c; // Cmpb al, #imm8. 145864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org static const byte kTwoByteJumpInstruction = 0xeb; // Jmp #imm8. 146864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 147864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org static const byte kFiveByteNopInstruction = 0x3d; // Cmpl eax, #imm32. 148864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org static const byte kFiveByteJumpInstruction = 0xe9; // Jmp #imm32. 149864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 150864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org static Mode GetMode(Code* stub) { 151864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org byte first_instruction = stub->instruction_start()[0]; 152864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org byte second_instruction = stub->instruction_start()[2]; 153864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 154864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (first_instruction == kTwoByteJumpInstruction) { 155864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org return INCREMENTAL; 156864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 157864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 158e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(first_instruction == kTwoByteNopInstruction); 159864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 160864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (second_instruction == kFiveByteJumpInstruction) { 161864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org return INCREMENTAL_COMPACTION; 162864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 163864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 164e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(second_instruction == kFiveByteNopInstruction); 165864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 166864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org return STORE_BUFFER_ONLY; 167864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 168864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 169864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org static void Patch(Code* stub, Mode mode) { 170864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org switch (mode) { 171864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org case STORE_BUFFER_ONLY: 172e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(GetMode(stub) == INCREMENTAL || 173864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org GetMode(stub) == INCREMENTAL_COMPACTION); 174864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org stub->instruction_start()[0] = kTwoByteNopInstruction; 175864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org stub->instruction_start()[2] = kFiveByteNopInstruction; 176864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org break; 177864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org case INCREMENTAL: 178e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(GetMode(stub) == STORE_BUFFER_ONLY); 179864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org stub->instruction_start()[0] = kTwoByteJumpInstruction; 180864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org break; 181864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org case INCREMENTAL_COMPACTION: 182e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(GetMode(stub) == STORE_BUFFER_ONLY); 183864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org stub->instruction_start()[0] = kTwoByteNopInstruction; 184864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org stub->instruction_start()[2] = kFiveByteJumpInstruction; 185864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org break; 186864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 187e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(GetMode(stub) == mode); 1885de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org CpuFeatures::FlushICache(stub->instruction_start(), 7); 189864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 190864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 191b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR(); 192b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org 193864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org private: 194864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // This is a helper class for freeing up 3 scratch registers, where the third 195864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // is always ecx (needed for shift operations). The input is two registers 196864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // that must be preserved and one scratch register provided by the caller. 197864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org class RegisterAllocation { 198864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org public: 199864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org RegisterAllocation(Register object, 200864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register address, 201864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register scratch0) 202864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org : object_orig_(object), 203864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org address_orig_(address), 204864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org scratch0_orig_(scratch0), 205864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org object_(object), 206864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org address_(address), 207864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org scratch0_(scratch0) { 208e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!AreAliased(scratch0, object, address, no_reg)); 209864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org scratch1_ = GetRegThatIsNotEcxOr(object_, address_, scratch0_); 210864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (scratch0.is(ecx)) { 211864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org scratch0_ = GetRegThatIsNotEcxOr(object_, address_, scratch1_); 212864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 213864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (object.is(ecx)) { 214864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org object_ = GetRegThatIsNotEcxOr(address_, scratch0_, scratch1_); 215864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 216864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (address.is(ecx)) { 217864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org address_ = GetRegThatIsNotEcxOr(object_, scratch0_, scratch1_); 218864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 219e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!AreAliased(scratch0_, object_, address_, ecx)); 220864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 221864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 222864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org void Save(MacroAssembler* masm) { 223e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!address_orig_.is(object_)); 224e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(object_.is(object_orig_) || address_.is(address_orig_)); 225e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!AreAliased(object_, address_, scratch1_, scratch0_)); 226e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!AreAliased(object_orig_, address_, scratch1_, scratch0_)); 227e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!AreAliased(object_, address_orig_, scratch1_, scratch0_)); 228864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // We don't have to save scratch0_orig_ because it was given to us as 229864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // a scratch register. But if we had to switch to a different reg then 230864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // we should save the new scratch0_. 231864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (!scratch0_.is(scratch0_orig_)) masm->push(scratch0_); 232864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (!ecx.is(scratch0_orig_) && 233864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org !ecx.is(object_orig_) && 234864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org !ecx.is(address_orig_)) { 235864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org masm->push(ecx); 236864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 237864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org masm->push(scratch1_); 238864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (!address_.is(address_orig_)) { 239864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org masm->push(address_); 240864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org masm->mov(address_, address_orig_); 241864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 242864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (!object_.is(object_orig_)) { 243864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org masm->push(object_); 244864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org masm->mov(object_, object_orig_); 245864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 246864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 247864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 248864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org void Restore(MacroAssembler* masm) { 249864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // These will have been preserved the entire time, so we just need to move 250864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // them back. Only in one case is the orig_ reg different from the plain 251864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // one, since only one of them can alias with ecx. 252864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (!object_.is(object_orig_)) { 253864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org masm->mov(object_orig_, object_); 254864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org masm->pop(object_); 255864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 256864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (!address_.is(address_orig_)) { 257864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org masm->mov(address_orig_, address_); 258864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org masm->pop(address_); 259864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 260864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org masm->pop(scratch1_); 261864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (!ecx.is(scratch0_orig_) && 262864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org !ecx.is(object_orig_) && 263864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org !ecx.is(address_orig_)) { 264864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org masm->pop(ecx); 265864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 266864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (!scratch0_.is(scratch0_orig_)) masm->pop(scratch0_); 267864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 268864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 269864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // If we have to call into C then we need to save and restore all caller- 270864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // saved registers that were not already preserved. The caller saved 271864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // registers are eax, ecx and edx. The three scratch registers (incl. ecx) 272864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // will be restored by other means so we don't bother pushing them here. 27306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org void SaveCallerSaveRegisters(MacroAssembler* masm, SaveFPRegsMode mode) { 274864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (!scratch0_.is(eax) && !scratch1_.is(eax)) masm->push(eax); 275864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (!scratch0_.is(edx) && !scratch1_.is(edx)) masm->push(edx); 27606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org if (mode == kSaveFPRegs) { 27706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org // Save FPU state in m108byte. 27806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org masm->sub(esp, Immediate(108)); 27906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org masm->fnsave(Operand(esp, 0)); 28006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org } 281864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 282864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 28306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org inline void RestoreCallerSaveRegisters(MacroAssembler* masm, 28406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org SaveFPRegsMode mode) { 28506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org if (mode == kSaveFPRegs) { 28606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org // Restore FPU state in m108byte. 28706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org masm->frstor(Operand(esp, 0)); 28806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org masm->add(esp, Immediate(108)); 28906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org } 290864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (!scratch0_.is(edx) && !scratch1_.is(edx)) masm->pop(edx); 291864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (!scratch0_.is(eax) && !scratch1_.is(eax)) masm->pop(eax); 292864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 293864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 294864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org inline Register object() { return object_; } 295864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org inline Register address() { return address_; } 296864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org inline Register scratch0() { return scratch0_; } 297864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org inline Register scratch1() { return scratch1_; } 298864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 299864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org private: 300864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register object_orig_; 301864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register address_orig_; 302864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register scratch0_orig_; 303864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register object_; 304864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register address_; 305864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register scratch0_; 306864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register scratch1_; 307864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Third scratch register is always ecx. 308864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 309864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register GetRegThatIsNotEcxOr(Register r1, 310864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register r2, 311864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register r3) { 312864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org for (int i = 0; i < Register::NumAllocatableRegisters(); i++) { 313864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register candidate = Register::FromAllocationIndex(i); 314864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (candidate.is(ecx)) continue; 315864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (candidate.is(r1)) continue; 316864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (candidate.is(r2)) continue; 317864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (candidate.is(r3)) continue; 318864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org return candidate; 319864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 320864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org UNREACHABLE(); 321864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org return no_reg; 322864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 323864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org friend class RecordWriteStub; 324864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org }; 325864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 326864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org enum OnNoNeedToInformIncrementalMarker { 327864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org kReturnOnNoNeedToInformIncrementalMarker, 328864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org kUpdateRememberedSetOnNoNeedToInformIncrementalMarker 32942ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org }; 33042ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org 3312c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org virtual inline Major MajorKey() const FINAL OVERRIDE { return RecordWrite; } 33242ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org 3332c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org virtual void Generate(MacroAssembler* masm) OVERRIDE; 334864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org void GenerateIncremental(MacroAssembler* masm, Mode mode); 335864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org void CheckNeedsToInformIncrementalMarker( 336864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org MacroAssembler* masm, 337864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org OnNoNeedToInformIncrementalMarker on_no_need, 338864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Mode mode); 339864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org void InformIncrementalMarker(MacroAssembler* masm); 340864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 34142ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org void Activate(Code* code) { 34242ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org code->GetHeap()->incremental_marking()->ActivateGeneratedStub(code); 34342ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org } 344864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 34542ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org Register object() const { 34642ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org return Register::from_code(ObjectBits::decode(minor_key_)); 347864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 348864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 34942ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org Register value() const { 35042ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org return Register::from_code(ValueBits::decode(minor_key_)); 35142ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org } 35242ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org 35342ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org Register address() const { 35442ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org return Register::from_code(AddressBits::decode(minor_key_)); 35542ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org } 35642ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org 35742ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org RememberedSetAction remembered_set_action() const { 35842ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org return RememberedSetActionBits::decode(minor_key_); 359864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 360864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 36106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org SaveFPRegsMode save_fp_regs_mode() const { 36206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org return SaveFPRegsModeBits::decode(minor_key_); 36306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org } 36406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org 365864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org class ObjectBits: public BitField<int, 0, 3> {}; 366864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org class ValueBits: public BitField<int, 3, 3> {}; 367864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org class AddressBits: public BitField<int, 6, 3> {}; 368864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org class RememberedSetActionBits: public BitField<RememberedSetAction, 9, 1> {}; 36906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org class SaveFPRegsModeBits : public BitField<SaveFPRegsMode, 10, 1> {}; 370864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 371864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org RegisterAllocation regs_; 37242ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org 37342ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org DISALLOW_COPY_AND_ASSIGN(RecordWriteStub); 374864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}; 375864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 376864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 377864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} } // namespace v8::internal 378864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 379864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#endif // V8_X87_CODE_STUBS_X87_H_ 380