1257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved.
280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// Redistribution and use in source and binary forms, with or without
380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// modification, are permitted provided that the following conditions are
480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// met:
580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen//
680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen//     * Redistributions of source code must retain the above copyright
780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen//       notice, this list of conditions and the following disclaimer.
880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen//     * Redistributions in binary form must reproduce the above
980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen//       copyright notice, this list of conditions and the following
1080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen//       disclaimer in the documentation and/or other materials provided
1180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen//       with the distribution.
1280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen//     * Neither the name of Google Inc. nor the names of its
1380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen//       contributors may be used to endorse or promote products derived
1480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen//       from this software without specific prior written permission.
1580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen//
1680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#ifndef V8_ARM_CODE_STUBS_ARM_H_
2980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#define V8_ARM_CODE_STUBS_ARM_H_
3080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
3180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#include "ic-inl.h"
3280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
3380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsennamespace v8 {
3480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsennamespace internal {
3580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
3680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
3780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// Compute a transcendental math function natively, or call the
3880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// TranscendentalCache runtime function.
3980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenclass TranscendentalCacheStub: public CodeStub {
4080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen public:
41e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  enum ArgumentType {
42e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    TAGGED = 0 << TranscendentalCache::kTranscendentalTypeBits,
43e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    UNTAGGED = 1 << TranscendentalCache::kTranscendentalTypeBits
44e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  };
45e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
46e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  TranscendentalCacheStub(TranscendentalCache::Type type,
47e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                          ArgumentType argument_type)
48e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      : type_(type), argument_type_(argument_type) { }
4980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void Generate(MacroAssembler* masm);
5080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen private:
5180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  TranscendentalCache::Type type_;
52e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ArgumentType argument_type_;
53e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void GenerateCallCFunction(MacroAssembler* masm, Register scratch);
54e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
5580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Major MajorKey() { return TranscendentalCache; }
56e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int MinorKey() { return type_ | argument_type_; }
5780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Runtime::FunctionId RuntimeFunction();
5880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen};
5980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
6080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochclass StoreBufferOverflowStub: public CodeStub {
623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  explicit StoreBufferOverflowStub(SaveFPRegsMode save_fp)
643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : save_doubles_(save_fp) { }
653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Generate(MacroAssembler* masm);
673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual bool IsPregenerated();
693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void GenerateFixedRegStubsAheadOfTime();
703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual bool SometimesSetsUpAFrame() { return false; }
713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private:
733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SaveFPRegsMode save_doubles_;
743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Major MajorKey() { return StoreBufferOverflow; }
763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int MinorKey() { return (save_doubles_ == kSaveFPRegs) ? 1 : 0; }
773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
80257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass UnaryOpStub: public CodeStub {
811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block public:
823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  UnaryOpStub(Token::Value op,
833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch              UnaryOverwriteMode mode,
843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch              UnaryOpIC::TypeInfo operand_type = UnaryOpIC::UNINITIALIZED)
851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      : op_(op),
861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        mode_(mode),
873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        operand_type_(operand_type) {
88257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
89257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
90257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private:
91257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Token::Value op_;
92257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  UnaryOverwriteMode mode_;
93257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
94257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Operand type information determined at runtime.
95257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  UnaryOpIC::TypeInfo operand_type_;
96257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  virtual void PrintName(StringStream* stream);
98257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
99257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  class ModeBits: public BitField<UnaryOverwriteMode, 0, 1> {};
100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  class OpBits: public BitField<Token::Value, 1, 7> {};
101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  class OperandTypeInfoBits: public BitField<UnaryOpIC::TypeInfo, 8, 3> {};
102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Major MajorKey() { return UnaryOp; }
104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int MinorKey() {
105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return ModeBits::encode(mode_)
106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch           | OpBits::encode(op_)
107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch           | OperandTypeInfoBits::encode(operand_type_);
108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Note: A lot of the helper functions below will vanish when we use virtual
111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // function instead of switch more often.
112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void Generate(MacroAssembler* masm);
113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateTypeTransition(MacroAssembler* masm);
115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateSmiStub(MacroAssembler* masm);
117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateSmiStubSub(MacroAssembler* masm);
118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateSmiStubBitNot(MacroAssembler* masm);
119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateSmiCodeSub(MacroAssembler* masm, Label* non_smi, Label* slow);
120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateSmiCodeBitNot(MacroAssembler* masm, Label* slow);
121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateHeapNumberStub(MacroAssembler* masm);
123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateHeapNumberStubSub(MacroAssembler* masm);
124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateHeapNumberStubBitNot(MacroAssembler* masm);
125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateHeapNumberCodeSub(MacroAssembler* masm, Label* slow);
126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateHeapNumberCodeBitNot(MacroAssembler* masm, Label* slow);
127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateGenericStub(MacroAssembler* masm);
129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateGenericStubSub(MacroAssembler* masm);
130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateGenericStubBitNot(MacroAssembler* masm);
131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateGenericCodeFallback(MacroAssembler* masm);
132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  virtual int GetCodeKind() { return Code::UNARY_OP_IC; }
134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  virtual InlineCacheState GetICState() {
136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return UnaryOpIC::ToState(operand_type_);
137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual void FinishCode(Handle<Code> code) {
140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    code->set_unary_op_type(operand_type_);
141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch};
143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
145257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass BinaryOpStub: public CodeStub {
146257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch public:
147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  BinaryOpStub(Token::Value op, OverwriteMode mode)
148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : op_(op),
149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        mode_(mode),
150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        operands_type_(BinaryOpIC::UNINITIALIZED),
1513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        result_type_(BinaryOpIC::UNINITIALIZED) {
1528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    use_vfp3_ = CpuFeatures::IsSupported(VFP3);
1531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
1541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
1551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  BinaryOpStub(
1571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      int key,
158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      BinaryOpIC::TypeInfo operands_type,
159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      BinaryOpIC::TypeInfo result_type = BinaryOpIC::UNINITIALIZED)
1601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      : op_(OpBits::decode(key)),
1611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        mode_(ModeBits::decode(key)),
1621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        use_vfp3_(VFP3Bits::decode(key)),
1631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        operands_type_(operands_type),
1643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        result_type_(result_type) { }
1651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block private:
1671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  enum SmiCodeGenerateHeapNumberResults {
1681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ALLOW_HEAPNUMBER_RESULTS,
1691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    NO_HEAPNUMBER_RESULTS
1701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  };
1711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Token::Value op_;
1731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  OverwriteMode mode_;
1741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool use_vfp3_;
1751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Operand type information determined at runtime.
177257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  BinaryOpIC::TypeInfo operands_type_;
178257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  BinaryOpIC::TypeInfo result_type_;
1791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  virtual void PrintName(StringStream* stream);
1811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Minor key encoding in 16 bits RRRTTTVOOOOOOOMM.
1831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  class ModeBits: public BitField<OverwriteMode, 0, 2> {};
1841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  class OpBits: public BitField<Token::Value, 2, 7> {};
1851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  class VFP3Bits: public BitField<bool, 9, 1> {};
186257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  class OperandTypeInfoBits: public BitField<BinaryOpIC::TypeInfo, 10, 3> {};
187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  class ResultTypeInfoBits: public BitField<BinaryOpIC::TypeInfo, 13, 3> {};
1881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
189257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Major MajorKey() { return BinaryOp; }
1901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int MinorKey() {
1911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return OpBits::encode(op_)
1921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block           | ModeBits::encode(mode_)
1931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block           | VFP3Bits::encode(use_vfp3_)
1941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block           | OperandTypeInfoBits::encode(operands_type_)
1951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block           | ResultTypeInfoBits::encode(result_type_);
1961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
1971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void Generate(MacroAssembler* masm);
1991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void GenerateGeneric(MacroAssembler* masm);
2001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void GenerateSmiSmiOperation(MacroAssembler* masm);
2011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void GenerateFPOperation(MacroAssembler* masm,
2021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                           bool smi_operands,
2031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                           Label* not_numbers,
2041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                           Label* gc_required);
2051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void GenerateSmiCode(MacroAssembler* masm,
2068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                       Label* use_runtime,
2071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                       Label* gc_required,
2081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                       SmiCodeGenerateHeapNumberResults heapnumber_results);
2091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void GenerateLoadArguments(MacroAssembler* masm);
2101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void GenerateReturn(MacroAssembler* masm);
2111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void GenerateUninitializedStub(MacroAssembler* masm);
2121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void GenerateSmiStub(MacroAssembler* masm);
2131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void GenerateInt32Stub(MacroAssembler* masm);
2141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void GenerateHeapNumberStub(MacroAssembler* masm);
21544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void GenerateOddballStub(MacroAssembler* masm);
2161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void GenerateStringStub(MacroAssembler* masm);
217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateBothStringStub(MacroAssembler* masm);
2181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void GenerateGenericStub(MacroAssembler* masm);
2191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void GenerateAddStrings(MacroAssembler* masm);
2201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void GenerateCallRuntime(MacroAssembler* masm);
2211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void GenerateHeapResultAllocation(MacroAssembler* masm,
2231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                    Register result,
2241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                    Register heap_number_map,
2251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                    Register scratch1,
2261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                    Register scratch2,
2271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                    Label* gc_required);
2281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void GenerateRegisterArgsPush(MacroAssembler* masm);
2291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void GenerateTypeTransition(MacroAssembler* masm);
2301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void GenerateTypeTransitionWithSavedArgs(MacroAssembler* masm);
2311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  virtual int GetCodeKind() { return Code::BINARY_OP_IC; }
2331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  virtual InlineCacheState GetICState() {
235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return BinaryOpIC::ToState(operands_type_);
2361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
2371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual void FinishCode(Handle<Code> code) {
239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    code->set_binary_op_type(operands_type_);
240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    code->set_binary_op_result_type(result_type_);
2411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
2421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  friend class CodeGenerator;
2441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block};
2451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
247692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdochclass StringHelper : public AllStatic {
248692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch public:
249692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  // Generate code for copying characters using a simple loop. This should only
250692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  // be used in places where the number of characters is small and the
251692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  // additional setup and checking in GenerateCopyCharactersLong adds too much
252692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  // overhead. Copying of overlapping regions is not supported.
253692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  // Dest register ends at the position after the last character written.
254692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  static void GenerateCopyCharacters(MacroAssembler* masm,
255692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch                                     Register dest,
256692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch                                     Register src,
257692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch                                     Register count,
258692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch                                     Register scratch,
259692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch                                     bool ascii);
260692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch
261692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  // Generate code for copying a large number of characters. This function
262692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  // is allowed to spend extra time setting up conditions to make copying
263692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  // faster. Copying of overlapping regions is not supported.
264692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  // Dest register ends at the position after the last character written.
265692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  static void GenerateCopyCharactersLong(MacroAssembler* masm,
266692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch                                         Register dest,
267692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch                                         Register src,
268692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch                                         Register count,
269692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch                                         Register scratch1,
270692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch                                         Register scratch2,
271692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch                                         Register scratch3,
272692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch                                         Register scratch4,
273692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch                                         Register scratch5,
274692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch                                         int flags);
275692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch
276692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch
277692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  // Probe the symbol table for a two character string. If the string is
278692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  // not found by probing a jump to the label not_found is performed. This jump
279692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  // does not guarantee that the string is not in the symbol table. If the
280692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  // string is found the code falls through with the string in register r0.
281692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  // Contents of both c1 and c2 registers are modified. At the exit c1 is
282692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  // guaranteed to contain halfword with low and high bytes equal to
283692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  // initial contents of c1 and c2 respectively.
284692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  static void GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
285692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch                                                   Register c1,
286692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch                                                   Register c2,
287692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch                                                   Register scratch1,
288692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch                                                   Register scratch2,
289692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch                                                   Register scratch3,
290692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch                                                   Register scratch4,
291692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch                                                   Register scratch5,
292692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch                                                   Label* not_found);
293692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch
294692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  // Generate string hash.
295692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  static void GenerateHashInit(MacroAssembler* masm,
296692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch                               Register hash,
297692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch                               Register character);
298692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch
299692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  static void GenerateHashAddCharacter(MacroAssembler* masm,
300692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch                                       Register hash,
301692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch                                       Register character);
302692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch
303692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  static void GenerateHashGetHash(MacroAssembler* masm,
304692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch                                  Register hash);
305692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch
306692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch private:
307692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper);
308692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch};
309692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch
310692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch
31180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// Flag that indicates how to generate code for the stub StringAddStub.
31280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenenum StringAddFlags {
31380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  NO_STRING_ADD_FLAGS = 0,
314e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Omit left string check in stub (left is definitely a string).
315e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  NO_STRING_CHECK_LEFT_IN_STUB = 1 << 0,
316e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Omit right string check in stub (right is definitely a string).
317e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  NO_STRING_CHECK_RIGHT_IN_STUB = 1 << 1,
318e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Omit both string checks in stub.
319e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  NO_STRING_CHECK_IN_STUB =
320e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      NO_STRING_CHECK_LEFT_IN_STUB | NO_STRING_CHECK_RIGHT_IN_STUB
32180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen};
32280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
32380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
32480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenclass StringAddStub: public CodeStub {
32580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen public:
326e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  explicit StringAddStub(StringAddFlags flags) : flags_(flags) {}
32780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
32880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen private:
32980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Major MajorKey() { return StringAdd; }
330e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int MinorKey() { return flags_; }
33180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
33280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void Generate(MacroAssembler* masm);
33380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
334e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void GenerateConvertArgument(MacroAssembler* masm,
335e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                               int stack_offset,
336e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                               Register arg,
337e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                               Register scratch1,
338e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                               Register scratch2,
339e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                               Register scratch3,
340e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                               Register scratch4,
341e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                               Label* slow);
342e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
343e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  const StringAddFlags flags_;
34480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen};
34580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
34680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
34780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenclass SubStringStub: public CodeStub {
34880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen public:
34980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  SubStringStub() {}
35080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
35180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen private:
35280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Major MajorKey() { return SubString; }
35380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int MinorKey() { return 0; }
35480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
35580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void Generate(MacroAssembler* masm);
35680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen};
35780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
35880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
35980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
36080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenclass StringCompareStub: public CodeStub {
36180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen public:
36280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  StringCompareStub() { }
36380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
364257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Compares two flat ASCII strings and returns result in r0.
36580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  static void GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
36680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              Register left,
36780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              Register right,
36880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              Register scratch1,
36980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              Register scratch2,
37080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              Register scratch3,
37180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              Register scratch4);
37280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
373257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Compares two flat ASCII strings for equality and returns result
374257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // in r0.
375257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void GenerateFlatAsciiStringEquals(MacroAssembler* masm,
376257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                            Register left,
377257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                            Register right,
378257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                            Register scratch1,
379257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                            Register scratch2,
380257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                            Register scratch3);
38180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
382257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private:
383257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  virtual Major MajorKey() { return StringCompare; }
384257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  virtual int MinorKey() { return 0; }
385257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  virtual void Generate(MacroAssembler* masm);
386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
387257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void GenerateAsciiCharsCompareLoop(MacroAssembler* masm,
388257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                            Register left,
389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                            Register right,
390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                            Register length,
391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                            Register scratch1,
392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                            Register scratch2,
393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                            Label* chars_not_equal);
39480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen};
39580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
39680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
39780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// This stub can convert a signed int32 to a heap number (double).  It does
39880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// not work for int32s that are in Smi range!  No GC occurs during this stub
39980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// so you don't have to set up the frame.
40080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenclass WriteInt32ToHeapNumberStub : public CodeStub {
40180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen public:
40280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  WriteInt32ToHeapNumberStub(Register the_int,
40380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                             Register the_heap_number,
40480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                             Register scratch)
40580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      : the_int_(the_int),
40680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        the_heap_number_(the_heap_number),
40780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        scratch_(scratch) { }
40880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool IsPregenerated();
4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void GenerateFixedRegStubsAheadOfTime();
4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen private:
41380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register the_int_;
41480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register the_heap_number_;
41580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register scratch_;
41680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
41780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Minor key encoding in 16 bits.
41880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  class IntRegisterBits: public BitField<int, 0, 4> {};
41980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  class HeapNumberRegisterBits: public BitField<int, 4, 4> {};
42080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  class ScratchRegisterBits: public BitField<int, 8, 4> {};
42180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
42280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Major MajorKey() { return WriteInt32ToHeapNumber; }
42380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int MinorKey() {
42480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Encode the parameters in a unique 16 bit value.
42580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    return IntRegisterBits::encode(the_int_.code())
42680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen           | HeapNumberRegisterBits::encode(the_heap_number_.code())
42780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen           | ScratchRegisterBits::encode(scratch_.code());
42880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
42980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
43080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void Generate(MacroAssembler* masm);
43180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen};
43280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
43380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
43480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenclass NumberToStringStub: public CodeStub {
43580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen public:
43680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  NumberToStringStub() { }
43780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
43880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Generate code to do a lookup in the number string cache. If the number in
43980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // the register object is found in the cache the generated code falls through
44080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // with the result in the result register. The object and the result register
44180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // can be the same. If the number is not found in the cache the code jumps to
44280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // the label not_found with only the content of register object unchanged.
44380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  static void GenerateLookupNumberStringCache(MacroAssembler* masm,
44480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              Register object,
44580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              Register result,
44680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              Register scratch1,
44780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              Register scratch2,
44880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              Register scratch3,
44980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              bool object_is_smi,
45080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              Label* not_found);
45180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
45280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen private:
45380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Major MajorKey() { return NumberToString; }
45480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int MinorKey() { return 0; }
45580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
45680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void Generate(MacroAssembler* masm);
45780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen};
45880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
45980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
4603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochclass RecordWriteStub: public CodeStub {
4613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
4623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordWriteStub(Register object,
4633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  Register value,
4643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  Register address,
4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  RememberedSetAction remembered_set_action,
4663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  SaveFPRegsMode fp_mode)
4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : object_(object),
4683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        value_(value),
4693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        address_(address),
4703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        remembered_set_action_(remembered_set_action),
4713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        save_fp_regs_mode_(fp_mode),
4723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        regs_(object,   // An input reg.
4733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              address,  // An input reg.
4743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              value) {  // One scratch reg.
4753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  enum Mode {
4783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    STORE_BUFFER_ONLY,
4793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    INCREMENTAL,
4803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    INCREMENTAL_COMPACTION
4813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
4823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual bool IsPregenerated();
4843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void GenerateFixedRegStubsAheadOfTime();
4853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual bool SometimesSetsUpAFrame() { return false; }
4863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void PatchBranchIntoNop(MacroAssembler* masm, int pos) {
4883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    masm->instr_at_put(pos, (masm->instr_at(pos) & ~B27) | (B24 | B20));
4893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(Assembler::IsTstImmediate(masm->instr_at(pos)));
4903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void PatchNopIntoBranch(MacroAssembler* masm, int pos) {
4933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    masm->instr_at_put(pos, (masm->instr_at(pos) & ~(B24 | B20)) | B27);
4943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(Assembler::IsBranch(masm->instr_at(pos)));
4953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static Mode GetMode(Code* stub) {
4983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Instr first_instruction = Assembler::instr_at(stub->instruction_start());
4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Instr second_instruction = Assembler::instr_at(stub->instruction_start() +
5003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Assembler::kInstrSize);
5013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (Assembler::IsBranch(first_instruction)) {
5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return INCREMENTAL;
5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(Assembler::IsTstImmediate(first_instruction));
5073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (Assembler::IsBranch(second_instruction)) {
5093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return INCREMENTAL_COMPACTION;
5103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(Assembler::IsTstImmediate(second_instruction));
5133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return STORE_BUFFER_ONLY;
5153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void Patch(Code* stub, Mode mode) {
5183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MacroAssembler masm(NULL,
5193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        stub->instruction_start(),
5203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        stub->instruction_size());
5213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    switch (mode) {
5223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case STORE_BUFFER_ONLY:
5233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(GetMode(stub) == INCREMENTAL ||
5243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               GetMode(stub) == INCREMENTAL_COMPACTION);
5253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        PatchBranchIntoNop(&masm, 0);
5263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        PatchBranchIntoNop(&masm, Assembler::kInstrSize);
5273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
5283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case INCREMENTAL:
5293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(GetMode(stub) == STORE_BUFFER_ONLY);
5303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        PatchNopIntoBranch(&masm, 0);
5313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
5323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case INCREMENTAL_COMPACTION:
5333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(GetMode(stub) == STORE_BUFFER_ONLY);
5343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        PatchNopIntoBranch(&masm, Assembler::kInstrSize);
5353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
5363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(GetMode(stub) == mode);
5383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CPU::FlushICache(stub->instruction_start(), 2 * Assembler::kInstrSize);
5393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private:
5423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // This is a helper class for freeing up 3 scratch registers.  The input is
5433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // two registers that must be preserved and one scratch register provided by
5443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the caller.
5453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  class RegisterAllocation {
5463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   public:
5473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RegisterAllocation(Register object,
5483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       Register address,
5493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       Register scratch0)
5503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : object_(object),
5513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          address_(address),
5523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          scratch0_(scratch0) {
5533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(!AreAliased(scratch0, object, address, no_reg));
5543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      scratch1_ = GetRegThatIsNotOneOf(object_, address_, scratch0_);
5553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    void Save(MacroAssembler* masm) {
5583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(!AreAliased(object_, address_, scratch1_, scratch0_));
5593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // We don't have to save scratch0_ because it was given to us as
5603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // a scratch register.
5613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      masm->push(scratch1_);
5623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    void Restore(MacroAssembler* masm) {
5653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      masm->pop(scratch1_);
5663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // If we have to call into C then we need to save and restore all caller-
5693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // saved registers that were not already preserved.  The scratch registers
5703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // will be restored by other means so we don't bother pushing them here.
5713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    void SaveCallerSaveRegisters(MacroAssembler* masm, SaveFPRegsMode mode) {
5723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      masm->stm(db_w, sp, (kCallerSaved | lr.bit()) & ~scratch1_.bit());
5733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (mode == kSaveFPRegs) {
5743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CpuFeatures::Scope scope(VFP3);
5753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        masm->sub(sp,
5763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  sp,
5773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  Operand(kDoubleSize * (DwVfpRegister::kNumRegisters - 1)));
5783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Save all VFP registers except d0.
5793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        for (int i = DwVfpRegister::kNumRegisters - 1; i > 0; i--) {
5803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          DwVfpRegister reg = DwVfpRegister::from_code(i);
5813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          masm->vstr(reg, MemOperand(sp, (i - 1) * kDoubleSize));
5823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
5833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
5843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    inline void RestoreCallerSaveRegisters(MacroAssembler*masm,
5873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           SaveFPRegsMode mode) {
5883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (mode == kSaveFPRegs) {
5893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CpuFeatures::Scope scope(VFP3);
5903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Restore all VFP registers except d0.
5913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        for (int i = DwVfpRegister::kNumRegisters - 1; i > 0; i--) {
5923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          DwVfpRegister reg = DwVfpRegister::from_code(i);
5933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          masm->vldr(reg, MemOperand(sp, (i - 1) * kDoubleSize));
5943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
5953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        masm->add(sp,
5963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  sp,
5973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  Operand(kDoubleSize * (DwVfpRegister::kNumRegisters - 1)));
5983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
5993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      masm->ldm(ia_w, sp, (kCallerSaved | lr.bit()) & ~scratch1_.bit());
6003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
6013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    inline Register object() { return object_; }
6033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    inline Register address() { return address_; }
6043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    inline Register scratch0() { return scratch0_; }
6053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    inline Register scratch1() { return scratch1_; }
6063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   private:
6083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register object_;
6093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register address_;
6103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch0_;
6113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch1_;
6123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register GetRegThatIsNotOneOf(Register r1,
6143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  Register r2,
6153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  Register r3) {
6163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      for (int i = 0; i < Register::kNumAllocatableRegisters; i++) {
6173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Register candidate = Register::FromAllocationIndex(i);
6183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (candidate.is(r1)) continue;
6193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (candidate.is(r2)) continue;
6203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (candidate.is(r3)) continue;
6213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return candidate;
6223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
6233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      UNREACHABLE();
6243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return no_reg;
6253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
6263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    friend class RecordWriteStub;
6273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
6283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  enum OnNoNeedToInformIncrementalMarker {
6303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    kReturnOnNoNeedToInformIncrementalMarker,
6313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    kUpdateRememberedSetOnNoNeedToInformIncrementalMarker
6323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
6333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Generate(MacroAssembler* masm);
6353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void GenerateIncremental(MacroAssembler* masm, Mode mode);
6363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CheckNeedsToInformIncrementalMarker(
6373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      MacroAssembler* masm,
6383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      OnNoNeedToInformIncrementalMarker on_no_need,
6393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Mode mode);
6403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void InformIncrementalMarker(MacroAssembler* masm, Mode mode);
6413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Major MajorKey() { return RecordWrite; }
6433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int MinorKey() {
6453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return ObjectBits::encode(object_.code()) |
6463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ValueBits::encode(value_.code()) |
6473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        AddressBits::encode(address_.code()) |
6483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        RememberedSetActionBits::encode(remembered_set_action_) |
6493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        SaveFPRegsModeBits::encode(save_fp_regs_mode_);
6503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
6513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Activate(Code* code) {
6533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    code->GetHeap()->incremental_marking()->ActivateGeneratedStub(code);
6543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
6553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  class ObjectBits: public BitField<int, 0, 4> {};
6573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  class ValueBits: public BitField<int, 4, 4> {};
6583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  class AddressBits: public BitField<int, 8, 4> {};
6593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  class RememberedSetActionBits: public BitField<RememberedSetAction, 12, 1> {};
6603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  class SaveFPRegsModeBits: public BitField<SaveFPRegsMode, 13, 1> {};
6613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register object_;
6633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register value_;
6643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register address_;
6653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RememberedSetAction remembered_set_action_;
6663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SaveFPRegsMode save_fp_regs_mode_;
6673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label slow_;
6683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RegisterAllocation regs_;
6693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
6703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
67280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// Enter C code from generated RegExp code in a way that allows
67380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// the C code to fix the return address in case of a GC.
67480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// Currently only needed on ARM.
67580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenclass RegExpCEntryStub: public CodeStub {
67680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen public:
67780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  RegExpCEntryStub() {}
67880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  virtual ~RegExpCEntryStub() {}
67980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void Generate(MacroAssembler* masm);
68080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
68180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen private:
68280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Major MajorKey() { return RegExpCEntry; }
68380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int MinorKey() { return 0; }
68444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
68544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bool NeedsImmovableCode() { return true; }
68680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen};
68780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
68880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
6891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Trampoline stub to call into native code. To call safely into native code
6901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// in the presence of compacting GC (which can move code objects) we need to
6911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// keep the code which called into native pinned in the memory. Currently the
6921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// simplest approach is to generate such stub early enough so it can never be
6931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// moved by GC
6941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockclass DirectCEntryStub: public CodeStub {
6951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block public:
6961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  DirectCEntryStub() {}
6971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void Generate(MacroAssembler* masm);
698e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void GenerateCall(MacroAssembler* masm, ExternalReference function);
699e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void GenerateCall(MacroAssembler* masm, Register target);
7001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
7011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block private:
7021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Major MajorKey() { return DirectCEntry; }
7031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int MinorKey() { return 0; }
70444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
70544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bool NeedsImmovableCode() { return true; }
7061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block};
7071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
7081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass FloatingPointHelper : public AllStatic {
710257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch public:
711257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  enum Destination {
712257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    kVFPRegisters,
713257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    kCoreRegisters
714257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  };
715257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
716257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
717257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Loads smis from r0 and r1 (right and left in binary operations) into
718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // floating point registers. Depending on the destination the values ends up
719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // either d7 and d6 or in r2/r3 and r0/r1 respectively. If the destination is
720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // floating point registers VFP3 must be supported. If core registers are
721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // requested when VFP3 is supported d6 and d7 will be scratched.
722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void LoadSmis(MacroAssembler* masm,
723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                       Destination destination,
724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                       Register scratch1,
725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                       Register scratch2);
726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
727257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Loads objects from r0 and r1 (right and left in binary operations) into
728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // floating point registers. Depending on the destination the values ends up
729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // either d7 and d6 or in r2/r3 and r0/r1 respectively. If the destination is
730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // floating point registers VFP3 must be supported. If core registers are
731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // requested when VFP3 is supported d6 and d7 will still be scratched. If
732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // either r0 or r1 is not a number (not smi and not heap number object) the
733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // not_number label is jumped to with r0 and r1 intact.
734257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void LoadOperands(MacroAssembler* masm,
735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                           FloatingPointHelper::Destination destination,
736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                           Register heap_number_map,
737257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                           Register scratch1,
738257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                           Register scratch2,
739257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                           Label* not_number);
740257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
741257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Convert the smi or heap number in object to an int32 using the rules
742257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // for ToInt32 as described in ECMAScript 9.5.: the value is truncated
743257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // and brought into the range -2^31 .. +2^31 - 1.
744257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void ConvertNumberToInt32(MacroAssembler* masm,
745257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   Register object,
746257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   Register dst,
747257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   Register heap_number_map,
748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   Register scratch1,
749257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   Register scratch2,
750257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   Register scratch3,
751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   DwVfpRegister double_scratch,
752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   Label* not_int32);
753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
754257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Converts the integer (untagged smi) in |int_scratch| to a double, storing
755257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // the result either in |double_dst| or |dst2:dst1|, depending on
756257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // |destination|.
757257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Warning: The value in |int_scratch| will be changed in the process!
758257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void ConvertIntToDouble(MacroAssembler* masm,
759257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Register int_scratch,
760257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Destination destination,
761257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 DwVfpRegister double_dst,
762257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Register dst1,
763257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Register dst2,
764257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Register scratch2,
765257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 SwVfpRegister single_scratch);
766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load the number from object into double_dst in the double format.
768257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Control will jump to not_int32 if the value cannot be exactly represented
769257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // by a 32-bit integer.
770257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Floating point value in the 32-bit integer range that are not exact integer
771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // won't be loaded.
772257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void LoadNumberAsInt32Double(MacroAssembler* masm,
773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                      Register object,
774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                      Destination destination,
775257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                      DwVfpRegister double_dst,
776257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                      Register dst1,
777257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                      Register dst2,
778257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                      Register heap_number_map,
779257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                      Register scratch1,
780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                      Register scratch2,
781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                      SwVfpRegister single_scratch,
782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                      Label* not_int32);
783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
784257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Loads the number from object into dst as a 32-bit integer.
785257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Control will jump to not_int32 if the object cannot be exactly represented
786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // by a 32-bit integer.
787257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Floating point value in the 32-bit integer range that are not exact integer
788257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // won't be converted.
789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // scratch3 is not used when VFP3 is supported.
790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void LoadNumberAsInt32(MacroAssembler* masm,
791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Register object,
792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Register dst,
793257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Register heap_number_map,
794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Register scratch1,
795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Register scratch2,
796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Register scratch3,
797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                DwVfpRegister double_scratch,
798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Label* not_int32);
799257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Generate non VFP3 code to check if a double can be exactly represented by a
801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // 32-bit integer. This does not check for 0 or -0, which need
802257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // to be checked for separately.
803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Control jumps to not_int32 if the value is not a 32-bit integer, and falls
804257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // through otherwise.
805257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // src1 and src2 will be cloberred.
806257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //
807257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Expected input:
808257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // - src1: higher (exponent) part of the double value.
809257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // - src2: lower (mantissa) part of the double value.
810257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Output status:
811257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // - dst: 32 higher bits of the mantissa. (mantissa[51:20])
812257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // - src2: contains 1.
813257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // - other registers are clobbered.
814257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void DoubleIs32BitInteger(MacroAssembler* masm,
815257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   Register src1,
816257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   Register src2,
817257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   Register dst,
818257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   Register scratch,
819257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   Label* not_int32);
820257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
821257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Generates code to call a C function to do a double operation using core
822257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // registers. (Used when VFP3 is not supported.)
823257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This code never falls through, but returns with a heap number containing
824257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // the result in r0.
825257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Register heapnumber_result must be a heap number in which the
826257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // result of the operation will be stored.
827257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Requires the following layout on entry:
828257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // r0: Left value (least significant part of mantissa).
829257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // r1: Left value (sign, exponent, top of mantissa).
830257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // r2: Right value (least significant part of mantissa).
831257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // r3: Right value (sign, exponent, top of mantissa).
832257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void CallCCodeForDoubleOperation(MacroAssembler* masm,
833257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                          Token::Value op,
834257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                          Register heap_number_result,
835257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                          Register scratch);
836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
837257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private:
838257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void LoadNumber(MacroAssembler* masm,
839257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                         FloatingPointHelper::Destination destination,
840257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                         Register object,
841257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                         DwVfpRegister dst,
842257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                         Register dst1,
843257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                         Register dst2,
844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                         Register heap_number_map,
845257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                         Register scratch1,
846257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                         Register scratch2,
847257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                         Label* not_number);
848257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch};
849257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
850257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
851257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass StringDictionaryLookupStub: public CodeStub {
852257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch public:
853257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  enum LookupMode { POSITIVE_LOOKUP, NEGATIVE_LOOKUP };
854257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
855257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  explicit StringDictionaryLookupStub(LookupMode mode) : mode_(mode) { }
856257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
857257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void Generate(MacroAssembler* masm);
858257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
8593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void GenerateNegativeLookup(MacroAssembler* masm,
8603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Label* miss,
8613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Label* done,
8623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Register receiver,
8633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Register properties,
8643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Handle<String> name,
8653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Register scratch0);
866257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
867257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void GeneratePositiveLookup(MacroAssembler* masm,
868257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Label* miss,
869257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Label* done,
870257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Register elements,
871257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Register name,
872257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Register r0,
873257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Register r1);
874257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
8753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual bool SometimesSetsUpAFrame() { return false; }
8763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
877257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private:
878257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static const int kInlinedProbes = 4;
879257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static const int kTotalProbes = 20;
880257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
881257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static const int kCapacityOffset =
882257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      StringDictionary::kHeaderSize +
883257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      StringDictionary::kCapacityIndex * kPointerSize;
884257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
885257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static const int kElementsStartOffset =
886257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      StringDictionary::kHeaderSize +
887257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      StringDictionary::kElementsStartIndex * kPointerSize;
888257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
8893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Major MajorKey() { return StringDictionaryLookup; }
890257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
891257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int MinorKey() {
892257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return LookupModeBits::encode(mode_);
893257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
894257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
895257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  class LookupModeBits: public BitField<LookupMode, 0, 1> {};
896257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
897257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  LookupMode mode_;
898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch};
899257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
900257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
90180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} }  // namespace v8::internal
90280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
90380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#endif  // V8_ARM_CODE_STUBS_ARM_H_
904