1257744e915dfc84d6d07a6b2accf8402d9ffc708Ben 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.
444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#ifndef V8_MIPS_CODE_STUBS_MIPS_H_
6014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define V8_MIPS_CODE_STUBS_MIPS_H_
7014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
8014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/mips/frames-mips.h"
944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1044f0eee88ff00398ff7f715fab053374d808c90dSteve Blocknamespace v8 {
1144f0eee88ff00398ff7f715fab053374d808c90dSteve Blocknamespace internal {
1244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ArrayNativeCode(MacroAssembler* masm, Label* call_generic_code);
1544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochclass StringHelper : public AllStatic {
183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Generate code for copying a large number of characters. This function
20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // is allowed to spend extra time setting up conditions to make copying
21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // faster. Copying of overlapping regions is not supported.
223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Dest register ends at the position after the last character written.
233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void GenerateCopyCharacters(MacroAssembler* masm,
243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Register dest,
253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Register src,
263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Register count,
273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Register scratch,
28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     String::Encoding encoding);
293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Compares two flat one-byte strings and returns result in v0.
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void GenerateCompareFlatOneByteStrings(
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      MacroAssembler* masm, Register left, Register right, Register scratch1,
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register scratch2, Register scratch3, Register scratch4);
343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Compares two flat one-byte strings for equality and returns result in v0.
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void GenerateFlatOneByteStringEquals(MacroAssembler* masm,
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              Register left, Register right,
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              Register scratch1,
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              Register scratch2,
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              Register scratch3);
4144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4244f0eee88ff00398ff7f715fab053374d808c90dSteve Block private:
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void GenerateOneByteCharsCompareLoop(
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      MacroAssembler* masm, Register left, Register right, Register length,
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register scratch1, Register scratch2, Register scratch3,
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Label* chars_not_equal);
4744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper);
4944f0eee88ff00398ff7f715fab053374d808c90dSteve Block};
5044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass StoreRegistersStateStub: public PlatformCodeStub {
5344f0eee88ff00398ff7f715fab053374d808c90dSteve Block public:
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit StoreRegistersStateStub(Isolate* isolate)
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : PlatformCodeStub(isolate) {}
5644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void GenerateAheadOfTime(Isolate* isolate);
5844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_PLATFORM_CODE_STUB(StoreRegistersState, PlatformCodeStub);
6244f0eee88ff00398ff7f715fab053374d808c90dSteve Block};
6344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass RestoreRegistersStateStub: public PlatformCodeStub {
6644f0eee88ff00398ff7f715fab053374d808c90dSteve Block public:
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit RestoreRegistersStateStub(Isolate* isolate)
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : PlatformCodeStub(isolate) {}
6944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void GenerateAheadOfTime(Isolate* isolate);
7144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
72257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private:
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_PLATFORM_CODE_STUB(RestoreRegistersState, PlatformCodeStub);
7544f0eee88ff00398ff7f715fab053374d808c90dSteve Block};
7644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
7744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass RecordWriteStub: public PlatformCodeStub {
7944f0eee88ff00398ff7f715fab053374d808c90dSteve Block public:
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordWriteStub(Isolate* isolate,
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  Register object,
823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  Register value,
833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  Register address,
843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  RememberedSetAction remembered_set_action,
853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  SaveFPRegsMode fp_mode)
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : PlatformCodeStub(isolate),
873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        regs_(object,   // An input reg.
883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              address,  // An input reg.
893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              value) {  // One scratch reg.
90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    minor_key_ = ObjectBits::encode(object.code()) |
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 ValueBits::encode(value.code()) |
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 AddressBits::encode(address.code()) |
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 RememberedSetActionBits::encode(remembered_set_action) |
94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 SaveFPRegsModeBits::encode(fp_mode);
953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordWriteStub(uint32_t key, Isolate* isolate)
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : PlatformCodeStub(key, isolate), regs_(object(), address(), value()) {}
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  enum Mode {
1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    STORE_BUFFER_ONLY,
1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    INCREMENTAL,
1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    INCREMENTAL_COMPACTION
1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool SometimesSetsUpAFrame() override { return false; }
1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void PatchBranchIntoNop(MacroAssembler* masm, int pos) {
1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    const unsigned offset = masm->instr_at(pos) & kImm16Mask;
1103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    masm->instr_at_put(pos, BNE | (zero_reg.code() << kRsShift) |
1113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        (zero_reg.code() << kRtShift) | (offset & kImm16Mask));
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(Assembler::IsBne(masm->instr_at(pos)));
1133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void PatchNopIntoBranch(MacroAssembler* masm, int pos) {
1163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    const unsigned offset = masm->instr_at(pos) & kImm16Mask;
1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    masm->instr_at_put(pos, BEQ | (zero_reg.code() << kRsShift) |
1183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        (zero_reg.code() << kRtShift) | (offset & kImm16Mask));
119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(Assembler::IsBeq(masm->instr_at(pos)));
1203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static Mode GetMode(Code* stub) {
1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Instr first_instruction = Assembler::instr_at(stub->instruction_start());
1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Instr second_instruction = Assembler::instr_at(stub->instruction_start() +
1253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   2 * Assembler::kInstrSize);
1263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (Assembler::IsBeq(first_instruction)) {
1283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return INCREMENTAL;
1293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(Assembler::IsBne(first_instruction));
1323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (Assembler::IsBeq(second_instruction)) {
1343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return INCREMENTAL_COMPACTION;
1353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(Assembler::IsBne(second_instruction));
1383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return STORE_BUFFER_ONLY;
1403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void Patch(Code* stub, Mode mode) {
143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    MacroAssembler masm(stub->GetIsolate(), stub->instruction_start(),
144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                        stub->instruction_size(), CodeObjectRequired::kNo);
1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    switch (mode) {
1463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case STORE_BUFFER_ONLY:
147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(GetMode(stub) == INCREMENTAL ||
1483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               GetMode(stub) == INCREMENTAL_COMPACTION);
1493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        PatchBranchIntoNop(&masm, 0);
1503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        PatchBranchIntoNop(&masm, 2 * Assembler::kInstrSize);
1513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
1523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case INCREMENTAL:
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(GetMode(stub) == STORE_BUFFER_ONLY);
1543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        PatchNopIntoBranch(&masm, 0);
1553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
1563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case INCREMENTAL_COMPACTION:
157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(GetMode(stub) == STORE_BUFFER_ONLY);
1583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        PatchNopIntoBranch(&masm, 2 * Assembler::kInstrSize);
1593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
1603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(GetMode(stub) == mode);
162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Assembler::FlushICache(stub->GetIsolate(), stub->instruction_start(),
163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                           4 * Assembler::kInstrSize);
1643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private:
1693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // This is a helper class for freeing up 3 scratch registers.  The input is
1703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // two registers that must be preserved and one scratch register provided by
1713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the caller.
1723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  class RegisterAllocation {
1733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   public:
1743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RegisterAllocation(Register object,
1753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       Register address,
1763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       Register scratch0)
1773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : object_(object),
1783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          address_(address),
1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          scratch0_(scratch0) {
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(!AreAliased(scratch0, object, address, no_reg));
181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      scratch1_ = GetRegisterThatIsNotOneOf(object_, address_, scratch0_);
1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    void Save(MacroAssembler* masm) {
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(!AreAliased(object_, address_, scratch1_, scratch0_));
1863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // We don't have to save scratch0_ because it was given to us as
1873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // a scratch register.
1883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      masm->push(scratch1_);
1893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    void Restore(MacroAssembler* masm) {
1923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      masm->pop(scratch1_);
1933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // If we have to call into C then we need to save and restore all caller-
1963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // saved registers that were not already preserved.  The scratch registers
1973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // will be restored by other means so we don't bother pushing them here.
1983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    void SaveCallerSaveRegisters(MacroAssembler* masm, SaveFPRegsMode mode) {
1993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      masm->MultiPush((kJSCallerSaved | ra.bit()) & ~scratch1_.bit());
2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (mode == kSaveFPRegs) {
2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        masm->MultiPushFPU(kCallerSavedFPU);
2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
2033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    inline void RestoreCallerSaveRegisters(MacroAssembler*masm,
2063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           SaveFPRegsMode mode) {
2073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (mode == kSaveFPRegs) {
2083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        masm->MultiPopFPU(kCallerSavedFPU);
2093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
2103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      masm->MultiPop((kJSCallerSaved | ra.bit()) & ~scratch1_.bit());
2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    inline Register object() { return object_; }
2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    inline Register address() { return address_; }
2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    inline Register scratch0() { return scratch0_; }
2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    inline Register scratch1() { return scratch1_; }
2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   private:
2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register object_;
2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register address_;
2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch0_;
2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch1_;
2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    friend class RecordWriteStub;
2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  enum OnNoNeedToInformIncrementalMarker {
2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    kReturnOnNoNeedToInformIncrementalMarker,
2293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    kUpdateRememberedSetOnNoNeedToInformIncrementalMarker
2303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline Major MajorKey() const final { return RecordWrite; }
233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Generate(MacroAssembler* masm) override;
2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void GenerateIncremental(MacroAssembler* masm, Mode mode);
2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CheckNeedsToInformIncrementalMarker(
2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      MacroAssembler* masm,
2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      OnNoNeedToInformIncrementalMarker on_no_need,
2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Mode mode);
240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void InformIncrementalMarker(MacroAssembler* masm);
2413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Activate(Code* code) override {
243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    code->GetHeap()->incremental_marking()->ActivateGeneratedStub(code);
244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register object() const {
247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Register::from_code(ObjectBits::decode(minor_key_));
2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register value() const {
251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Register::from_code(ValueBits::decode(minor_key_));
252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register address() const {
255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Register::from_code(AddressBits::decode(minor_key_));
256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RememberedSetAction remembered_set_action() const {
259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return RememberedSetActionBits::decode(minor_key_);
260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SaveFPRegsMode save_fp_regs_mode() const {
263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return SaveFPRegsModeBits::decode(minor_key_);
2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  class ObjectBits: public BitField<int, 0, 5> {};
2673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  class ValueBits: public BitField<int, 5, 5> {};
2683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  class AddressBits: public BitField<int, 10, 5> {};
2693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  class RememberedSetActionBits: public BitField<RememberedSetAction, 15, 1> {};
2703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  class SaveFPRegsModeBits: public BitField<SaveFPRegsMode, 16, 1> {};
2713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label slow_;
2733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RegisterAllocation regs_;
27444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DISALLOW_COPY_AND_ASSIGN(RecordWriteStub);
27644f0eee88ff00398ff7f715fab053374d808c90dSteve Block};
27744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Trampoline stub to call into native code. To call safely into native code
280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// in the presence of compacting GC (which can move code objects) we need to
281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// keep the code which called into native pinned in the memory. Currently the
282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// simplest approach is to generate such stub early enough so it can never be
283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// moved by GC
284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass DirectCEntryStub: public PlatformCodeStub {
285257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch public:
286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit DirectCEntryStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateCall(MacroAssembler* masm, Register target);
288257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private:
290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool NeedsImmovableCode() override { return true; }
291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_PLATFORM_CODE_STUB(DirectCEntry, PlatformCodeStub);
294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch};
295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass NameDictionaryLookupStub: public PlatformCodeStub {
298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch public:
299257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  enum LookupMode { POSITIVE_LOOKUP, NEGATIVE_LOOKUP };
300257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  NameDictionaryLookupStub(Isolate* isolate, LookupMode mode)
302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : PlatformCodeStub(isolate) {
303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    minor_key_ = LookupModeBits::encode(mode);
304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
305257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void GenerateNegativeLookup(MacroAssembler* masm,
3073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Label* miss,
3083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Label* done,
3093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Register receiver,
3103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Register properties,
311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     Handle<Name> name,
3123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Register scratch0);
313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void GeneratePositiveLookup(MacroAssembler* masm,
315257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Label* miss,
316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Label* done,
317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Register elements,
318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Register name,
319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Register r0,
320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Register r1);
321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
322014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool SometimesSetsUpAFrame() override { return false; }
3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private:
325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static const int kInlinedProbes = 4;
326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static const int kTotalProbes = 20;
327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static const int kCapacityOffset =
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      NameDictionary::kHeaderSize +
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      NameDictionary::kCapacityIndex * kPointerSize;
331257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static const int kElementsStartOffset =
333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      NameDictionary::kHeaderSize +
334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      NameDictionary::kElementsStartIndex * kPointerSize;
335257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LookupMode mode() const { return LookupModeBits::decode(minor_key_); }
337257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
338257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  class LookupModeBits: public BitField<LookupMode, 0, 1> {};
339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_PLATFORM_CODE_STUB(NameDictionaryLookup, PlatformCodeStub);
342257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch};
34344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
34444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
345014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
346014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
34744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
348014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif  // V8_MIPS_CODE_STUBS_MIPS_H_
349