LCOV - code coverage report
Current view: top level - src/x64 - code-stubs-x64.h (source / functions) Hit Total Coverage
Test: app.info Lines: 21 56 37.5 %
Date: 2017-10-20 Functions: 5 16 31.2 %

          Line data    Source code
       1             : // Copyright 2011 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #ifndef V8_X64_CODE_STUBS_X64_H_
       6             : #define V8_X64_CODE_STUBS_X64_H_
       7             : 
       8             : namespace v8 {
       9             : namespace internal {
      10             : 
      11             : 
      12           0 : class NameDictionaryLookupStub: public PlatformCodeStub {
      13             :  public:
      14             :   NameDictionaryLookupStub(Isolate* isolate, Register dictionary,
      15             :                            Register result, Register index)
      16         829 :       : PlatformCodeStub(isolate) {
      17         829 :     minor_key_ = DictionaryBits::encode(dictionary.code()) |
      18         829 :                  ResultBits::encode(result.code()) |
      19         829 :                  IndexBits::encode(index.code());
      20             :   }
      21             : 
      22             :   static void GenerateNegativeLookup(MacroAssembler* masm,
      23             :                                      Label* miss,
      24             :                                      Label* done,
      25             :                                      Register properties,
      26             :                                      Handle<Name> name,
      27             :                                      Register r0);
      28             : 
      29           0 :   bool SometimesSetsUpAFrame() override { return false; }
      30             : 
      31             :  private:
      32             :   static const int kInlinedProbes = 4;
      33             :   static const int kTotalProbes = 20;
      34             : 
      35             :   static const int kCapacityOffset =
      36             :       NameDictionary::kHeaderSize +
      37             :       NameDictionary::kCapacityIndex * kPointerSize;
      38             : 
      39             :   static const int kElementsStartOffset =
      40             :       NameDictionary::kHeaderSize +
      41             :       NameDictionary::kElementsStartIndex * kPointerSize;
      42             : 
      43             :   Register dictionary() const {
      44             :     return Register::from_code(DictionaryBits::decode(minor_key_));
      45             :   }
      46             : 
      47             :   Register result() const {
      48             :     return Register::from_code(ResultBits::decode(minor_key_));
      49             :   }
      50             : 
      51             :   Register index() const {
      52             :     return Register::from_code(IndexBits::decode(minor_key_));
      53             :   }
      54             : 
      55             :   class DictionaryBits: public BitField<int, 0, 4> {};
      56             :   class ResultBits: public BitField<int, 4, 4> {};
      57             :   class IndexBits: public BitField<int, 8, 4> {};
      58             : 
      59           0 :   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
      60         940 :   DEFINE_PLATFORM_CODE_STUB(NameDictionaryLookup, PlatformCodeStub);
      61             : };
      62             : 
      63             : 
      64           6 : class RecordWriteStub: public PlatformCodeStub {
      65             :  public:
      66             :   RecordWriteStub(Isolate* isolate, Register object, Register value,
      67             :                   Register address, RememberedSetAction remembered_set_action,
      68             :                   SaveFPRegsMode fp_mode)
      69             :       : PlatformCodeStub(isolate),
      70             :         regs_(object,   // An input reg.
      71             :               address,  // An input reg.
      72             :               value) {  // One scratch reg.
      73             :     minor_key_ = ObjectBits::encode(object.code()) |
      74             :                  ValueBits::encode(value.code()) |
      75             :                  AddressBits::encode(address.code()) |
      76             :                  RememberedSetActionBits::encode(remembered_set_action) |
      77             :                  SaveFPRegsModeBits::encode(fp_mode);
      78             :   }
      79             : 
      80           6 :   RecordWriteStub(uint32_t key, Isolate* isolate)
      81          12 :       : PlatformCodeStub(key, isolate), regs_(object(), address(), value()) {}
      82             : 
      83             :   enum Mode {
      84             :     STORE_BUFFER_ONLY,
      85             :     INCREMENTAL,
      86             :     INCREMENTAL_COMPACTION
      87             :   };
      88             : 
      89           0 :   bool SometimesSetsUpAFrame() override { return false; }
      90             : 
      91             :   static const byte kTwoByteNopInstruction = 0x3c;  // Cmpb al, #imm8.
      92             :   static const byte kTwoByteJumpInstruction = 0xeb;  // Jmp #imm8.
      93             : 
      94             :   static Mode GetMode(Code* stub);
      95             : 
      96             :   static void Patch(Code* stub, Mode mode);
      97             : 
      98           0 :   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
      99             : 
     100             :  private:
     101             :   // This is a helper class for freeing up 3 scratch registers, where the third
     102             :   // is always rcx (needed for shift operations).  The input is two registers
     103             :   // that must be preserved and one scratch register provided by the caller.
     104             :   class RegisterAllocation {
     105             :    public:
     106           6 :     RegisterAllocation(Register object, Register address, Register scratch0)
     107             :         : object_orig_(object),
     108             :           address_orig_(address),
     109             :           scratch0_orig_(scratch0),
     110             :           object_(object),
     111             :           address_(address),
     112             :           scratch0_(scratch0),
     113           6 :           scratch1_(no_reg) {
     114             :       DCHECK(!AreAliased(scratch0, object, address, no_reg));
     115           6 :       scratch1_ = GetRegThatIsNotRcxOr(object_, address_, scratch0_);
     116           6 :       if (scratch0 == rcx) {
     117           0 :         scratch0_ = GetRegThatIsNotRcxOr(object_, address_, scratch1_);
     118             :       }
     119           6 :       if (object == rcx) {
     120           0 :         object_ = GetRegThatIsNotRcxOr(address_, scratch0_, scratch1_);
     121             :       }
     122           6 :       if (address == rcx) {
     123           0 :         address_ = GetRegThatIsNotRcxOr(object_, scratch0_, scratch1_);
     124             :       }
     125             :       DCHECK(!AreAliased(scratch0_, object_, address_, rcx));
     126           6 :     }
     127             : 
     128           0 :     void Save(MacroAssembler* masm) {
     129             :       DCHECK(address_orig_ != object_);
     130             :       DCHECK(object_ == object_orig_ || address_ == address_orig_);
     131             :       DCHECK(!AreAliased(object_, address_, scratch1_, scratch0_));
     132             :       DCHECK(!AreAliased(object_orig_, address_, scratch1_, scratch0_));
     133             :       DCHECK(!AreAliased(object_, address_orig_, scratch1_, scratch0_));
     134             :       // We don't have to save scratch0_orig_ because it was given to us as
     135             :       // a scratch register.  But if we had to switch to a different reg then
     136             :       // we should save the new scratch0_.
     137           0 :       if (scratch0_ != scratch0_orig_) masm->Push(scratch0_);
     138           0 :       if (rcx != scratch0_orig_ && rcx != object_orig_ &&
     139             :           rcx != address_orig_) {
     140           0 :         masm->Push(rcx);
     141             :       }
     142           0 :       masm->Push(scratch1_);
     143           0 :       if (address_ != address_orig_) {
     144           0 :         masm->Push(address_);
     145           0 :         masm->movp(address_, address_orig_);
     146             :       }
     147           0 :       if (object_ != object_orig_) {
     148           0 :         masm->Push(object_);
     149           0 :         masm->movp(object_, object_orig_);
     150             :       }
     151           0 :     }
     152             : 
     153           0 :     void Restore(MacroAssembler* masm) {
     154             :       // These will have been preserved the entire time, so we just need to move
     155             :       // them back.  Only in one case is the orig_ reg different from the plain
     156             :       // one, since only one of them can alias with rcx.
     157           0 :       if (object_ != object_orig_) {
     158           0 :         masm->movp(object_orig_, object_);
     159           0 :         masm->Pop(object_);
     160             :       }
     161           0 :       if (address_ != address_orig_) {
     162           0 :         masm->movp(address_orig_, address_);
     163           0 :         masm->Pop(address_);
     164             :       }
     165           0 :       masm->Pop(scratch1_);
     166           0 :       if (rcx != scratch0_orig_ && rcx != object_orig_ &&
     167             :           rcx != address_orig_) {
     168           0 :         masm->Pop(rcx);
     169             :       }
     170           0 :       if (scratch0_ != scratch0_orig_) masm->Pop(scratch0_);
     171           0 :     }
     172             : 
     173             :     // If we have to call into C then we need to save and restore all caller-
     174             :     // saved registers that were not already preserved.
     175             : 
     176             :     // The three scratch registers (incl. rcx) will be restored by other means
     177             :     // so we don't bother pushing them here.  Rbx, rbp and r12-15 are callee
     178             :     // save and don't need to be preserved.
     179             :     void SaveCallerSaveRegisters(MacroAssembler* masm, SaveFPRegsMode mode) {
     180           0 :       masm->PushCallerSaved(mode, scratch0_, scratch1_, rcx);
     181             :     }
     182             : 
     183             :     inline void RestoreCallerSaveRegisters(MacroAssembler*masm,
     184             :                                            SaveFPRegsMode mode) {
     185           0 :       masm->PopCallerSaved(mode, scratch0_, scratch1_, rcx);
     186             :     }
     187             : 
     188             :     inline Register object() { return object_; }
     189             :     inline Register address() { return address_; }
     190             :     inline Register scratch0() { return scratch0_; }
     191             :     inline Register scratch1() { return scratch1_; }
     192             : 
     193             :    private:
     194             :     Register object_orig_;
     195             :     Register address_orig_;
     196             :     Register scratch0_orig_;
     197             :     Register object_;
     198             :     Register address_;
     199             :     Register scratch0_;
     200             :     Register scratch1_;
     201             :     // Third scratch register is always rcx.
     202             : 
     203           6 :     Register GetRegThatIsNotRcxOr(Register r1,
     204             :                                   Register r2,
     205             :                                   Register r3) {
     206          12 :       for (int i = 0; i < Register::kNumRegisters; i++) {
     207          36 :         if (RegisterConfiguration::Default()->IsAllocatableGeneralCode(i)) {
     208             :           Register candidate = Register::from_code(i);
     209          18 :           if (candidate != rcx && candidate != r1 && candidate != r2 &&
     210             :               candidate != r3) {
     211           6 :             return candidate;
     212             :           }
     213             :         }
     214             :       }
     215           0 :       UNREACHABLE();
     216             :     }
     217             :     friend class RecordWriteStub;
     218             :   };
     219             : 
     220             :   enum OnNoNeedToInformIncrementalMarker {
     221             :     kReturnOnNoNeedToInformIncrementalMarker,
     222             :     kUpdateRememberedSetOnNoNeedToInformIncrementalMarker
     223             :   };
     224             : 
     225           6 :   Major MajorKey() const final { return RecordWrite; }
     226             : 
     227             :   void Generate(MacroAssembler* masm) override;
     228             :   void GenerateIncremental(MacroAssembler* masm, Label* second_instr);
     229             :   void CheckNeedsToInformIncrementalMarker(
     230             :       MacroAssembler* masm, OnNoNeedToInformIncrementalMarker on_no_need,
     231             :       Label* second_instr);
     232             :   void InformIncrementalMarker(MacroAssembler* masm);
     233             : 
     234             :   void Activate(Code* code) override;
     235             : 
     236             :   Register object() const {
     237             :     return Register::from_code(ObjectBits::decode(minor_key_));
     238             :   }
     239             : 
     240             :   Register value() const {
     241             :     return Register::from_code(ValueBits::decode(minor_key_));
     242             :   }
     243             : 
     244             :   Register address() const {
     245             :     return Register::from_code(AddressBits::decode(minor_key_));
     246             :   }
     247             : 
     248             :   RememberedSetAction remembered_set_action() const {
     249             :     return RememberedSetActionBits::decode(minor_key_);
     250             :   }
     251             : 
     252             :   SaveFPRegsMode save_fp_regs_mode() const {
     253             :     return SaveFPRegsModeBits::decode(minor_key_);
     254             :   }
     255             : 
     256             :   class ObjectBits: public BitField<int, 0, 4> {};
     257             :   class ValueBits: public BitField<int, 4, 4> {};
     258             :   class AddressBits: public BitField<int, 8, 4> {};
     259             :   class RememberedSetActionBits: public BitField<RememberedSetAction, 12, 1> {};
     260             :   class SaveFPRegsModeBits: public BitField<SaveFPRegsMode, 13, 1> {};
     261             : 
     262             :   Label slow_;
     263             :   RegisterAllocation regs_;
     264             : 
     265             :   DISALLOW_COPY_AND_ASSIGN(RecordWriteStub);
     266             : };
     267             : 
     268             : 
     269             : }  // namespace internal
     270             : }  // namespace v8
     271             : 
     272             : #endif  // V8_X64_CODE_STUBS_X64_H_

Generated by: LCOV version 1.10