15d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org// Copyright 2011 the V8 project authors. All rights reserved.
265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// Redistribution and use in source and binary forms, with or without
365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// modification, are permitted provided that the following conditions are
465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// met:
565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org//
665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org//     * Redistributions of source code must retain the above copyright
765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org//       notice, this list of conditions and the following disclaimer.
865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org//     * Redistributions in binary form must reproduce the above
965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org//       copyright notice, this list of conditions and the following
1065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org//       disclaimer in the documentation and/or other materials provided
1165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org//       with the distribution.
1265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org//     * Neither the name of Google Inc. nor the names of its
1365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org//       contributors may be used to endorse or promote products derived
1465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org//       from this software without specific prior written permission.
1565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org//
1665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
2865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#ifndef V8_X64_CODE_STUBS_X64_H_
2965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#define V8_X64_CODE_STUBS_X64_H_
3065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
3165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#include "ic-inl.h"
32d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org#include "type-info.h"
3365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
3465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgnamespace v8 {
3565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgnamespace internal {
3665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
3765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
38ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgvoid ArrayNativeCode(MacroAssembler* masm, Label* call_generic_code);
39ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
4065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// Compute a transcendental math function natively, or call the
4165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// TranscendentalCache runtime function.
42a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgclass TranscendentalCacheStub: public PlatformCodeStub {
4365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org public:
445d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  enum ArgumentType {
455d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org    TAGGED = 0,
465d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org    UNTAGGED = 1 << TranscendentalCache::kTranscendentalTypeBits
475d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  };
485d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org
495d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  explicit TranscendentalCacheStub(TranscendentalCache::Type type,
505d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org                                   ArgumentType argument_type)
515d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org      : type_(type), argument_type_(argument_type) {}
5265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  void Generate(MacroAssembler* masm);
539a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org  static void GenerateOperation(MacroAssembler* masm,
549a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org                                TranscendentalCache::Type type);
5565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org private:
5665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  TranscendentalCache::Type type_;
575d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  ArgumentType argument_type_;
585d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org
5965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Major MajorKey() { return TranscendentalCache; }
605d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  int MinorKey() { return type_ | argument_type_; }
6165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Runtime::FunctionId RuntimeFunction();
6265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org};
6365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
6465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
65a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgclass StoreBufferOverflowStub: public PlatformCodeStub {
66c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com public:
67c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  explicit StoreBufferOverflowStub(SaveFPRegsMode save_fp)
68c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      : save_doubles_(save_fp) { }
69c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
70c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void Generate(MacroAssembler* masm);
71c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
728432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
73c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  virtual bool SometimesSetsUpAFrame() { return false; }
74c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
75c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com private:
76c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  SaveFPRegsMode save_doubles_;
77c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
78c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Major MajorKey() { return StoreBufferOverflow; }
79c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  int MinorKey() { return (save_doubles_ == kSaveFPRegs) ? 1 : 0; }
80c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com};
81c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
82c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
8365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgclass StringHelper : public AllStatic {
8465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org public:
8565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Generate code for copying characters using a simple loop. This should only
8665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // be used in places where the number of characters is small and the
8765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // additional setup and checking in GenerateCopyCharactersREP adds too much
8865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // overhead. Copying of overlapping regions is not supported.
8965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  static void GenerateCopyCharacters(MacroAssembler* masm,
9065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                     Register dest,
9165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                     Register src,
9265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                     Register count,
9365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                     bool ascii);
9465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
9565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Generate code for copying characters using the rep movs instruction.
9665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Copies rcx characters from rsi to rdi. Copying of overlapping regions is
9765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // not supported.
9865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  static void GenerateCopyCharactersREP(MacroAssembler* masm,
9965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                        Register dest,     // Must be rdi.
10065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                        Register src,      // Must be rsi.
10165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                        Register count,    // Must be rcx.
10265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                        bool ascii);
10365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
10465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
1054a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Probe the string table for a two character string. If the string is
10665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // not found by probing a jump to the label not_found is performed. This jump
1074a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // does not guarantee that the string is not in the string table. If the
10865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // string is found the code falls through with the string in register rax.
1094a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  static void GenerateTwoCharacterStringTableProbe(MacroAssembler* masm,
11065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                   Register c1,
11165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                   Register c2,
11265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                   Register scratch1,
11365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                   Register scratch2,
11465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                   Register scratch3,
11565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                   Register scratch4,
11665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                   Label* not_found);
11765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
11865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Generate string hash.
11965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  static void GenerateHashInit(MacroAssembler* masm,
12065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                               Register hash,
12165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                               Register character,
12265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                               Register scratch);
12365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  static void GenerateHashAddCharacter(MacroAssembler* masm,
12465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                       Register hash,
12565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                       Register character,
12665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                       Register scratch);
12765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  static void GenerateHashGetHash(MacroAssembler* masm,
12865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                  Register hash,
12965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                  Register scratch);
13065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
13165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org private:
13265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper);
13365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org};
13465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
13565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
136a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgclass StringAddStub: public PlatformCodeStub {
13765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org public:
1383a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  explicit StringAddStub(StringAddFlags flags) : flags_(flags) {}
13965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
14065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org private:
14165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Major MajorKey() { return StringAdd; }
1423a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  int MinorKey() { return flags_; }
14365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
14465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  void Generate(MacroAssembler* masm);
14565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
1463a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  void GenerateConvertArgument(MacroAssembler* masm,
1473a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                               int stack_offset,
1483a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                               Register arg,
1493a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                               Register scratch1,
1503a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                               Register scratch2,
1513a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                               Register scratch3,
1523a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                               Label* slow);
1533a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
1544e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  void GenerateRegisterArgsPush(MacroAssembler* masm);
1554e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  void GenerateRegisterArgsPop(MacroAssembler* masm, Register temp);
1564e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org
1573a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  const StringAddFlags flags_;
15865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org};
15965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
16065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
161a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgclass SubStringStub: public PlatformCodeStub {
16265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org public:
16365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  SubStringStub() {}
16465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
16565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org private:
16665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Major MajorKey() { return SubString; }
16765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  int MinorKey() { return 0; }
16865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
16965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  void Generate(MacroAssembler* masm);
17065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org};
17165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
17265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
173a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgclass StringCompareStub: public PlatformCodeStub {
17465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org public:
1751c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  StringCompareStub() {}
17665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
1771c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Compares two flat ASCII strings and returns result in rax.
17865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  static void GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
17965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                              Register left,
18065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                              Register right,
18165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                              Register scratch1,
18265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                              Register scratch2,
18365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                              Register scratch3,
18465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                              Register scratch4);
18565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
1861c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Compares two flat ASCII strings for equality and returns result
1871c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // in rax.
1881c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  static void GenerateFlatAsciiStringEquals(MacroAssembler* masm,
1891c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                                            Register left,
1901c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                                            Register right,
1911c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                                            Register scratch1,
1921c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                                            Register scratch2);
19365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
1941c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org private:
1951c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  virtual Major MajorKey() { return StringCompare; }
1961c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  virtual int MinorKey() { return 0; }
1971c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  virtual void Generate(MacroAssembler* masm);
1981c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
19983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static void GenerateAsciiCharsCompareLoop(
20083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      MacroAssembler* masm,
20183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      Register left,
20283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      Register right,
20383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      Register length,
20483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      Register scratch,
20583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      Label* chars_not_equal,
20683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      Label::Distance near_jump = Label::kFar);
20765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org};
20865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
20965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
210750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.orgclass NameDictionaryLookupStub: public PlatformCodeStub {
2111c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org public:
2121c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  enum LookupMode { POSITIVE_LOOKUP, NEGATIVE_LOOKUP };
2131c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
214750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  NameDictionaryLookupStub(Register dictionary,
215750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                           Register result,
216750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                           Register index,
217750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                           LookupMode mode)
2181c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org      : dictionary_(dictionary), result_(result), index_(index), mode_(mode) { }
2191c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
2201c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  void Generate(MacroAssembler* masm);
2211c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
222394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  static void GenerateNegativeLookup(MacroAssembler* masm,
223394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                     Label* miss,
224394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                     Label* done,
225394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                     Register properties,
226750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                     Handle<Name> name,
227394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                     Register r0);
228394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
2291c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  static void GeneratePositiveLookup(MacroAssembler* masm,
2301c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                                     Label* miss,
2311c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                                     Label* done,
2321c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                                     Register elements,
2331c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                                     Register name,
2341c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                                     Register r0,
2351c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                                     Register r1);
2361c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
237c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  virtual bool SometimesSetsUpAFrame() { return false; }
238c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
2391c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org private:
2401c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  static const int kInlinedProbes = 4;
2411c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  static const int kTotalProbes = 20;
2421c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
2431c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  static const int kCapacityOffset =
244750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org      NameDictionary::kHeaderSize +
245750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org      NameDictionary::kCapacityIndex * kPointerSize;
2461c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
2471c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  static const int kElementsStartOffset =
248750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org      NameDictionary::kHeaderSize +
249750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org      NameDictionary::kElementsStartIndex * kPointerSize;
2501c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
251750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  Major MajorKey() { return NameDictionaryLookup; }
2521c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
2531c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  int MinorKey() {
2541c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    return DictionaryBits::encode(dictionary_.code()) |
2551c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org        ResultBits::encode(result_.code()) |
2561c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org        IndexBits::encode(index_.code()) |
2571c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org        LookupModeBits::encode(mode_);
2581c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  }
2591c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
2601c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  class DictionaryBits: public BitField<int, 0, 4> {};
2611c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  class ResultBits: public BitField<int, 4, 4> {};
2621c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  class IndexBits: public BitField<int, 8, 4> {};
2631c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  class LookupModeBits: public BitField<LookupMode, 12, 1> {};
2641c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
2651c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Register dictionary_;
2661c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Register result_;
2671c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Register index_;
2681c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  LookupMode mode_;
2691c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org};
2701c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
2711c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
272a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgclass RecordWriteStub: public PlatformCodeStub {
273c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com public:
274c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  RecordWriteStub(Register object,
275c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                  Register value,
276c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                  Register address,
277c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                  RememberedSetAction remembered_set_action,
278c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                  SaveFPRegsMode fp_mode)
279c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      : object_(object),
280c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        value_(value),
281c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        address_(address),
282c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        remembered_set_action_(remembered_set_action),
283c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        save_fp_regs_mode_(fp_mode),
284c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        regs_(object,   // An input reg.
285c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com              address,  // An input reg.
286c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com              value) {  // One scratch reg.
287c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
288c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
289c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  enum Mode {
290c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    STORE_BUFFER_ONLY,
291c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    INCREMENTAL,
292c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    INCREMENTAL_COMPACTION
293c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  };
294c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
295c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  virtual bool SometimesSetsUpAFrame() { return false; }
296c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
297c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  static const byte kTwoByteNopInstruction = 0x3c;  // Cmpb al, #imm8.
298c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  static const byte kTwoByteJumpInstruction = 0xeb;  // Jmp #imm8.
299c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
300c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  static const byte kFiveByteNopInstruction = 0x3d;  // Cmpl eax, #imm32.
301c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  static const byte kFiveByteJumpInstruction = 0xe9;  // Jmp #imm32.
302c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
303c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  static Mode GetMode(Code* stub) {
304c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    byte first_instruction = stub->instruction_start()[0];
305c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    byte second_instruction = stub->instruction_start()[2];
306c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
307c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    if (first_instruction == kTwoByteJumpInstruction) {
308c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      return INCREMENTAL;
309c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
310c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
311c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    ASSERT(first_instruction == kTwoByteNopInstruction);
312c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
313c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    if (second_instruction == kFiveByteJumpInstruction) {
314c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      return INCREMENTAL_COMPACTION;
315c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
316c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
317c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    ASSERT(second_instruction == kFiveByteNopInstruction);
318c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
319c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    return STORE_BUFFER_ONLY;
320c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
321c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
322c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  static void Patch(Code* stub, Mode mode) {
323c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    switch (mode) {
324c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      case STORE_BUFFER_ONLY:
325c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        ASSERT(GetMode(stub) == INCREMENTAL ||
326c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com               GetMode(stub) == INCREMENTAL_COMPACTION);
327c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        stub->instruction_start()[0] = kTwoByteNopInstruction;
328c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        stub->instruction_start()[2] = kFiveByteNopInstruction;
329c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        break;
330c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      case INCREMENTAL:
331c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        ASSERT(GetMode(stub) == STORE_BUFFER_ONLY);
332c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        stub->instruction_start()[0] = kTwoByteJumpInstruction;
333c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        break;
334c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      case INCREMENTAL_COMPACTION:
335c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        ASSERT(GetMode(stub) == STORE_BUFFER_ONLY);
336c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        stub->instruction_start()[0] = kTwoByteNopInstruction;
337c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        stub->instruction_start()[2] = kFiveByteJumpInstruction;
338c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        break;
339c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
340c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    ASSERT(GetMode(stub) == mode);
341c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    CPU::FlushICache(stub->instruction_start(), 7);
342c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
343c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
344c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com private:
345c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // This is a helper class for freeing up 3 scratch registers, where the third
346c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // is always rcx (needed for shift operations).  The input is two registers
347c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // that must be preserved and one scratch register provided by the caller.
348c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  class RegisterAllocation {
349c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com   public:
350c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    RegisterAllocation(Register object,
351c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                       Register address,
352c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                       Register scratch0)
353c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        : object_orig_(object),
354c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          address_orig_(address),
355c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          scratch0_orig_(scratch0),
356c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          object_(object),
357c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          address_(address),
358c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          scratch0_(scratch0) {
359c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      ASSERT(!AreAliased(scratch0, object, address, no_reg));
360c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      scratch1_ = GetRegThatIsNotRcxOr(object_, address_, scratch0_);
361c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      if (scratch0.is(rcx)) {
362c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        scratch0_ = GetRegThatIsNotRcxOr(object_, address_, scratch1_);
363c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      }
364c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      if (object.is(rcx)) {
365c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        object_ = GetRegThatIsNotRcxOr(address_, scratch0_, scratch1_);
366c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      }
367c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      if (address.is(rcx)) {
368c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        address_ = GetRegThatIsNotRcxOr(object_, scratch0_, scratch1_);
369c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      }
370c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      ASSERT(!AreAliased(scratch0_, object_, address_, rcx));
371c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
372c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
373c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    void Save(MacroAssembler* masm) {
374c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      ASSERT(!address_orig_.is(object_));
375c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      ASSERT(object_.is(object_orig_) || address_.is(address_orig_));
376c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      ASSERT(!AreAliased(object_, address_, scratch1_, scratch0_));
377c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      ASSERT(!AreAliased(object_orig_, address_, scratch1_, scratch0_));
378c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      ASSERT(!AreAliased(object_, address_orig_, scratch1_, scratch0_));
379c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // We don't have to save scratch0_orig_ because it was given to us as
380c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // a scratch register.  But if we had to switch to a different reg then
381c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // we should save the new scratch0_.
382c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      if (!scratch0_.is(scratch0_orig_)) masm->push(scratch0_);
383c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      if (!rcx.is(scratch0_orig_) &&
384c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          !rcx.is(object_orig_) &&
385c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          !rcx.is(address_orig_)) {
386c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        masm->push(rcx);
387c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      }
388c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      masm->push(scratch1_);
389c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      if (!address_.is(address_orig_)) {
390c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        masm->push(address_);
391c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        masm->movq(address_, address_orig_);
392c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      }
393c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      if (!object_.is(object_orig_)) {
394c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        masm->push(object_);
395c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        masm->movq(object_, object_orig_);
396c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      }
397c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
398c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
399c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    void Restore(MacroAssembler* masm) {
400c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // These will have been preserved the entire time, so we just need to move
401c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // them back.  Only in one case is the orig_ reg different from the plain
402c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // one, since only one of them can alias with rcx.
403c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      if (!object_.is(object_orig_)) {
404c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        masm->movq(object_orig_, object_);
405c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        masm->pop(object_);
406c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      }
407c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      if (!address_.is(address_orig_)) {
408c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        masm->movq(address_orig_, address_);
409c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        masm->pop(address_);
410c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      }
411c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      masm->pop(scratch1_);
412c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      if (!rcx.is(scratch0_orig_) &&
413c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          !rcx.is(object_orig_) &&
414c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          !rcx.is(address_orig_)) {
415c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        masm->pop(rcx);
416c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      }
417c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      if (!scratch0_.is(scratch0_orig_)) masm->pop(scratch0_);
418c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
419c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
420c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // If we have to call into C then we need to save and restore all caller-
421c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // saved registers that were not already preserved.
422c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
423c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // The three scratch registers (incl. rcx) will be restored by other means
424c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // so we don't bother pushing them here.  Rbx, rbp and r12-15 are callee
425c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // save and don't need to be preserved.
426c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    void SaveCallerSaveRegisters(MacroAssembler* masm, SaveFPRegsMode mode) {
427c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      masm->PushCallerSaved(mode, scratch0_, scratch1_, rcx);
428c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
429c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
430c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    inline void RestoreCallerSaveRegisters(MacroAssembler*masm,
431c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                           SaveFPRegsMode mode) {
432c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      masm->PopCallerSaved(mode, scratch0_, scratch1_, rcx);
433c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
434c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
435c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    inline Register object() { return object_; }
436c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    inline Register address() { return address_; }
437c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    inline Register scratch0() { return scratch0_; }
438c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    inline Register scratch1() { return scratch1_; }
439c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
440c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com   private:
441c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Register object_orig_;
442c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Register address_orig_;
443c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Register scratch0_orig_;
444c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Register object_;
445c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Register address_;
446c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Register scratch0_;
447c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Register scratch1_;
448c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Third scratch register is always rcx.
449c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
450c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Register GetRegThatIsNotRcxOr(Register r1,
451c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                  Register r2,
452c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                  Register r3) {
453a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      for (int i = 0; i < Register::NumAllocatableRegisters(); i++) {
454c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        Register candidate = Register::FromAllocationIndex(i);
455c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        if (candidate.is(rcx)) continue;
456c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        if (candidate.is(r1)) continue;
457c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        if (candidate.is(r2)) continue;
458c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        if (candidate.is(r3)) continue;
459c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        return candidate;
460c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      }
461c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      UNREACHABLE();
462c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      return no_reg;
463c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
464c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    friend class RecordWriteStub;
465c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  };
466c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
467c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  enum OnNoNeedToInformIncrementalMarker {
468c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    kReturnOnNoNeedToInformIncrementalMarker,
469c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    kUpdateRememberedSetOnNoNeedToInformIncrementalMarker
470c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  };
471c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
472c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void Generate(MacroAssembler* masm);
473c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void GenerateIncremental(MacroAssembler* masm, Mode mode);
474c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void CheckNeedsToInformIncrementalMarker(
475c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      MacroAssembler* masm,
476c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      OnNoNeedToInformIncrementalMarker on_no_need,
477c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Mode mode);
478c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void InformIncrementalMarker(MacroAssembler* masm, Mode mode);
479c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
480c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Major MajorKey() { return RecordWrite; }
481c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
482c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  int MinorKey() {
483c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    return ObjectBits::encode(object_.code()) |
484c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        ValueBits::encode(value_.code()) |
485c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        AddressBits::encode(address_.code()) |
486c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        RememberedSetActionBits::encode(remembered_set_action_) |
487c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        SaveFPRegsModeBits::encode(save_fp_regs_mode_);
488c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
489c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
490c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void Activate(Code* code) {
491c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    code->GetHeap()->incremental_marking()->ActivateGeneratedStub(code);
492c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
493c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
494c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  class ObjectBits: public BitField<int, 0, 4> {};
495c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  class ValueBits: public BitField<int, 4, 4> {};
496c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  class AddressBits: public BitField<int, 8, 4> {};
497c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  class RememberedSetActionBits: public BitField<RememberedSetAction, 12, 1> {};
498c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  class SaveFPRegsModeBits: public BitField<SaveFPRegsMode, 13, 1> {};
499c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
500c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Register object_;
501c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Register value_;
502c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Register address_;
503c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  RememberedSetAction remembered_set_action_;
504c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  SaveFPRegsMode save_fp_regs_mode_;
505c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Label slow_;
506c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  RegisterAllocation regs_;
507c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com};
508c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
509c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
51065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} }  // namespace v8::internal
51165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
51265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#endif  // V8_X64_CODE_STUBS_X64_H_
513