ic.h revision 69a99ed0b2b2ef69d393c371b03db3a98aaf880e
1257744e915dfc84d6d07a6b2accf8402d9ffc708Ben 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_IC_H_
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define V8_IC_H_
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
31b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "macro-assembler.h"
32257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#include "type-info.h"
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
37e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// IC_UTIL_LIST defines all utility functions called from generated
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// inline caching code. The argument for the macro, ICU, is the function name.
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define IC_UTIL_LIST(ICU)                             \
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ICU(LoadIC_Miss)                                    \
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ICU(KeyedLoadIC_Miss)                               \
43257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ICU(KeyedLoadIC_MissForceGeneric)                   \
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ICU(CallIC_Miss)                                    \
457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ICU(KeyedCallIC_Miss)                               \
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ICU(StoreIC_Miss)                                   \
476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ICU(StoreIC_ArrayLength)                            \
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ICU(SharedStoreIC_ExtendStorage)                    \
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ICU(KeyedStoreIC_Miss)                              \
50257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ICU(KeyedStoreIC_MissForceGeneric)                  \
51257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ICU(KeyedStoreIC_Slow)                              \
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  /* Utilities for IC stubs. */                       \
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ICU(LoadCallbackProperty)                           \
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ICU(StoreCallbackProperty)                          \
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ICU(LoadPropertyWithInterceptorOnly)                \
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ICU(LoadPropertyWithInterceptorForLoad)             \
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ICU(LoadPropertyWithInterceptorForCall)             \
58402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ICU(KeyedLoadPropertyWithInterceptor)               \
596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ICU(StoreInterceptorProperty)                       \
60257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ICU(UnaryOp_Patch)                                  \
61257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ICU(BinaryOp_Patch)                                 \
6269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  ICU(CompareIC_Miss)                                 \
6369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  ICU(ToBoolean_Patch)
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// IC is the base class for LoadIC, StoreIC, CallIC, KeyedLoadIC,
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// and KeyedStoreIC.
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass IC {
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The ids for utility called from the generated code.
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  enum UtilityId {
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  #define CONST_NAME(name) k##name,
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    IC_UTIL_LIST(CONST_NAME)
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  #undef CONST_NAME
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    kUtilityCount
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Looks up the address of the named utility.
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static Address AddressFromUtilityId(UtilityId id);
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Alias the inline cache state type to make the IC code more readable.
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  typedef InlineCacheState State;
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The IC code is either invoked with no extra frames on the stack
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // or with a single extra frame for supporting calls.
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  enum FrameDepth {
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    NO_EXTRA_FRAME = 0,
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    EXTRA_CALL_FRAME = 1
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Construct the IC structure with the given number of extra
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // JavaScript frames on the stack.
9344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  IC(FrameDepth depth, Isolate* isolate);
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the call-site target; used for determining the state.
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Code* target() { return GetTargetAtAddress(address()); }
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline Address address();
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Compute the current IC state based on the target stub, receiver and name.
1006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static State StateFrom(Code* target, Object* receiver, Object* name);
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clear the inline cache to initial state.
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void Clear(Address address);
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Computes the reloc info for this IC. This is a fairly expensive
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // operation as it has to search through the heap to find the code
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object that contains this IC site.
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RelocInfo::Mode ComputeMode();
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Returns if this IC is for contextual (no explicit receiver)
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // access to properties.
112e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  bool IsContextual(Handle<Object> receiver) {
113e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    if (receiver->IsGlobalObject()) {
114e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      return SlowIsContextual();
115e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    } else {
116e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      ASSERT(!SlowIsContextual());
117e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      return false;
118e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
119e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
120e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
121e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  bool SlowIsContextual() {
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return ComputeMode() == RelocInfo::CODE_TARGET_CONTEXT;
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1258defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Determines which map must be used for keeping the code stub.
1268defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // These methods should not be called with undefined or null.
1278defd9ff6930b4e24729971a61cf7469daf119beSteve Block  static inline InlineCacheHolderFlag GetCodeCacheForObject(Object* object,
1288defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                                            JSObject* holder);
1298defd9ff6930b4e24729971a61cf7469daf119beSteve Block  static inline InlineCacheHolderFlag GetCodeCacheForObject(JSObject* object,
1308defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                                            JSObject* holder);
13180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  static inline JSObject* GetCodeCacheHolder(Object* object,
13280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                             InlineCacheHolderFlag holder);
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block protected:
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address fp() const { return fp_; }
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address pc() const { return *pc_address_; }
13744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate() const { return isolate_; }
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Computes the address in the original code when the code running is
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // containing break points (calls to DebugBreakXXX builtins).
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address OriginalCodeAddress();
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set the call-site target.
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void set_target(Code* code) { SetTargetAtAddress(address(), code); }
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void TraceIC(const char* type,
150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch               Handle<Object> name,
151257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch               State old_state,
152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch               Code* new_target,
153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch               const char* extra_info = "");
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Failure* TypeError(const char* type,
15744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     Handle<Object> object,
15844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     Handle<Object> key);
15944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Failure* ReferenceError(const char* type, Handle<String> name);
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Access the target code for the given IC address.
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static inline Code* GetTargetAtAddress(Address address);
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static inline void SetTargetAtAddress(Address address, Code* target);
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Frame pointer for the frame that uses (calls) the IC.
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address fp_;
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // All access to the program counter of an IC structure is indirect
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to make the code GC safe. This feature is crucial since
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // GetProperty and SetProperty are called and they in turn might
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // invoke the garbage collector.
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address* pc_address_;
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate_;
17644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// An IC_Utility encapsulates IC::UtilityId. It exists mainly because you
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// cannot make forward declarations to an enum.
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass IC_Utility {
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit IC_Utility(IC::UtilityId id)
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    : address_(IC::AddressFromUtilityId(id)), id_(id) {}
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address address() const { return address_; }
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  IC::UtilityId id() const { return id_; }
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address address_;
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  IC::UtilityId id_;
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochclass CallICBase: public IC {
198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch public:
199257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  class Contextual: public BitField<bool, 0, 1> {};
200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  class StringStubState: public BitField<StringStubFeedback, 1, 1> {};
201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch protected:
20344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CallICBase(Code::Kind kind, Isolate* isolate)
20444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : IC(EXTRA_CALL_FRAME, isolate), kind_(kind) {}
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch public:
2075913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  MUST_USE_RESULT MaybeObject* LoadFunction(State state,
208b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                            Code::ExtraICState extra_ic_state,
2095913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                            Handle<Object> object,
2105913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                            Handle<String> name);
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch protected:
2137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Code::Kind kind_;
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
215b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  bool TryUpdateExtraICState(LookupResult* lookup,
216b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                             Handle<Object> object,
217b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                             Code::ExtraICState* extra_ic_state);
218b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
219b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  MUST_USE_RESULT MaybeObject* ComputeMonomorphicStub(
220b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      LookupResult* lookup,
221b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      State state,
222b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      Code::ExtraICState extra_ic_state,
223b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      Handle<Object> object,
224b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      Handle<String> name);
225b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update the inline cache and the global stub cache based on the
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // lookup result.
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void UpdateCaches(LookupResult* lookup,
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    State state,
230b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                    Code::ExtraICState extra_ic_state,
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Handle<Object> object,
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Handle<String> name);
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Returns a JSFunction if the object can be called as a function,
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // and patches the stack to be ready for the call.
236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Otherwise, it returns the undefined value.
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Object* TryCallAsFunction(Object* object);
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
239e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void ReceiverToObjectIfRequired(Handle<Object> callee, Handle<Object> object);
240e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void Clear(Address address, Code* target);
242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class IC;
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochclass CallIC: public CallICBase {
2487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch public:
24944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  explicit CallIC(Isolate* isolate) : CallICBase(Code::CALL_IC, isolate) {
25044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(target()->is_call_stub());
25144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
2527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Code generator routines.
254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void GenerateInitialize(MacroAssembler* masm,
255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 int argc,
256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Code::ExtraICState extra_ic_state) {
257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    GenerateMiss(masm, argc, extra_ic_state);
258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void GenerateMiss(MacroAssembler* masm,
260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                           int argc,
261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                           Code::ExtraICState extra_ic_state);
262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void GenerateMegamorphic(MacroAssembler* masm,
263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                  int argc,
264257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                  Code::ExtraICState extra_ic_state);
2657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  static void GenerateNormal(MacroAssembler* masm, int argc);
2667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch};
2677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochclass KeyedCallIC: public CallICBase {
2707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch public:
27144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  explicit KeyedCallIC(Isolate* isolate)
27244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : CallICBase(Code::KEYED_CALL_IC, isolate) {
2737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    ASSERT(target()->is_keyed_call_stub());
2747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
2757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2765913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  MUST_USE_RESULT MaybeObject* LoadFunction(State state,
2775913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                            Handle<Object> object,
2785913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                            Handle<Object> key);
2797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Code generator routines.
2817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  static void GenerateInitialize(MacroAssembler* masm, int argc) {
2827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    GenerateMiss(masm, argc);
2837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
2847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  static void GenerateMiss(MacroAssembler* masm, int argc);
2857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  static void GenerateMegamorphic(MacroAssembler* masm, int argc);
2867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  static void GenerateNormal(MacroAssembler* masm, int argc);
2873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  static void GenerateNonStrictArguments(MacroAssembler* masm, int argc);
2887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch};
2897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass LoadIC: public IC {
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
29344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  explicit LoadIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {
29444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(target()->is_load_stub());
29544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2975913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  MUST_USE_RESULT MaybeObject* Load(State state,
2985913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                    Handle<Object> object,
2995913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                    Handle<String> name);
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Code generator routines.
302402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
303402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  static void GeneratePreMonomorphic(MacroAssembler* masm) {
304402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    GenerateMiss(masm);
305402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void GenerateMiss(MacroAssembler* masm);
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void GenerateMegamorphic(MacroAssembler* masm);
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void GenerateNormal(MacroAssembler* masm);
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Specialized code generator routines.
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void GenerateArrayLength(MacroAssembler* masm);
3121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static void GenerateStringLength(MacroAssembler* masm,
3131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                   bool support_wrappers);
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void GenerateFunctionPrototype(MacroAssembler* masm);
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update the inline cache and the global stub cache based on the
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // lookup result.
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void UpdateCaches(LookupResult* lookup,
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    State state,
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Handle<Object> object,
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Handle<String> name);
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stub accessors.
32544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Code* megamorphic_stub() {
32644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return isolate()->builtins()->builtin(
32744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Builtins::kLoadIC_Megamorphic);
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static Code* initialize_stub() {
33044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return Isolate::Current()->builtins()->builtin(
33144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Builtins::kLoadIC_Initialize);
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
33344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Code* pre_monomorphic_stub() {
33444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return isolate()->builtins()->builtin(
33544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Builtins::kLoadIC_PreMonomorphic);
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void Clear(Address address, Code* target);
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
340257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  friend class IC;
341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch};
342053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
343053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
344257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass KeyedIC: public IC {
345257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch public:
346257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  explicit KeyedIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {}
347257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  virtual ~KeyedIC() {}
348257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  virtual MaybeObject* GetElementStubWithoutMapCheck(
3503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      bool is_js_array,
3513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      JSObject::ElementsKind elements_kind) = 0;
352257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
353257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch protected:
354257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  virtual Code* string_stub() {
355257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return NULL;
356257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
357257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
358257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  virtual Code::Kind kind() const = 0;
359257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
360257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  MaybeObject* ComputeStub(JSObject* receiver,
361257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                           bool is_store,
362257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                           StrictModeFlag strict_mode,
363257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                           Code* default_stub);
364257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
365257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  virtual MaybeObject* ConstructMegamorphicStub(
366257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      MapList* receiver_maps,
367257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CodeList* targets,
368257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      StrictModeFlag strict_mode) = 0;
369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
370257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private:
371257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GetReceiverMapsForStub(Code* stub, MapList* result);
372257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
373257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  MaybeObject* ComputeMonomorphicStubWithoutMapCheck(
374257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Map* receiver_map,
3753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      StrictModeFlag strict_mode);
376257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
377257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  MaybeObject* ComputeMonomorphicStub(JSObject* receiver,
378257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                      bool is_store,
379257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                      StrictModeFlag strict_mode,
380257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                      Code* default_stub);
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
384257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass KeyedLoadIC: public KeyedIC {
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  explicit KeyedLoadIC(Isolate* isolate) : KeyedIC(isolate) {
38744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(target()->is_keyed_load_stub());
38844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3905913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  MUST_USE_RESULT MaybeObject* Load(State state,
3915913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                    Handle<Object> object,
392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Handle<Object> key,
393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    bool force_generic_stub);
394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Code generator routines.
396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void GenerateMiss(MacroAssembler* masm, bool force_generic);
397402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  static void GenerateRuntimeGetProperty(MacroAssembler* masm);
398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void GenerateInitialize(MacroAssembler* masm) {
399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    GenerateMiss(masm, false);
400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
401402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  static void GeneratePreMonomorphic(MacroAssembler* masm) {
402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    GenerateMiss(masm, false);
403402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void GenerateGeneric(MacroAssembler* masm);
405e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  static void GenerateString(MacroAssembler* masm);
406402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  static void GenerateIndexedInterceptor(MacroAssembler* masm);
4073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  static void GenerateNonStrictArguments(MacroAssembler* masm);
4083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
409d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Bit mask to be tested against bit field for the cases when
410d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // generic stub should go into slow case.
411d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Access check is necessary explicitly since generic stub does not perform
412d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // map checks.
413d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  static const int kSlowCaseBitFieldMask =
414d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor);
415d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
4163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  virtual MaybeObject* GetElementStubWithoutMapCheck(
4173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      bool is_js_array,
4183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      JSObject::ElementsKind elements_kind);
419257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
420257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch protected:
421257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  virtual Code::Kind kind() const { return Code::KEYED_LOAD_IC; }
422257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
423257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  virtual MaybeObject* ConstructMegamorphicStub(
424257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      MapList* receiver_maps,
425257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CodeList* targets,
426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      StrictModeFlag strict_mode);
427257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
428257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  virtual Code* string_stub() {
429257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return isolate()->builtins()->builtin(
430257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        Builtins::kKeyedLoadIC_String);
431257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update the inline cache.
435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void UpdateCaches(LookupResult* lookup,
436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    State state,
437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Handle<Object> object,
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Handle<String> name);
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stub accessors.
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static Code* initialize_stub() {
44244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return Isolate::Current()->builtins()->builtin(
44344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Builtins::kKeyedLoadIC_Initialize);
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
44544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Code* megamorphic_stub() {
44644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return isolate()->builtins()->builtin(
44744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Builtins::kKeyedLoadIC_Generic);
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
44944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Code* generic_stub() {
45044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return isolate()->builtins()->builtin(
45144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Builtins::kKeyedLoadIC_Generic);
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
45344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Code* pre_monomorphic_stub() {
45444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return isolate()->builtins()->builtin(
45544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Builtins::kKeyedLoadIC_PreMonomorphic);
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
45744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Code* indexed_interceptor_stub() {
45844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return isolate()->builtins()->builtin(
45944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Builtins::kKeyedLoadIC_IndexedInterceptor);
460402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
4613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Code* non_strict_arguments_stub() {
4623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return isolate()->builtins()->builtin(
4633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        Builtins::kKeyedLoadIC_NonStrictArguments);
4643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
465402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void Clear(Address address, Code* target);
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class IC;
469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass StoreIC: public IC {
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
47444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  explicit StoreIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {
47544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(target()->is_store_stub());
47644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4785913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  MUST_USE_RESULT MaybeObject* Store(State state,
479e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                     StrictModeFlag strict_mode,
4805913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                     Handle<Object> object,
4815913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                     Handle<String> name,
4825913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                     Handle<Object> value);
483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Code generators for stub routines. Only called once at startup.
4854515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void GenerateMiss(MacroAssembler* masm);
4871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static void GenerateMegamorphic(MacroAssembler* masm,
488e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                  StrictModeFlag strict_mode);
4896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static void GenerateArrayLength(MacroAssembler* masm);
4908defd9ff6930b4e24729971a61cf7469daf119beSteve Block  static void GenerateNormal(MacroAssembler* masm);
491e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  static void GenerateGlobalProxy(MacroAssembler* masm,
492e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                  StrictModeFlag strict_mode);
493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update the inline cache and the global stub cache based on the
496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // lookup result.
497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void UpdateCaches(LookupResult* lookup,
4981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                    State state,
499e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                    StrictModeFlag strict_mode,
5001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                    Handle<JSObject> receiver,
501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Handle<String> name,
502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Handle<Object> value);
503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
504e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void set_target(Code* code) {
505e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Strict mode must be preserved across IC patching.
506e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ASSERT((code->extra_ic_state() & kStrictMode) ==
507e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch           (target()->extra_ic_state() & kStrictMode));
508e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    IC::set_target(code);
509e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
510e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stub accessors.
51244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Code* megamorphic_stub() {
51344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return isolate()->builtins()->builtin(
51444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Builtins::kStoreIC_Megamorphic);
515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
51644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Code* megamorphic_stub_strict() {
51744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return isolate()->builtins()->builtin(
51844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Builtins::kStoreIC_Megamorphic_Strict);
5191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static Code* initialize_stub() {
52144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return Isolate::Current()->builtins()->builtin(
52244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Builtins::kStoreIC_Initialize);
523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static Code* initialize_stub_strict() {
52544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return Isolate::Current()->builtins()->builtin(
52644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Builtins::kStoreIC_Initialize_Strict);
5271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
52844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Code* global_proxy_stub() {
52944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return isolate()->builtins()->builtin(
53044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Builtins::kStoreIC_GlobalProxy);
531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
53244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Code* global_proxy_stub_strict() {
53344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return isolate()->builtins()->builtin(
53444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Builtins::kStoreIC_GlobalProxy_Strict);
5351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void Clear(Address address, Code* target);
53850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class IC;
540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
543257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass KeyedStoreIC: public KeyedIC {
544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
545257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  explicit KeyedStoreIC(Isolate* isolate) : KeyedIC(isolate) {
546257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(target()->is_keyed_store_stub());
547257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5495913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  MUST_USE_RESULT MaybeObject* Store(State state,
550257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   StrictModeFlag strict_mode,
5515913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                     Handle<Object> object,
5525913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                     Handle<Object> name,
553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Handle<Object> value,
554257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     bool force_generic);
555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Code generators for stub routines.  Only called once at startup.
557257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void GenerateInitialize(MacroAssembler* masm) {
558257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    GenerateMiss(masm, false);
559257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
560257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void GenerateMiss(MacroAssembler* masm, bool force_generic);
561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void GenerateSlow(MacroAssembler* masm);
562e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  static void GenerateRuntimeSetProperty(MacroAssembler* masm,
563e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         StrictModeFlag strict_mode);
564e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  static void GenerateGeneric(MacroAssembler* masm, StrictModeFlag strict_mode);
5653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  static void GenerateNonStrictArguments(MacroAssembler* masm);
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  virtual MaybeObject* GetElementStubWithoutMapCheck(
5683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      bool is_js_array,
5693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      JSObject::ElementsKind elements_kind);
570053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
571257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch protected:
572257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  virtual Code::Kind kind() const { return Code::KEYED_STORE_IC; }
573257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
574257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  virtual MaybeObject* ConstructMegamorphicStub(
575257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      MapList* receiver_maps,
576257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CodeList* targets,
577257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      StrictModeFlag strict_mode);
578257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
579257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  private:
580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update the inline cache.
581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void UpdateCaches(LookupResult* lookup,
582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    State state,
583e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                    StrictModeFlag strict_mode,
584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Handle<JSObject> receiver,
585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Handle<String> name,
586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Handle<Object> value);
587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
588e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void set_target(Code* code) {
589e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Strict mode must be preserved across IC patching.
590e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ASSERT((code->extra_ic_state() & kStrictMode) ==
591e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch           (target()->extra_ic_state() & kStrictMode));
592e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    IC::set_target(code);
593e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
594e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stub accessors.
596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static Code* initialize_stub() {
59744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return Isolate::Current()->builtins()->builtin(
59844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Builtins::kKeyedStoreIC_Initialize);
599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
60044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Code* megamorphic_stub() {
60144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return isolate()->builtins()->builtin(
60244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Builtins::kKeyedStoreIC_Generic);
603e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
60444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static Code* initialize_stub_strict() {
60544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return Isolate::Current()->builtins()->builtin(
60644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Builtins::kKeyedStoreIC_Initialize_Strict);
607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
60844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Code* megamorphic_stub_strict() {
60944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return isolate()->builtins()->builtin(
61044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Builtins::kKeyedStoreIC_Generic_Strict);
611e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
61244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Code* generic_stub() {
61344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return isolate()->builtins()->builtin(
61444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Builtins::kKeyedStoreIC_Generic);
615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
61644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Code* generic_stub_strict() {
61744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return isolate()->builtins()->builtin(
61844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Builtins::kKeyedStoreIC_Generic_Strict);
619e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
6203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Code* non_strict_arguments_stub() {
6213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return isolate()->builtins()->builtin(
6223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        Builtins::kKeyedStoreIC_NonStrictArguments);
6233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void Clear(Address address, Code* target);
626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class IC;
628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
631257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass UnaryOpIC: public IC {
632257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch public:
633257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // sorted: increasingly more unspecific (ignoring UNINITIALIZED)
634257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // TODO(svenpanne) Using enums+switch is an antipattern, use a class instead.
635257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  enum TypeInfo {
636257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    UNINITIALIZED,
637257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    SMI,
638257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HEAP_NUMBER,
639257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    GENERIC
640257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  };
641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
642257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  explicit UnaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
643257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void patch(Code* code);
645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static const char* GetName(TypeInfo type_info);
647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static State ToState(TypeInfo type_info);
649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static TypeInfo GetTypeInfo(Handle<Object> operand);
651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
652257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static TypeInfo ComputeNewType(TypeInfo type, TypeInfo previous);
653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch};
654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Type Recording BinaryOpIC, that records the types of the inputs and outputs.
657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass BinaryOpIC: public IC {
658b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  enum TypeInfo {
660b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    UNINITIALIZED,
661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    SMI,
662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    INT32,
663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HEAP_NUMBER,
66444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ODDBALL,
665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    BOTH_STRING,  // Only used for addition operation.
666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    STRING,  // Only used for addition operation.  At least one string operand.
667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    GENERIC
668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  };
669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  explicit BinaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void patch(Code* code);
673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static const char* GetName(TypeInfo type_info);
675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static State ToState(TypeInfo type_info);
677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static TypeInfo GetTypeInfo(Handle<Object> left, Handle<Object> right);
679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static TypeInfo JoinTypes(TypeInfo x, TypeInfo y);
681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass CompareIC: public IC {
685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  enum State {
687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    UNINITIALIZED,
688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    SMIS,
689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HEAP_NUMBERS,
690257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    SYMBOLS,
691257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    STRINGS,
692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    OBJECTS,
693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    GENERIC
694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  };
695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
69644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CompareIC(Isolate* isolate, Token::Value op)
69744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : IC(EXTRA_CALL_FRAME, isolate), op_(op) { }
698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Update the inline cache for the given operands.
700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void UpdateCaches(Handle<Object> x, Handle<Object> y);
701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Factory method for getting an uninitialized compare stub.
703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static Handle<Code> GetUninitialized(Token::Value op);
704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Helper function for computing the condition for a compare operation.
706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static Condition ComputeCondition(Token::Value op);
707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Helper function for determining the state of a compare IC.
709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static State ComputeState(Code* target);
710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static const char* GetStateName(State state);
712b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
713b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  State TargetState(State state, bool has_inlined_smi_code,
715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    Handle<Object> x, Handle<Object> y);
716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool strict() const { return op_ == Token::EQ_STRICT; }
718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Condition GetCondition() const { return ComputeCondition(op_); }
719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  State GetState() { return ComputeState(target()); }
720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Token::Value op_;
722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
72469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
72569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochclass ToBooleanIC: public IC {
72669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch public:
72769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  explicit ToBooleanIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
72869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
72969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  void patch(Code* code);
73069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch};
73169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
73269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Helper for BinaryOpIC and CompareIC.
734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid PatchInlinedSmiCode(Address address);
735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // V8_IC_H_
739