code-stubs.h revision 086aeeaae12517475c22695a200be45495516549
1086aeeaae12517475c22695a200be45495516549Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef V8_CODE_STUBS_H_
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define V8_CODE_STUBS_H_
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#include "globals.h"
326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
36d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// List of code stubs used on all platforms. The order in this list is important
37086aeeaae12517475c22695a200be45495516549Ben Murdoch// as only the stubs up to and including Instanceof allows nested stub calls.
38d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#define CODE_STUB_LIST_ALL_PLATFORMS(V)  \
39d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  V(CallFunction)                        \
40d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  V(GenericBinaryOp)                     \
41b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  V(TypeRecordingBinaryOp)               \
42d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  V(StringAdd)                           \
43b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  V(StringCharAt)                        \
44e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  V(SubString)                           \
45e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  V(StringCompare)                       \
46d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  V(SmiOp)                               \
47d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  V(Compare)                             \
48b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  V(CompareIC)                           \
49b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  V(MathPow)                             \
50b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  V(TranscendentalCache)                 \
51086aeeaae12517475c22695a200be45495516549Ben Murdoch  V(Instanceof)                          \
52d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  V(ConvertToDouble)                     \
53d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  V(WriteInt32ToHeapNumber)              \
548defd9ff6930b4e24729971a61cf7469daf119beSteve Block  V(IntegerMod)                          \
55d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  V(StackCheck)                          \
56e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  V(FastNewClosure)                      \
57e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  V(FastNewContext)                      \
58e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  V(FastCloneShallowArray)               \
59e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  V(GenericUnaryOp)                      \
60d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  V(RevertToNumber)                      \
61d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  V(ToBoolean)                           \
62d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  V(CounterOp)                           \
63d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  V(ArgumentsAccess)                     \
64e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  V(RegExpExec)                          \
65b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  V(RegExpConstructResult)               \
66402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  V(NumberToString)                      \
67d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  V(CEntry)                              \
684515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  V(JSEntry)                             \
694515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  V(DebuggerStatement)
70d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
71d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// List of code stubs only used on ARM platforms.
72d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef V8_TARGET_ARCH_ARM
73d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#define CODE_STUB_LIST_ARM(V)  \
74d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  V(GetProperty)               \
75d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  V(SetProperty)               \
76d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  V(InvokeBuiltin)             \
77d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  V(RegExpCEntry)
78d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#else
79d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#define CODE_STUB_LIST_ARM(V)
80d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif
81d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
82d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Combined list of code stubs.
83d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#define CODE_STUB_LIST(V)            \
84d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CODE_STUB_LIST_ALL_PLATFORMS(V)    \
85d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CODE_STUB_LIST_ARM(V)
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// Types of uncatchable exceptions.
8880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenenum UncatchableExceptionType { OUT_OF_MEMORY, TERMINATION };
8980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
9080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// Mode to overwrite BinaryExpression values.
9180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenenum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
9280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenenum UnaryOverwriteMode { UNARY_OVERWRITE, UNARY_NO_OVERWRITE };
9380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
9480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Stub is base classes of all stubs.
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass CodeStub BASE_EMBEDDED {
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  enum Major {
99d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#define DEF_ENUM(name) name,
100d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    CODE_STUB_LIST(DEF_ENUM)
101d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#undef DEF_ENUM
102d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    NoCache,  // marker for stubs that do custom caching
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    NUMBER_OF_IDS
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Retrieve the code for the stub. Generate the code if needed.
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> GetCode();
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
109e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Retrieve the code for the stub if already generated.  Do not
110e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // generate the code if not already generated and instead return a
111e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // retry after GC Failure object.
1125913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  MUST_USE_RESULT MaybeObject* TryGetCode();
113e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static Major MajorKeyFromKey(uint32_t key) {
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return static_cast<Major>(MajorKeyBits::decode(key));
1169ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  }
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static int MinorKeyFromKey(uint32_t key) {
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return MinorKeyBits::decode(key);
1199ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  }
12080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
12180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Gets the major key from a code object that is a code stub or binary op IC.
12280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  static Major GetMajorKey(Code* code_stub) {
12380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    return static_cast<Major>(code_stub->major_key());
12480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
12580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  static const char* MajorName(Major major_key, bool allow_unknown_keys);
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual ~CodeStub() {}
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block protected:
131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static const int kMajorBits = 6;
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kMinorBits = kBitsPerInt - kSmiTagSize - kMajorBits;
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
135e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Lookup the code in the (possibly custom) cache.
136e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  bool FindCodeInCache(Code** code_out);
137e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
138e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Nonvirtual wrapper around the stub-specific Generate function.  Call
139e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // this function to set up the macro assembler and generate the code.
140e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void GenerateCode(MacroAssembler* masm);
141e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Generates the assembler code for the stub.
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual void Generate(MacroAssembler* masm) = 0;
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
145e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Perform bookkeeping required after code generation when stub code is
146e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // initially generated.
147e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void RecordCodeGeneration(Code* code, MacroAssembler* masm);
148e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Finish the code object after it has been generated.
150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  virtual void FinishCode(Code* code) { }
151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Returns information for computing the number key.
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual Major MajorKey() = 0;
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual int MinorKey() = 0;
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The CallFunctionStub needs to override this so it can encode whether a
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // lazily generated function should be fully optimized or not.
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual InLoopFlag InLoop() { return NOT_IN_LOOP; }
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // GenericBinaryOpStub needs to override this.
1616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  virtual int GetCodeKind();
1626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // GenericBinaryOpStub needs to override this.
1646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  virtual InlineCacheState GetICState() {
1656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return UNINITIALIZED;
1666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
1676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Returns a name for logging/debugging purposes.
1693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  virtual const char* GetName() { return MajorName(MajorKey(), false); }
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual void Print() { PrintF("%s\n", GetName()); }
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Computes the key based on major and minor.
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uint32_t GetKey() {
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(static_cast<int>(MajorKey()) < NUMBER_OF_IDS);
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return MinorKeyBits::encode(MinorKey()) |
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           MajorKeyBits::encode(MajorKey());
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
182086aeeaae12517475c22695a200be45495516549Ben Murdoch  bool AllowsStubCalls() { return MajorKey() <= Instanceof; }
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  class MajorKeyBits: public BitField<uint32_t, 0, kMajorBits> {};
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  class MinorKeyBits: public BitField<uint32_t, kMajorBits, kMinorBits> {};
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class BreakPointIterator;
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
19180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// Helper interface to prepare to/restore after making runtime calls.
19280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenclass RuntimeCallHelper {
19380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen public:
19480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  virtual ~RuntimeCallHelper() {}
19580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
19680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  virtual void BeforeCall(MacroAssembler* masm) const = 0;
19780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
19880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  virtual void AfterCall(MacroAssembler* masm) const = 0;
19980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
20080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen protected:
20180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  RuntimeCallHelper() {}
20280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
20380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen private:
20480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  DISALLOW_COPY_AND_ASSIGN(RuntimeCallHelper);
20580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen};
20680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
20780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} }  // namespace v8::internal
20880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
20980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#if V8_TARGET_ARCH_IA32
21080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#include "ia32/code-stubs-ia32.h"
21180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#elif V8_TARGET_ARCH_X64
21280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#include "x64/code-stubs-x64.h"
21380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#elif V8_TARGET_ARCH_ARM
21480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#include "arm/code-stubs-arm.h"
21580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#elif V8_TARGET_ARCH_MIPS
21680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#include "mips/code-stubs-mips.h"
21780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#else
21880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#error Unsupported target architecture.
21980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#endif
22080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
22180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsennamespace v8 {
22280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsennamespace internal {
22380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
22480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// RuntimeCallHelper implementation used in stubs: enters/leaves a
22680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// newly created internal frame before/after the runtime call.
227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass StubRuntimeCallHelper : public RuntimeCallHelper {
22880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen public:
229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  StubRuntimeCallHelper() {}
23080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
23180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  virtual void BeforeCall(MacroAssembler* masm) const;
23280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
23380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  virtual void AfterCall(MacroAssembler* masm) const;
23480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen};
23580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
23680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
23780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// Trivial RuntimeCallHelper implementation.
23880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenclass NopRuntimeCallHelper : public RuntimeCallHelper {
23980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen public:
24080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  NopRuntimeCallHelper() {}
24180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
24280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  virtual void BeforeCall(MacroAssembler* masm) const {}
24380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
24480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  virtual void AfterCall(MacroAssembler* masm) const {}
24580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen};
24680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
24780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
24880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenclass StackCheckStub : public CodeStub {
24980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen public:
25080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  StackCheckStub() { }
25180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
25280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void Generate(MacroAssembler* masm);
25380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
25480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen private:
25580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
25680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  const char* GetName() { return "StackCheckStub"; }
25780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
25880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Major MajorKey() { return StackCheck; }
25980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int MinorKey() { return 0; }
26080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen};
26180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
26280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
26380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenclass FastNewClosureStub : public CodeStub {
26480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen public:
26580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void Generate(MacroAssembler* masm);
26680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
26780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen private:
26880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  const char* GetName() { return "FastNewClosureStub"; }
26980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Major MajorKey() { return FastNewClosure; }
27080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int MinorKey() { return 0; }
27180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen};
27280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
27380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
27480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenclass FastNewContextStub : public CodeStub {
27580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen public:
27680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  static const int kMaximumSlots = 64;
27780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
27880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  explicit FastNewContextStub(int slots) : slots_(slots) {
27980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    ASSERT(slots_ > 0 && slots <= kMaximumSlots);
28080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
28180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
28280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void Generate(MacroAssembler* masm);
28380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
28480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen private:
28580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int slots_;
28680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
28780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  const char* GetName() { return "FastNewContextStub"; }
28880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Major MajorKey() { return FastNewContext; }
28980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int MinorKey() { return slots_; }
29080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen};
29180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
29280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
29380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenclass FastCloneShallowArrayStub : public CodeStub {
29480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen public:
29580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Maximum length of copied elements array.
29680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  static const int kMaximumClonedLength = 8;
29780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
29880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  enum Mode {
29980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    CLONE_ELEMENTS,
30080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    COPY_ON_WRITE_ELEMENTS
30180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  };
30280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
30380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  FastCloneShallowArrayStub(Mode mode, int length)
30480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      : mode_(mode),
30580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        length_((mode == COPY_ON_WRITE_ELEMENTS) ? 0 : length) {
30680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    ASSERT(length_ >= 0);
30780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    ASSERT(length_ <= kMaximumClonedLength);
30880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
30980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
31080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void Generate(MacroAssembler* masm);
31180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
31280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen private:
31380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Mode mode_;
31480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int length_;
31580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
31680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  const char* GetName() { return "FastCloneShallowArrayStub"; }
31780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Major MajorKey() { return FastCloneShallowArray; }
31880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int MinorKey() {
31980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    ASSERT(mode_ == 0 || mode_ == 1);
32080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    return (length_ << 1) | mode_;
32180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
32280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen};
32380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
32480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
32580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenclass InstanceofStub: public CodeStub {
32680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen public:
327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  enum Flags {
328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    kNoFlags = 0,
329086aeeaae12517475c22695a200be45495516549Ben Murdoch    kArgsInRegisters = 1 << 0,
330086aeeaae12517475c22695a200be45495516549Ben Murdoch    kCallSiteInlineCheck = 1 << 1,
331086aeeaae12517475c22695a200be45495516549Ben Murdoch    kReturnTrueFalseObject = 1 << 2
332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  };
333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
334086aeeaae12517475c22695a200be45495516549Ben Murdoch  explicit InstanceofStub(Flags flags) : flags_(flags), name_(NULL) { }
335086aeeaae12517475c22695a200be45495516549Ben Murdoch
336086aeeaae12517475c22695a200be45495516549Ben Murdoch  static Register left();
337086aeeaae12517475c22695a200be45495516549Ben Murdoch  static Register right();
33880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
33980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void Generate(MacroAssembler* masm);
34080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
34180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen private:
34280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Major MajorKey() { return Instanceof; }
343086aeeaae12517475c22695a200be45495516549Ben Murdoch  int MinorKey() { return static_cast<int>(flags_); }
344b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
345086aeeaae12517475c22695a200be45495516549Ben Murdoch  bool HasArgsInRegisters() const {
346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return (flags_ & kArgsInRegisters) != 0;
347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
349086aeeaae12517475c22695a200be45495516549Ben Murdoch  bool HasCallSiteInlineCheck() const {
350086aeeaae12517475c22695a200be45495516549Ben Murdoch    return (flags_ & kCallSiteInlineCheck) != 0;
351086aeeaae12517475c22695a200be45495516549Ben Murdoch  }
352086aeeaae12517475c22695a200be45495516549Ben Murdoch
353086aeeaae12517475c22695a200be45495516549Ben Murdoch  bool ReturnTrueFalseObject() const {
354086aeeaae12517475c22695a200be45495516549Ben Murdoch    return (flags_ & kReturnTrueFalseObject) != 0;
355086aeeaae12517475c22695a200be45495516549Ben Murdoch  }
356086aeeaae12517475c22695a200be45495516549Ben Murdoch
357086aeeaae12517475c22695a200be45495516549Ben Murdoch  const char* GetName();
358086aeeaae12517475c22695a200be45495516549Ben Murdoch
359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Flags flags_;
360086aeeaae12517475c22695a200be45495516549Ben Murdoch  char* name_;
36180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen};
36280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
36380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
36480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenenum NegativeZeroHandling {
36580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  kStrictNegativeZero,
36680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  kIgnoreNegativeZero
36780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen};
36880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
36980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
3700d5e116f6aee03185f237311a943491bb079a768Kristian Monsenenum UnaryOpFlags {
3710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NO_UNARY_FLAGS = 0,
3720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NO_UNARY_SMI_CODE_IN_STUB = 1 << 0
3730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen};
3740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
3750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
37680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenclass GenericUnaryOpStub : public CodeStub {
37780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen public:
37880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  GenericUnaryOpStub(Token::Value op,
37980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                     UnaryOverwriteMode overwrite,
3800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                     UnaryOpFlags flags,
38180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                     NegativeZeroHandling negative_zero = kStrictNegativeZero)
3820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      : op_(op),
3830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        overwrite_(overwrite),
3840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        include_smi_code_((flags & NO_UNARY_SMI_CODE_IN_STUB) == 0),
3850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        negative_zero_(negative_zero) { }
38680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
38780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen private:
38880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Token::Value op_;
38980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  UnaryOverwriteMode overwrite_;
3900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  bool include_smi_code_;
39180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  NegativeZeroHandling negative_zero_;
39280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
39380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  class OverwriteField: public BitField<UnaryOverwriteMode, 0, 1> {};
3940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  class IncludeSmiCodeField: public BitField<bool, 1, 1> {};
3950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  class NegativeZeroField: public BitField<NegativeZeroHandling, 2, 1> {};
3960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  class OpField: public BitField<Token::Value, 3, kMinorBits - 3> {};
39780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
39880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Major MajorKey() { return GenericUnaryOp; }
39980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int MinorKey() {
40080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    return OpField::encode(op_) |
4010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        OverwriteField::encode(overwrite_) |
4020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        IncludeSmiCodeField::encode(include_smi_code_) |
4030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        NegativeZeroField::encode(negative_zero_);
40480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
40580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
40680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void Generate(MacroAssembler* masm);
40780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
40880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  const char* GetName();
40980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen};
41080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
41180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass MathPowStub: public CodeStub {
413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  MathPowStub() {}
415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  virtual void Generate(MacroAssembler* masm);
416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  virtual CodeStub::Major MajorKey() { return MathPow; }
419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  virtual int MinorKey() { return 0; }
420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const char* GetName() { return "MathPowStub"; }
422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass StringCharAtStub: public CodeStub {
426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  StringCharAtStub() {}
428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Major MajorKey() { return StringCharAt; }
431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int MinorKey() { return 0; }
432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void Generate(MacroAssembler* masm);
434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass ICCompareStub: public CodeStub {
438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ICCompareStub(Token::Value op, CompareIC::State state)
440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      : op_(op), state_(state) {
441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(Token::IsCompareOp(op));
442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  virtual void Generate(MacroAssembler* masm);
445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  class OpField: public BitField<int, 0, 3> { };
448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  class StateField: public BitField<int, 3, 5> { };
449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  virtual void FinishCode(Code* code) { code->set_compare_state(state_); }
451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  virtual CodeStub::Major MajorKey() { return CompareIC; }
453b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  virtual int MinorKey();
454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  virtual int GetCodeKind() { return Code::COMPARE_IC; }
456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void GenerateSmis(MacroAssembler* masm);
458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void GenerateHeapNumbers(MacroAssembler* masm);
459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void GenerateObjects(MacroAssembler* masm);
460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void GenerateMiss(MacroAssembler* masm);
461b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool strict() const { return op_ == Token::EQ_STRICT; }
463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Condition GetCondition() const { return CompareIC::ComputeCondition(op_); }
464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Token::Value op_;
466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CompareIC::State state_;
46780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen};
46880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
46980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
4700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen// Flags that control the compare stub code generation.
4710d5e116f6aee03185f237311a943491bb079a768Kristian Monsenenum CompareFlags {
4720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NO_COMPARE_FLAGS = 0,
4730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NO_SMI_COMPARE_IN_STUB = 1 << 0,
4740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NO_NUMBER_COMPARE_IN_STUB = 1 << 1,
4750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  CANT_BOTH_BE_NAN = 1 << 2
4760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen};
4770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochenum NaNInformation {
480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  kBothCouldBeNaN,
481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  kCantBothBeNaN
482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
48580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenclass CompareStub: public CodeStub {
48680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen public:
48780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  CompareStub(Condition cc,
48880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen              bool strict,
4890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen              CompareFlags flags,
4900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen              Register lhs,
4910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen              Register rhs) :
492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch     cc_(cc),
49380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      strict_(strict),
4940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      never_nan_nan_((flags & CANT_BOTH_BE_NAN) != 0),
4950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      include_number_compare_((flags & NO_NUMBER_COMPARE_IN_STUB) == 0),
4960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      include_smi_compare_((flags & NO_SMI_COMPARE_IN_STUB) == 0),
49780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      lhs_(lhs),
49880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      rhs_(rhs),
49980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      name_(NULL) { }
50080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
5010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  CompareStub(Condition cc,
5020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen              bool strict,
5030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen              CompareFlags flags) :
5040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      cc_(cc),
5050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      strict_(strict),
5060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      never_nan_nan_((flags & CANT_BOTH_BE_NAN) != 0),
5070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      include_number_compare_((flags & NO_NUMBER_COMPARE_IN_STUB) == 0),
5080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      include_smi_compare_((flags & NO_SMI_COMPARE_IN_STUB) == 0),
5090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      lhs_(no_reg),
5100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      rhs_(no_reg),
5110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      name_(NULL) { }
5120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
51380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void Generate(MacroAssembler* masm);
51480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
51580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen private:
51680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Condition cc_;
51780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  bool strict_;
51880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Only used for 'equal' comparisons.  Tells the stub that we already know
51980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // that at least one side of the comparison is not NaN.  This allows the
52080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // stub to use object identity in the positive case.  We ignore it when
52180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // generating the minor key for other comparisons to avoid creating more
52280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // stubs.
52380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  bool never_nan_nan_;
52480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Do generate the number comparison code in the stub. Stubs without number
52580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // comparison code is used when the number comparison has been inlined, and
52680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // the stub will be called if one of the operands is not a number.
52780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  bool include_number_compare_;
5280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Generate the comparison code for two smi operands in the stub.
5300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  bool include_smi_compare_;
5310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
53280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Register holding the left hand side of the comparison if the stub gives
53380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // a choice, no_reg otherwise.
534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
53580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register lhs_;
53680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Register holding the right hand side of the comparison if the stub gives
53780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // a choice, no_reg otherwise.
53880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register rhs_;
53980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
5400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Encoding of the minor key in 16 bits.
54180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  class StrictField: public BitField<bool, 0, 1> {};
54280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  class NeverNanNanField: public BitField<bool, 1, 1> {};
54380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  class IncludeNumberCompareField: public BitField<bool, 2, 1> {};
5440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  class IncludeSmiCompareField: public  BitField<bool, 3, 1> {};
5450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  class RegisterField: public BitField<bool, 4, 1> {};
5460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  class ConditionField: public BitField<int, 5, 11> {};
54780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
54880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Major MajorKey() { return Compare; }
54980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
55080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int MinorKey();
55180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
552b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  virtual int GetCodeKind() { return Code::COMPARE_IC; }
553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  virtual void FinishCode(Code* code) {
554b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    code->set_compare_state(CompareIC::GENERIC);
555b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
55780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Branch to the label if the given object isn't a symbol.
55880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void BranchIfNonSymbol(MacroAssembler* masm,
55980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                         Label* label,
56080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                         Register object,
56180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                         Register scratch);
56280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
56380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Unfortunately you have to run without snapshots to see most of these
56480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // names in the profile since most compare stubs end up in the snapshot.
56580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  char* name_;
56680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  const char* GetName();
56780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#ifdef DEBUG
56880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void Print() {
5690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    PrintF("CompareStub (minor %d) (cc %d), (strict %s), "
5700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen           "(never_nan_nan %s), (smi_compare %s) (number_compare %s) ",
5710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen           MinorKey(),
57280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen           static_cast<int>(cc_),
57380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen           strict_ ? "true" : "false",
57480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen           never_nan_nan_ ? "true" : "false",
5750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen           include_smi_compare_ ? "inluded" : "not included",
57680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen           include_number_compare_ ? "included" : "not included");
57780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
57880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if (!lhs_.is(no_reg) && !rhs_.is(no_reg)) {
57980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      PrintF("(lhs r%d), (rhs r%d)\n", lhs_.code(), rhs_.code());
58080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    } else {
58180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      PrintF("\n");
58280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
58380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
58480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#endif
58580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen};
58680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
58780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
58880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenclass CEntryStub : public CodeStub {
58980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen public:
590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  explicit CEntryStub(int result_size)
591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      : result_size_(result_size), save_doubles_(false) { }
59280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
59380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void Generate(MacroAssembler* masm);
594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void SaveDoubles() { save_doubles_ = true; }
59580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
59680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen private:
59780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void GenerateCore(MacroAssembler* masm,
59880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                    Label* throw_normal_exception,
59980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                    Label* throw_termination_exception,
60080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                    Label* throw_out_of_memory_exception,
60180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                    bool do_gc,
60280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                    bool always_allocate_scope,
60380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                    int alignment_skew = 0);
60480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void GenerateThrowTOS(MacroAssembler* masm);
60580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void GenerateThrowUncatchable(MacroAssembler* masm,
60680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                UncatchableExceptionType type);
60780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
60880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Number of pointers/values returned.
60980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  const int result_size_;
610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool save_doubles_;
61180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
61280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Major MajorKey() { return CEntry; }
61380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int MinorKey();
61480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
61580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  const char* GetName() { return "CEntryStub"; }
61680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen};
61780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
61880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
61980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenclass JSEntryStub : public CodeStub {
62080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen public:
62180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  JSEntryStub() { }
62280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
62380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void Generate(MacroAssembler* masm) { GenerateBody(masm, false); }
62480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
62580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen protected:
62680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void GenerateBody(MacroAssembler* masm, bool is_construct);
62780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
62880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen private:
62980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Major MajorKey() { return JSEntry; }
63080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int MinorKey() { return 0; }
63180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
63280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  const char* GetName() { return "JSEntryStub"; }
63380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen};
63480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
63580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
63680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenclass JSConstructEntryStub : public JSEntryStub {
63780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen public:
63880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  JSConstructEntryStub() { }
63980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
64080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void Generate(MacroAssembler* masm) { GenerateBody(masm, true); }
64180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
64280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen private:
64380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int MinorKey() { return 1; }
64480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
64580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  const char* GetName() { return "JSConstructEntryStub"; }
64680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen};
64780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
64880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
64980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenclass ArgumentsAccessStub: public CodeStub {
65080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen public:
65180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  enum Type {
65280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    READ_ELEMENT,
65380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    NEW_OBJECT
65480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  };
65580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
65680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  explicit ArgumentsAccessStub(Type type) : type_(type) { }
65780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
65880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen private:
65980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Type type_;
66080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
66180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Major MajorKey() { return ArgumentsAccess; }
66280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int MinorKey() { return type_; }
66380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
66480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void Generate(MacroAssembler* masm);
66580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void GenerateReadElement(MacroAssembler* masm);
66680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void GenerateNewObject(MacroAssembler* masm);
66780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
66880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  const char* GetName() { return "ArgumentsAccessStub"; }
66980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
67080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#ifdef DEBUG
67180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void Print() {
67280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    PrintF("ArgumentsAccessStub (type %d)\n", type_);
67380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
67480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#endif
67580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen};
67680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
67780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
67880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenclass RegExpExecStub: public CodeStub {
67980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen public:
68080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  RegExpExecStub() { }
68180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
68280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen private:
68380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Major MajorKey() { return RegExpExec; }
68480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int MinorKey() { return 0; }
68580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
68680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void Generate(MacroAssembler* masm);
68780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
68880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  const char* GetName() { return "RegExpExecStub"; }
68980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
69080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#ifdef DEBUG
69180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void Print() {
69280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    PrintF("RegExpExecStub\n");
69380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
69480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#endif
69580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen};
69680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
69780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass RegExpConstructResultStub: public CodeStub {
699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  RegExpConstructResultStub() { }
701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Major MajorKey() { return RegExpConstructResult; }
704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int MinorKey() { return 0; }
705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void Generate(MacroAssembler* masm);
707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const char* GetName() { return "RegExpConstructResultStub"; }
709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void Print() {
712b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintF("RegExpConstructResultStub\n");
713b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
71880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenclass CallFunctionStub: public CodeStub {
71980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen public:
72080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  CallFunctionStub(int argc, InLoopFlag in_loop, CallFunctionFlags flags)
72180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      : argc_(argc), in_loop_(in_loop), flags_(flags) { }
72280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
72380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void Generate(MacroAssembler* masm);
72480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
725086aeeaae12517475c22695a200be45495516549Ben Murdoch  static int ExtractArgcFromMinorKey(int minor_key) {
726086aeeaae12517475c22695a200be45495516549Ben Murdoch    return ArgcBits::decode(minor_key);
727086aeeaae12517475c22695a200be45495516549Ben Murdoch  }
728086aeeaae12517475c22695a200be45495516549Ben Murdoch
72980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen private:
73080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int argc_;
73180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  InLoopFlag in_loop_;
73280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  CallFunctionFlags flags_;
73380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
73480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#ifdef DEBUG
73580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void Print() {
73680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    PrintF("CallFunctionStub (args %d, in_loop %d, flags %d)\n",
73780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen           argc_,
73880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen           static_cast<int>(in_loop_),
73980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen           static_cast<int>(flags_));
74080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
74180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#endif
74280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
74380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Minor key encoding in 32 bits with Bitfield <Type, shift, size>.
74480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  class InLoopBits: public BitField<InLoopFlag, 0, 1> {};
74580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  class FlagBits: public BitField<CallFunctionFlags, 1, 1> {};
74680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  class ArgcBits: public BitField<int, 2, 32 - 2> {};
74780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
74880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Major MajorKey() { return CallFunction; }
74980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int MinorKey() {
75080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Encode the parameters in a unique 32 bit value.
75180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    return InLoopBits::encode(in_loop_)
75280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen           | FlagBits::encode(flags_)
75380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen           | ArgcBits::encode(argc_);
75480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
75580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
75680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  InLoopFlag InLoop() { return in_loop_; }
75780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  bool ReceiverMightBeValue() {
75880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    return (flags_ & RECEIVER_MIGHT_BE_VALUE) != 0;
75980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
76080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen};
76180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
76280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
76380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenenum StringIndexFlags {
76480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Accepts smis or heap numbers.
76580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  STRING_INDEX_IS_NUMBER,
76680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
76780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Accepts smis or heap numbers that are valid array indices
76880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // (ECMA-262 15.4). Invalid indices are reported as being out of
76980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // range.
77080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  STRING_INDEX_IS_ARRAY_INDEX
77180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen};
77280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
77380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
77480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// Generates code implementing String.prototype.charCodeAt.
77580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen//
77680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// Only supports the case when the receiver is a string and the index
77780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// is a number (smi or heap number) that is a valid index into the
77880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// string. Additional index constraints are specified by the
77980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// flags. Otherwise, bails out to the provided labels.
78080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen//
78180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// Register usage: |object| may be changed to another string in a way
78280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// that doesn't affect charCodeAt/charAt semantics, |index| is
78380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// preserved, |scratch| and |result| are clobbered.
78480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenclass StringCharCodeAtGenerator {
78580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen public:
78680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  StringCharCodeAtGenerator(Register object,
78780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            Register index,
78880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            Register scratch,
78980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            Register result,
79080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            Label* receiver_not_string,
79180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            Label* index_not_number,
79280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            Label* index_out_of_range,
79380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            StringIndexFlags index_flags)
79480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      : object_(object),
79580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        index_(index),
79680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        scratch_(scratch),
79780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        result_(result),
79880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        receiver_not_string_(receiver_not_string),
79980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        index_not_number_(index_not_number),
80080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        index_out_of_range_(index_out_of_range),
80180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        index_flags_(index_flags) {
80280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    ASSERT(!scratch_.is(object_));
80380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    ASSERT(!scratch_.is(index_));
80480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    ASSERT(!scratch_.is(result_));
80580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    ASSERT(!result_.is(object_));
80680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    ASSERT(!result_.is(index_));
80780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
80880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
80980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Generates the fast case code. On the fallthrough path |result|
81080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // register contains the result.
81180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void GenerateFast(MacroAssembler* masm);
81280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
81380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Generates the slow case code. Must not be naturally
81480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // reachable. Expected to be put after a ret instruction (e.g., in
81580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // deferred code). Always jumps back to the fast case.
81680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void GenerateSlow(MacroAssembler* masm,
81780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                    const RuntimeCallHelper& call_helper);
81880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
81980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen private:
82080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register object_;
82180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register index_;
82280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register scratch_;
82380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register result_;
82480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
82580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* receiver_not_string_;
82680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* index_not_number_;
82780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* index_out_of_range_;
82880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
82980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  StringIndexFlags index_flags_;
83080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
83180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label call_runtime_;
83280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label index_not_smi_;
83380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label got_smi_index_;
83480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label exit_;
83580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
83680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator);
83780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen};
83880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
83980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
84080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// Generates code for creating a one-char string from a char code.
84180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenclass StringCharFromCodeGenerator {
84280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen public:
84380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  StringCharFromCodeGenerator(Register code,
84480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                              Register result)
84580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      : code_(code),
84680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        result_(result) {
84780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    ASSERT(!code_.is(result_));
84880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
84980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
85080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Generates the fast case code. On the fallthrough path |result|
85180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // register contains the result.
85280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void GenerateFast(MacroAssembler* masm);
85380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
85480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Generates the slow case code. Must not be naturally
85580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // reachable. Expected to be put after a ret instruction (e.g., in
85680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // deferred code). Always jumps back to the fast case.
85780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void GenerateSlow(MacroAssembler* masm,
85880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                    const RuntimeCallHelper& call_helper);
85980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
86080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen private:
86180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register code_;
86280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register result_;
86380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
86480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label slow_case_;
86580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label exit_;
86680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
86780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  DISALLOW_COPY_AND_ASSIGN(StringCharFromCodeGenerator);
86880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen};
86980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
87080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
87180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// Generates code implementing String.prototype.charAt.
87280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen//
87380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// Only supports the case when the receiver is a string and the index
87480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// is a number (smi or heap number) that is a valid index into the
87580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// string. Additional index constraints are specified by the
87680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// flags. Otherwise, bails out to the provided labels.
87780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen//
87880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// Register usage: |object| may be changed to another string in a way
87980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// that doesn't affect charCodeAt/charAt semantics, |index| is
88080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// preserved, |scratch1|, |scratch2|, and |result| are clobbered.
88180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenclass StringCharAtGenerator {
88280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen public:
88380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  StringCharAtGenerator(Register object,
88480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                        Register index,
88580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                        Register scratch1,
88680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                        Register scratch2,
88780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                        Register result,
88880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                        Label* receiver_not_string,
88980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                        Label* index_not_number,
89080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                        Label* index_out_of_range,
89180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                        StringIndexFlags index_flags)
89280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      : char_code_at_generator_(object,
89380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                index,
89480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                scratch1,
89580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                scratch2,
89680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                receiver_not_string,
89780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                index_not_number,
89880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                index_out_of_range,
89980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                index_flags),
90080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        char_from_code_generator_(scratch2, result) {}
90180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
90280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Generates the fast case code. On the fallthrough path |result|
90380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // register contains the result.
90480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void GenerateFast(MacroAssembler* masm);
90580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
90680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Generates the slow case code. Must not be naturally
90780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // reachable. Expected to be put after a ret instruction (e.g., in
90880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // deferred code). Always jumps back to the fast case.
90980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void GenerateSlow(MacroAssembler* masm,
91080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                    const RuntimeCallHelper& call_helper);
91180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
91280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen private:
91380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  StringCharCodeAtGenerator char_code_at_generator_;
91480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  StringCharFromCodeGenerator char_from_code_generator_;
91580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
91680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  DISALLOW_COPY_AND_ASSIGN(StringCharAtGenerator);
91780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen};
91880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
919086aeeaae12517475c22695a200be45495516549Ben Murdoch
920086aeeaae12517475c22695a200be45495516549Ben Murdochclass AllowStubCallsScope {
921086aeeaae12517475c22695a200be45495516549Ben Murdoch public:
922086aeeaae12517475c22695a200be45495516549Ben Murdoch  AllowStubCallsScope(MacroAssembler* masm, bool allow)
923086aeeaae12517475c22695a200be45495516549Ben Murdoch       : masm_(masm), previous_allow_(masm->allow_stub_calls()) {
924086aeeaae12517475c22695a200be45495516549Ben Murdoch    masm_->set_allow_stub_calls(allow);
925086aeeaae12517475c22695a200be45495516549Ben Murdoch  }
926086aeeaae12517475c22695a200be45495516549Ben Murdoch  ~AllowStubCallsScope() {
927086aeeaae12517475c22695a200be45495516549Ben Murdoch    masm_->set_allow_stub_calls(previous_allow_);
928086aeeaae12517475c22695a200be45495516549Ben Murdoch  }
929086aeeaae12517475c22695a200be45495516549Ben Murdoch
930086aeeaae12517475c22695a200be45495516549Ben Murdoch private:
931086aeeaae12517475c22695a200be45495516549Ben Murdoch  MacroAssembler* masm_;
932086aeeaae12517475c22695a200be45495516549Ben Murdoch  bool previous_allow_;
933086aeeaae12517475c22695a200be45495516549Ben Murdoch
934086aeeaae12517475c22695a200be45495516549Ben Murdoch  DISALLOW_COPY_AND_ASSIGN(AllowStubCallsScope);
935086aeeaae12517475c22695a200be45495516549Ben Murdoch};
936086aeeaae12517475c22695a200be45495516549Ben Murdoch
937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // V8_CODE_STUBS_H_
940