1257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved.
244f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Redistribution and use in source and binary forms, with or without
344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// modification, are permitted provided that the following conditions are
444f0eee88ff00398ff7f715fab053374d808c90dSteve Block// met:
544f0eee88ff00398ff7f715fab053374d808c90dSteve Block//
644f0eee88ff00398ff7f715fab053374d808c90dSteve Block//     * Redistributions of source code must retain the above copyright
744f0eee88ff00398ff7f715fab053374d808c90dSteve Block//       notice, this list of conditions and the following disclaimer.
844f0eee88ff00398ff7f715fab053374d808c90dSteve Block//     * Redistributions in binary form must reproduce the above
944f0eee88ff00398ff7f715fab053374d808c90dSteve Block//       copyright notice, this list of conditions and the following
1044f0eee88ff00398ff7f715fab053374d808c90dSteve Block//       disclaimer in the documentation and/or other materials provided
1144f0eee88ff00398ff7f715fab053374d808c90dSteve Block//       with the distribution.
1244f0eee88ff00398ff7f715fab053374d808c90dSteve Block//     * Neither the name of Google Inc. nor the names of its
1344f0eee88ff00398ff7f715fab053374d808c90dSteve Block//       contributors may be used to endorse or promote products derived
1444f0eee88ff00398ff7f715fab053374d808c90dSteve Block//       from this software without specific prior written permission.
1544f0eee88ff00398ff7f715fab053374d808c90dSteve Block//
1644f0eee88ff00398ff7f715fab053374d808c90dSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1744f0eee88ff00398ff7f715fab053374d808c90dSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1844f0eee88ff00398ff7f715fab053374d808c90dSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1944f0eee88ff00398ff7f715fab053374d808c90dSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2044f0eee88ff00398ff7f715fab053374d808c90dSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2144f0eee88ff00398ff7f715fab053374d808c90dSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2244f0eee88ff00398ff7f715fab053374d808c90dSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2444f0eee88ff00398ff7f715fab053374d808c90dSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2544f0eee88ff00398ff7f715fab053374d808c90dSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2644f0eee88ff00398ff7f715fab053374d808c90dSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifndef V8_MIPS_CODE_STUBS_ARM_H_
2944f0eee88ff00398ff7f715fab053374d808c90dSteve Block#define V8_MIPS_CODE_STUBS_ARM_H_
3044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3144f0eee88ff00398ff7f715fab053374d808c90dSteve Block#include "ic-inl.h"
3244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3444f0eee88ff00398ff7f715fab053374d808c90dSteve Blocknamespace v8 {
3544f0eee88ff00398ff7f715fab053374d808c90dSteve Blocknamespace internal {
3644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3844f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Compute a transcendental math function natively, or call the
3944f0eee88ff00398ff7f715fab053374d808c90dSteve Block// TranscendentalCache runtime function.
4044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass TranscendentalCacheStub: public CodeStub {
4144f0eee88ff00398ff7f715fab053374d808c90dSteve Block public:
42257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  enum ArgumentType {
43257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    TAGGED = 0 << TranscendentalCache::kTranscendentalTypeBits,
44257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    UNTAGGED = 1 << TranscendentalCache::kTranscendentalTypeBits
45257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  };
46257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
47257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  TranscendentalCacheStub(TranscendentalCache::Type type,
48257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                          ArgumentType argument_type)
49257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : type_(type), argument_type_(argument_type) { }
5044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void Generate(MacroAssembler* masm);
5144f0eee88ff00398ff7f715fab053374d808c90dSteve Block private:
5244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  TranscendentalCache::Type type_;
53257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ArgumentType argument_type_;
54257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateCallCFunction(MacroAssembler* masm, Register scratch);
55257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
5644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Major MajorKey() { return TranscendentalCache; }
57257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int MinorKey() { return type_ | argument_type_; }
5844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Runtime::FunctionId RuntimeFunction();
5944f0eee88ff00398ff7f715fab053374d808c90dSteve Block};
6044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochclass StoreBufferOverflowStub: public CodeStub {
633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  explicit StoreBufferOverflowStub(SaveFPRegsMode save_fp)
653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : save_doubles_(save_fp) { }
663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Generate(MacroAssembler* masm);
683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual bool IsPregenerated();
703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void GenerateFixedRegStubsAheadOfTime();
713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual bool SometimesSetsUpAFrame() { return false; }
723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private:
743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SaveFPRegsMode save_doubles_;
753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Major MajorKey() { return StoreBufferOverflow; }
773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int MinorKey() { return (save_doubles_ == kSaveFPRegs) ? 1 : 0; }
783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
81257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass UnaryOpStub: public CodeStub {
8244f0eee88ff00398ff7f715fab053374d808c90dSteve Block public:
833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  UnaryOpStub(Token::Value op,
843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch              UnaryOverwriteMode mode,
853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch              UnaryOpIC::TypeInfo operand_type = UnaryOpIC::UNINITIALIZED)
8644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : op_(op),
8744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        mode_(mode),
883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        operand_type_(operand_type) {
89257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
9044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
9144f0eee88ff00398ff7f715fab053374d808c90dSteve Block private:
9244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Token::Value op_;
93257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  UnaryOverwriteMode mode_;
9444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
95257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Operand type information determined at runtime.
96257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  UnaryOpIC::TypeInfo operand_type_;
9744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  virtual void PrintName(StringStream* stream);
9944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  class ModeBits: public BitField<UnaryOverwriteMode, 0, 1> {};
101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  class OpBits: public BitField<Token::Value, 1, 7> {};
102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  class OperandTypeInfoBits: public BitField<UnaryOpIC::TypeInfo, 8, 3> {};
10344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Major MajorKey() { return UnaryOp; }
105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int MinorKey() {
106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return ModeBits::encode(mode_)
107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch           | OpBits::encode(op_)
108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch           | OperandTypeInfoBits::encode(operand_type_);
10944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
11044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Note: A lot of the helper functions below will vanish when we use virtual
112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // function instead of switch more often.
113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void Generate(MacroAssembler* masm);
11444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateTypeTransition(MacroAssembler* masm);
11644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateSmiStub(MacroAssembler* masm);
118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateSmiStubSub(MacroAssembler* masm);
119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateSmiStubBitNot(MacroAssembler* masm);
120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateSmiCodeSub(MacroAssembler* masm, Label* non_smi, Label* slow);
121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateSmiCodeBitNot(MacroAssembler* masm, Label* slow);
12244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateHeapNumberStub(MacroAssembler* masm);
124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateHeapNumberStubSub(MacroAssembler* masm);
125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateHeapNumberStubBitNot(MacroAssembler* masm);
126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateHeapNumberCodeSub(MacroAssembler* masm, Label* slow);
127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateHeapNumberCodeBitNot(MacroAssembler* masm, Label* slow);
12844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateGenericStub(MacroAssembler* masm);
130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateGenericStubSub(MacroAssembler* masm);
131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateGenericStubBitNot(MacroAssembler* masm);
132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateGenericCodeFallback(MacroAssembler* masm);
13344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  virtual int GetCodeKind() { return Code::UNARY_OP_IC; }
13544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
13644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  virtual InlineCacheState GetICState() {
137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return UnaryOpIC::ToState(operand_type_);
13844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
13944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual void FinishCode(Handle<Code> code) {
141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    code->set_unary_op_type(operand_type_);
14244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
14344f0eee88ff00398ff7f715fab053374d808c90dSteve Block};
14444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
145257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
146257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass BinaryOpStub: public CodeStub {
14744f0eee88ff00398ff7f715fab053374d808c90dSteve Block public:
148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  BinaryOpStub(Token::Value op, OverwriteMode mode)
14944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : op_(op),
15044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        mode_(mode),
151257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        operands_type_(BinaryOpIC::UNINITIALIZED),
1523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        result_type_(BinaryOpIC::UNINITIALIZED) {
153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    use_fpu_ = CpuFeatures::IsSupported(FPU);
154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
15544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
15644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  BinaryOpStub(
15844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      int key,
159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      BinaryOpIC::TypeInfo operands_type,
160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      BinaryOpIC::TypeInfo result_type = BinaryOpIC::UNINITIALIZED)
16144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : op_(OpBits::decode(key)),
16244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        mode_(ModeBits::decode(key)),
16344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        use_fpu_(FPUBits::decode(key)),
16444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        operands_type_(operands_type),
1653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        result_type_(result_type) { }
16644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
16744f0eee88ff00398ff7f715fab053374d808c90dSteve Block private:
16844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  enum SmiCodeGenerateHeapNumberResults {
16944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ALLOW_HEAPNUMBER_RESULTS,
17044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    NO_HEAPNUMBER_RESULTS
17144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  };
17244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
17344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Token::Value op_;
17444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  OverwriteMode mode_;
17544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bool use_fpu_;
17644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
17744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Operand type information determined at runtime.
178257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  BinaryOpIC::TypeInfo operands_type_;
179257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  BinaryOpIC::TypeInfo result_type_;
18044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  virtual void PrintName(StringStream* stream);
18244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
18344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Minor key encoding in 16 bits RRRTTTVOOOOOOOMM.
18444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  class ModeBits: public BitField<OverwriteMode, 0, 2> {};
18544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  class OpBits: public BitField<Token::Value, 2, 7> {};
18644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  class FPUBits: public BitField<bool, 9, 1> {};
187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  class OperandTypeInfoBits: public BitField<BinaryOpIC::TypeInfo, 10, 3> {};
188257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  class ResultTypeInfoBits: public BitField<BinaryOpIC::TypeInfo, 13, 3> {};
18944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
190257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Major MajorKey() { return BinaryOp; }
19144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int MinorKey() {
19244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return OpBits::encode(op_)
19344f0eee88ff00398ff7f715fab053374d808c90dSteve Block           | ModeBits::encode(mode_)
19444f0eee88ff00398ff7f715fab053374d808c90dSteve Block           | FPUBits::encode(use_fpu_)
19544f0eee88ff00398ff7f715fab053374d808c90dSteve Block           | OperandTypeInfoBits::encode(operands_type_)
19644f0eee88ff00398ff7f715fab053374d808c90dSteve Block           | ResultTypeInfoBits::encode(result_type_);
19744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
19844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
19944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void Generate(MacroAssembler* masm);
20044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void GenerateGeneric(MacroAssembler* masm);
20144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void GenerateSmiSmiOperation(MacroAssembler* masm);
20244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void GenerateFPOperation(MacroAssembler* masm,
20344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           bool smi_operands,
20444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           Label* not_numbers,
20544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           Label* gc_required);
20644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void GenerateSmiCode(MacroAssembler* masm,
207257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                       Label* use_runtime,
20844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                       Label* gc_required,
20944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                       SmiCodeGenerateHeapNumberResults heapnumber_results);
21044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void GenerateLoadArguments(MacroAssembler* masm);
21144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void GenerateReturn(MacroAssembler* masm);
21244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void GenerateUninitializedStub(MacroAssembler* masm);
21344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void GenerateSmiStub(MacroAssembler* masm);
21444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void GenerateInt32Stub(MacroAssembler* masm);
21544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void GenerateHeapNumberStub(MacroAssembler* masm);
216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateOddballStub(MacroAssembler* masm);
21744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void GenerateStringStub(MacroAssembler* masm);
218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateBothStringStub(MacroAssembler* masm);
21944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void GenerateGenericStub(MacroAssembler* masm);
22044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void GenerateAddStrings(MacroAssembler* masm);
22144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void GenerateCallRuntime(MacroAssembler* masm);
22244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
22344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void GenerateHeapResultAllocation(MacroAssembler* masm,
22444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                    Register result,
22544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                    Register heap_number_map,
22644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                    Register scratch1,
22744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                    Register scratch2,
22844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                    Label* gc_required);
22944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void GenerateRegisterArgsPush(MacroAssembler* masm);
23044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void GenerateTypeTransition(MacroAssembler* masm);
23144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void GenerateTypeTransitionWithSavedArgs(MacroAssembler* masm);
23244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  virtual int GetCodeKind() { return Code::BINARY_OP_IC; }
23444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
23544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  virtual InlineCacheState GetICState() {
236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return BinaryOpIC::ToState(operands_type_);
23744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
23844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual void FinishCode(Handle<Code> code) {
240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    code->set_binary_op_type(operands_type_);
241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    code->set_binary_op_result_type(result_type_);
24244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
24344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
24444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  friend class CodeGenerator;
24544f0eee88ff00398ff7f715fab053374d808c90dSteve Block};
24644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
24744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochclass StringHelper : public AllStatic {
2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Generate code for copying characters using a simple loop. This should only
2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // be used in places where the number of characters is small and the
2523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // additional setup and checking in GenerateCopyCharactersLong adds too much
2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // overhead. Copying of overlapping regions is not supported.
2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Dest register ends at the position after the last character written.
2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void GenerateCopyCharacters(MacroAssembler* masm,
2563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Register dest,
2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Register src,
2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Register count,
2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Register scratch,
2603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     bool ascii);
2613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Generate code for copying a large number of characters. This function
2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // is allowed to spend extra time setting up conditions to make copying
2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // faster. Copying of overlapping regions is not supported.
2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Dest register ends at the position after the last character written.
2663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void GenerateCopyCharactersLong(MacroAssembler* masm,
2673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Register dest,
2683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Register src,
2693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Register count,
2703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Register scratch1,
2713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Register scratch2,
2723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Register scratch3,
2733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Register scratch4,
2743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Register scratch5,
2753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         int flags);
2763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Probe the symbol table for a two character string. If the string is
2793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // not found by probing a jump to the label not_found is performed. This jump
2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // does not guarantee that the string is not in the symbol table. If the
2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // string is found the code falls through with the string in register r0.
2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Contents of both c1 and c2 registers are modified. At the exit c1 is
2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // guaranteed to contain halfword with low and high bytes equal to
2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // initial contents of c1 and c2 respectively.
2853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Register c1,
2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Register c2,
2883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Register scratch1,
2893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Register scratch2,
2903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Register scratch3,
2913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Register scratch4,
2923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Register scratch5,
2933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Label* not_found);
2943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Generate string hash.
2963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void GenerateHashInit(MacroAssembler* masm,
2973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Register hash,
2983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Register character);
2993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void GenerateHashAddCharacter(MacroAssembler* masm,
3013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Register hash,
3023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Register character);
3033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void GenerateHashGetHash(MacroAssembler* masm,
3053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  Register hash);
3063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private:
3083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper);
3093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
3103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31244f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Flag that indicates how to generate code for the stub StringAddStub.
31344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockenum StringAddFlags {
31444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  NO_STRING_ADD_FLAGS = 0,
315257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Omit left string check in stub (left is definitely a string).
316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  NO_STRING_CHECK_LEFT_IN_STUB = 1 << 0,
317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Omit right string check in stub (right is definitely a string).
318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  NO_STRING_CHECK_RIGHT_IN_STUB = 1 << 1,
319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Omit both string checks in stub.
320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  NO_STRING_CHECK_IN_STUB =
321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      NO_STRING_CHECK_LEFT_IN_STUB | NO_STRING_CHECK_RIGHT_IN_STUB
32244f0eee88ff00398ff7f715fab053374d808c90dSteve Block};
32344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
32444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
32544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass StringAddStub: public CodeStub {
32644f0eee88ff00398ff7f715fab053374d808c90dSteve Block public:
327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  explicit StringAddStub(StringAddFlags flags) : flags_(flags) {}
32844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
32944f0eee88ff00398ff7f715fab053374d808c90dSteve Block private:
33044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Major MajorKey() { return StringAdd; }
331257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int MinorKey() { return flags_; }
33244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
33344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void Generate(MacroAssembler* masm);
33444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
335257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateConvertArgument(MacroAssembler* masm,
336257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               int stack_offset,
337257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               Register arg,
338257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               Register scratch1,
339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               Register scratch2,
340257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               Register scratch3,
341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               Register scratch4,
342257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               Label* slow);
343257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
344257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const StringAddFlags flags_;
34544f0eee88ff00398ff7f715fab053374d808c90dSteve Block};
34644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
34744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
34844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass SubStringStub: public CodeStub {
34944f0eee88ff00398ff7f715fab053374d808c90dSteve Block public:
35044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  SubStringStub() {}
35144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
35244f0eee88ff00398ff7f715fab053374d808c90dSteve Block private:
35344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Major MajorKey() { return SubString; }
35444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int MinorKey() { return 0; }
35544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
35644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void Generate(MacroAssembler* masm);
35744f0eee88ff00398ff7f715fab053374d808c90dSteve Block};
35844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
35944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
36044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass StringCompareStub: public CodeStub {
36144f0eee88ff00398ff7f715fab053374d808c90dSteve Block public:
36244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  StringCompareStub() { }
36344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
36444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Compare two flat ASCII strings and returns result in v0.
36544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static void GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
36644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                              Register left,
36744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                              Register right,
36844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                              Register scratch1,
36944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                              Register scratch2,
37044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                              Register scratch3,
37144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                              Register scratch4);
37244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
373257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Compares two flat ASCII strings for equality and returns result
374257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // in v0.
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);
38144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
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                                            Register scratch3,
394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                            Label* chars_not_equal);
39544f0eee88ff00398ff7f715fab053374d808c90dSteve Block};
39644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
39744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
39844f0eee88ff00398ff7f715fab053374d808c90dSteve Block// This stub can convert a signed int32 to a heap number (double).  It does
39944f0eee88ff00398ff7f715fab053374d808c90dSteve Block// not work for int32s that are in Smi range!  No GC occurs during this stub
40044f0eee88ff00398ff7f715fab053374d808c90dSteve Block// so you don't have to set up the frame.
40144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass WriteInt32ToHeapNumberStub : public CodeStub {
40244f0eee88ff00398ff7f715fab053374d808c90dSteve Block public:
40344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  WriteInt32ToHeapNumberStub(Register the_int,
40444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                             Register the_heap_number,
40544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                             Register scratch,
40644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                             Register scratch2)
40744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : the_int_(the_int),
40844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        the_heap_number_(the_heap_number),
40944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        scratch_(scratch),
4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        sign_(scratch2) {
4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(IntRegisterBits::is_valid(the_int_.code()));
4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(HeapNumberRegisterBits::is_valid(the_heap_number_.code()));
4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(ScratchRegisterBits::is_valid(scratch_.code()));
4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(SignRegisterBits::is_valid(sign_.code()));
4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool IsPregenerated();
4183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void GenerateFixedRegStubsAheadOfTime();
41944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
42044f0eee88ff00398ff7f715fab053374d808c90dSteve Block private:
42144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register the_int_;
42244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register the_heap_number_;
42344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register scratch_;
42444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register sign_;
42544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
42644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Minor key encoding in 16 bits.
42744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  class IntRegisterBits: public BitField<int, 0, 4> {};
42844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  class HeapNumberRegisterBits: public BitField<int, 4, 4> {};
42944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  class ScratchRegisterBits: public BitField<int, 8, 4> {};
4303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  class SignRegisterBits: public BitField<int, 12, 4> {};
43144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
43244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Major MajorKey() { return WriteInt32ToHeapNumber; }
43344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int MinorKey() {
43444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Encode the parameters in a unique 16 bit value.
43544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return IntRegisterBits::encode(the_int_.code())
43644f0eee88ff00398ff7f715fab053374d808c90dSteve Block           | HeapNumberRegisterBits::encode(the_heap_number_.code())
4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           | ScratchRegisterBits::encode(scratch_.code())
4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           | SignRegisterBits::encode(sign_.code());
43944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
44044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
44144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void Generate(MacroAssembler* masm);
44244f0eee88ff00398ff7f715fab053374d808c90dSteve Block};
44344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
44444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
44544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass NumberToStringStub: public CodeStub {
44644f0eee88ff00398ff7f715fab053374d808c90dSteve Block public:
44744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  NumberToStringStub() { }
44844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
44944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Generate code to do a lookup in the number string cache. If the number in
45044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // the register object is found in the cache the generated code falls through
45144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // with the result in the result register. The object and the result register
45244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // can be the same. If the number is not found in the cache the code jumps to
45344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // the label not_found with only the content of register object unchanged.
45444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static void GenerateLookupNumberStringCache(MacroAssembler* masm,
45544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                              Register object,
45644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                              Register result,
45744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                              Register scratch1,
45844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                              Register scratch2,
45944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                              Register scratch3,
46044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                              bool object_is_smi,
46144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                              Label* not_found);
46244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
46344f0eee88ff00398ff7f715fab053374d808c90dSteve Block private:
46444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Major MajorKey() { return NumberToString; }
46544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int MinorKey() { return 0; }
46644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
46744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void Generate(MacroAssembler* masm);
46844f0eee88ff00398ff7f715fab053374d808c90dSteve Block};
46944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
47044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochclass RecordWriteStub: public CodeStub {
4723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
4733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordWriteStub(Register object,
4743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  Register value,
4753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  Register address,
4763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  RememberedSetAction remembered_set_action,
4773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  SaveFPRegsMode fp_mode)
4783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : object_(object),
4793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        value_(value),
4803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        address_(address),
4813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        remembered_set_action_(remembered_set_action),
4823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        save_fp_regs_mode_(fp_mode),
4833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        regs_(object,   // An input reg.
4843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              address,  // An input reg.
4853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              value) {  // One scratch reg.
4863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  enum Mode {
4893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    STORE_BUFFER_ONLY,
4903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    INCREMENTAL,
4913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    INCREMENTAL_COMPACTION
4923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
4933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual bool IsPregenerated();
4953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void GenerateFixedRegStubsAheadOfTime();
4963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual bool SometimesSetsUpAFrame() { return false; }
4973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void PatchBranchIntoNop(MacroAssembler* masm, int pos) {
4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    const unsigned offset = masm->instr_at(pos) & kImm16Mask;
5003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    masm->instr_at_put(pos, BNE | (zero_reg.code() << kRsShift) |
5013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        (zero_reg.code() << kRtShift) | (offset & kImm16Mask));
5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(Assembler::IsBne(masm->instr_at(pos)));
5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void PatchNopIntoBranch(MacroAssembler* masm, int pos) {
5063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    const unsigned offset = masm->instr_at(pos) & kImm16Mask;
5073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    masm->instr_at_put(pos, BEQ | (zero_reg.code() << kRsShift) |
5083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        (zero_reg.code() << kRtShift) | (offset & kImm16Mask));
5093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(Assembler::IsBeq(masm->instr_at(pos)));
5103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static Mode GetMode(Code* stub) {
5133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Instr first_instruction = Assembler::instr_at(stub->instruction_start());
5143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Instr second_instruction = Assembler::instr_at(stub->instruction_start() +
5153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   2 * Assembler::kInstrSize);
5163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (Assembler::IsBeq(first_instruction)) {
5183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return INCREMENTAL;
5193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(Assembler::IsBne(first_instruction));
5223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (Assembler::IsBeq(second_instruction)) {
5243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return INCREMENTAL_COMPACTION;
5253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(Assembler::IsBne(second_instruction));
5283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return STORE_BUFFER_ONLY;
5303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void Patch(Code* stub, Mode mode) {
5333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MacroAssembler masm(NULL,
5343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        stub->instruction_start(),
5353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        stub->instruction_size());
5363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    switch (mode) {
5373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case STORE_BUFFER_ONLY:
5383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(GetMode(stub) == INCREMENTAL ||
5393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               GetMode(stub) == INCREMENTAL_COMPACTION);
5403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        PatchBranchIntoNop(&masm, 0);
5413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        PatchBranchIntoNop(&masm, 2 * Assembler::kInstrSize);
5423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
5433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case INCREMENTAL:
5443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(GetMode(stub) == STORE_BUFFER_ONLY);
5453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        PatchNopIntoBranch(&masm, 0);
5463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
5473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case INCREMENTAL_COMPACTION:
5483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(GetMode(stub) == STORE_BUFFER_ONLY);
5493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        PatchNopIntoBranch(&masm, 2 * Assembler::kInstrSize);
5503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
5513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(GetMode(stub) == mode);
5533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CPU::FlushICache(stub->instruction_start(), 4 * Assembler::kInstrSize);
5543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private:
5573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // This is a helper class for freeing up 3 scratch registers.  The input is
5583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // two registers that must be preserved and one scratch register provided by
5593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the caller.
5603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  class RegisterAllocation {
5613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   public:
5623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RegisterAllocation(Register object,
5633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       Register address,
5643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       Register scratch0)
5653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : object_(object),
5663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          address_(address),
5673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          scratch0_(scratch0) {
5683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(!AreAliased(scratch0, object, address, no_reg));
5693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      scratch1_ = GetRegThatIsNotOneOf(object_, address_, scratch0_);
5703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    void Save(MacroAssembler* masm) {
5733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(!AreAliased(object_, address_, scratch1_, scratch0_));
5743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // We don't have to save scratch0_ because it was given to us as
5753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // a scratch register.
5763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      masm->push(scratch1_);
5773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    void Restore(MacroAssembler* masm) {
5803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      masm->pop(scratch1_);
5813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // If we have to call into C then we need to save and restore all caller-
5843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // saved registers that were not already preserved.  The scratch registers
5853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // will be restored by other means so we don't bother pushing them here.
5863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    void SaveCallerSaveRegisters(MacroAssembler* masm, SaveFPRegsMode mode) {
5873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      masm->MultiPush((kJSCallerSaved | ra.bit()) & ~scratch1_.bit());
5883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (mode == kSaveFPRegs) {
5893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CpuFeatures::Scope scope(FPU);
5903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        masm->MultiPushFPU(kCallerSavedFPU);
5913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
5923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    inline void RestoreCallerSaveRegisters(MacroAssembler*masm,
5953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           SaveFPRegsMode mode) {
5963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (mode == kSaveFPRegs) {
5973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CpuFeatures::Scope scope(FPU);
5983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        masm->MultiPopFPU(kCallerSavedFPU);
5993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
6003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      masm->MultiPop((kJSCallerSaved | ra.bit()) & ~scratch1_.bit());
6013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
6023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    inline Register object() { return object_; }
6043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    inline Register address() { return address_; }
6053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    inline Register scratch0() { return scratch0_; }
6063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    inline Register scratch1() { return scratch1_; }
6073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   private:
6093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register object_;
6103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register address_;
6113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch0_;
6123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch1_;
6133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register GetRegThatIsNotOneOf(Register r1,
6153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  Register r2,
6163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  Register r3) {
6173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      for (int i = 0; i < Register::kNumAllocatableRegisters; i++) {
6183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Register candidate = Register::FromAllocationIndex(i);
6193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (candidate.is(r1)) continue;
6203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (candidate.is(r2)) continue;
6213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (candidate.is(r3)) continue;
6223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return candidate;
6233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
6243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      UNREACHABLE();
6253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return no_reg;
6263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
6273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    friend class RecordWriteStub;
6283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
6293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  enum OnNoNeedToInformIncrementalMarker {
6313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    kReturnOnNoNeedToInformIncrementalMarker,
6323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    kUpdateRememberedSetOnNoNeedToInformIncrementalMarker
6333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
6343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Generate(MacroAssembler* masm);
6363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void GenerateIncremental(MacroAssembler* masm, Mode mode);
6373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CheckNeedsToInformIncrementalMarker(
6383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      MacroAssembler* masm,
6393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      OnNoNeedToInformIncrementalMarker on_no_need,
6403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Mode mode);
6413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void InformIncrementalMarker(MacroAssembler* masm, Mode mode);
6423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Major MajorKey() { return RecordWrite; }
6443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int MinorKey() {
6463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return ObjectBits::encode(object_.code()) |
6473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ValueBits::encode(value_.code()) |
6483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        AddressBits::encode(address_.code()) |
6493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        RememberedSetActionBits::encode(remembered_set_action_) |
6503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        SaveFPRegsModeBits::encode(save_fp_regs_mode_);
6513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
6523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Activate(Code* code) {
6543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    code->GetHeap()->incremental_marking()->ActivateGeneratedStub(code);
6553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
6563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  class ObjectBits: public BitField<int, 0, 5> {};
6583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  class ValueBits: public BitField<int, 5, 5> {};
6593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  class AddressBits: public BitField<int, 10, 5> {};
6603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  class RememberedSetActionBits: public BitField<RememberedSetAction, 15, 1> {};
6613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  class SaveFPRegsModeBits: public BitField<SaveFPRegsMode, 16, 1> {};
6623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register object_;
6643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register value_;
6653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register address_;
6663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RememberedSetAction remembered_set_action_;
6673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SaveFPRegsMode save_fp_regs_mode_;
6683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label slow_;
6693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RegisterAllocation regs_;
6703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
6713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
67344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Enter C code from generated RegExp code in a way that allows
67444f0eee88ff00398ff7f715fab053374d808c90dSteve Block// the C code to fix the return address in case of a GC.
67544f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Currently only needed on ARM and MIPS.
67644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass RegExpCEntryStub: public CodeStub {
67744f0eee88ff00398ff7f715fab053374d808c90dSteve Block public:
67844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  RegExpCEntryStub() {}
67944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  virtual ~RegExpCEntryStub() {}
68044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void Generate(MacroAssembler* masm);
68144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
68244f0eee88ff00398ff7f715fab053374d808c90dSteve Block private:
68344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Major MajorKey() { return RegExpCEntry; }
68444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int MinorKey() { return 0; }
68544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
68644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bool NeedsImmovableCode() { return true; }
68744f0eee88ff00398ff7f715fab053374d808c90dSteve Block};
68844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
689257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Trampoline stub to call into native code. To call safely into native code
690257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// in the presence of compacting GC (which can move code objects) we need to
691257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// keep the code which called into native pinned in the memory. Currently the
692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// simplest approach is to generate such stub early enough so it can never be
693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// moved by GC
694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass DirectCEntryStub: public CodeStub {
695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch public:
696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DirectCEntryStub() {}
697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void Generate(MacroAssembler* masm);
698257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateCall(MacroAssembler* masm,
699257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                ExternalReference function);
700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GenerateCall(MacroAssembler* masm, Register target);
701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private:
703257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Major MajorKey() { return DirectCEntry; }
704257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int MinorKey() { return 0; }
705257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool NeedsImmovableCode() { return true; }
707257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch};
708257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass FloatingPointHelper : public AllStatic {
710257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch public:
711257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  enum Destination {
712257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    kFPURegisters,
713257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    kCoreRegisters
714257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  };
71544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
716257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
717257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Loads smis from a0 and a1 (right and left in binary operations) into
718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // floating point registers. Depending on the destination the values ends up
719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // either f14 and f12 or in a2/a3 and a0/a1 respectively. If the destination
720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // is floating point registers FPU must be supported. If core registers are
721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // requested when FPU is supported f12 and f14 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 a0 and a1 (right and left in binary operations) into
728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // floating point registers. Depending on the destination the values ends up
729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // either f14 and f12 or in a2/a3 and a0/a1 respectively. If the destination
730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // is floating point registers FPU must be supported. If core registers are
731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // requested when FPU is supported f12 and f14 will still be scratched. If
732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // either a0 or a1 is not a number (not smi and not heap number object) the
733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // not_number label is jumped to with a0 and a1 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                                   FPURegister 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                                 FPURegister double_dst,
762257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Register dst1,
763257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Register dst2,
764257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Register scratch2,
765257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 FPURegister 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                                      FPURegister 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                                      FPURegister 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 FPU is supported.
790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void LoadNumberAsInt32(MacroAssembler* masm,
791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Register object,
792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Register dst,
793257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Register heap_number_map,
79444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                Register scratch1,
79544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                Register scratch2,
796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Register scratch3,
797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                FPURegister double_scratch,
798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Label* not_int32);
799257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Generate non FPU 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 FPU is not supported.)
823257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This code never falls through, but returns with a heap number containing
824257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // the result in v0.
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  // a0: Left value (least significant part of mantissa).
829257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a1: Left value (sign, exponent, top of mantissa).
830257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a2: Right value (least significant part of mantissa).
831257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a3: 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                         FPURegister 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};
89944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
90044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
90144f0eee88ff00398ff7f715fab053374d808c90dSteve Block} }  // namespace v8::internal
90244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
90344f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif  // V8_MIPS_CODE_STUBS_ARM_H_
904