13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 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);
943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual ~IC() {}
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the call-site target; used for determining the state.
973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Code* target() const { return GetTargetAtAddress(address()); }
983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline Address address() const;
993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual bool IsGeneric() const { return false; }
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Compute the current IC state based on the target stub, receiver and name.
1036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static State StateFrom(Code* target, Object* receiver, Object* name);
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clear the inline cache to initial state.
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void Clear(Address address);
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Computes the reloc info for this IC. This is a fairly expensive
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // operation as it has to search through the heap to find the code
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object that contains this IC site.
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RelocInfo::Mode ComputeMode();
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Returns if this IC is for contextual (no explicit receiver)
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // access to properties.
115e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  bool IsContextual(Handle<Object> receiver) {
116e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    if (receiver->IsGlobalObject()) {
117e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      return SlowIsContextual();
118e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    } else {
119e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      ASSERT(!SlowIsContextual());
120e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      return false;
121e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
122e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
123e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
124e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  bool SlowIsContextual() {
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return ComputeMode() == RelocInfo::CODE_TARGET_CONTEXT;
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1288defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Determines which map must be used for keeping the code stub.
1298defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // These methods should not be called with undefined or null.
1308defd9ff6930b4e24729971a61cf7469daf119beSteve Block  static inline InlineCacheHolderFlag GetCodeCacheForObject(Object* object,
1318defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                                            JSObject* holder);
1328defd9ff6930b4e24729971a61cf7469daf119beSteve Block  static inline InlineCacheHolderFlag GetCodeCacheForObject(JSObject* object,
1338defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                                            JSObject* holder);
13480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  static inline JSObject* GetCodeCacheHolder(Object* object,
13580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                             InlineCacheHolderFlag holder);
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block protected:
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address fp() const { return fp_; }
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address pc() const { return *pc_address_; }
14044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate() const { return isolate_; }
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Computes the address in the original code when the code running is
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // containing break points (calls to DebugBreakXXX builtins).
1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address OriginalCodeAddress() const;
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set the call-site target.
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void set_target(Code* code) { SetTargetAtAddress(address(), code); }
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  char TransitionMarkFromState(IC::State state);
1533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void TraceIC(const char* type,
155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch               Handle<Object> name,
156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch               State old_state,
157589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch               Code* new_target);
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Failure* TypeError(const char* type,
16144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     Handle<Object> object,
16244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     Handle<Object> key);
16344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Failure* ReferenceError(const char* type, Handle<String> name);
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Access the target code for the given IC address.
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static inline Code* GetTargetAtAddress(Address address);
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static inline void SetTargetAtAddress(Address address, Code* target);
1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void PostPatching(Address address, Code* target, Code* old_target);
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Frame pointer for the frame that uses (calls) the IC.
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address fp_;
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // All access to the program counter of an IC structure is indirect
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to make the code GC safe. This feature is crucial since
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // GetProperty and SetProperty are called and they in turn might
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // invoke the garbage collector.
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address* pc_address_;
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
18044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate_;
18144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// An IC_Utility encapsulates IC::UtilityId. It exists mainly because you
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// cannot make forward declarations to an enum.
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass IC_Utility {
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit IC_Utility(IC::UtilityId id)
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    : address_(IC::AddressFromUtilityId(id)), id_(id) {}
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address address() const { return address_; }
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  IC::UtilityId id() const { return id_; }
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address address_;
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  IC::UtilityId id_;
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochclass CallICBase: public IC {
203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch public:
204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  class Contextual: public BitField<bool, 0, 1> {};
205257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  class StringStubState: public BitField<StringStubFeedback, 1, 1> {};
206257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Returns a JSFunction or a Failure.
2085913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  MUST_USE_RESULT MaybeObject* LoadFunction(State state,
209b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                            Code::ExtraICState extra_ic_state,
2105913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                            Handle<Object> object,
2115913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                            Handle<String> name);
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch protected:
2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallICBase(Code::Kind kind, Isolate* isolate)
2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : IC(EXTRA_CALL_FRAME, isolate), kind_(kind) {}
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
217b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  bool TryUpdateExtraICState(LookupResult* lookup,
218b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                             Handle<Object> object,
219b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                             Code::ExtraICState* extra_ic_state);
220b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Compute a monomorphic stub if possible, otherwise return a null handle.
2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ComputeMonomorphicStub(LookupResult* lookup,
2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      State state,
2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Code::ExtraICState extra_state,
2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Handle<Object> object,
2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Handle<String> name);
227b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Update the inline cache and the global stub cache based on the lookup
2293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // result.
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void UpdateCaches(LookupResult* lookup,
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    State state,
232b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                    Code::ExtraICState extra_ic_state,
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Handle<Object> object,
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Handle<String> name);
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Returns a JSFunction if the object can be called as a function, and
2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // patches the stack to be ready for the call.  Otherwise, it returns the
2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // undefined value.
2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Object> TryCallAsFunction(Handle<Object> object);
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
241e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void ReceiverToObjectIfRequired(Handle<Object> callee, Handle<Object> object);
242e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void Clear(Address address, Code* target);
244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Platform-specific code generation functions used by both call and
2463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // keyed call.
2473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void GenerateMiss(MacroAssembler* masm,
2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           int argc,
2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           IC::UtilityId id,
2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Code::ExtraICState extra_state);
2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void GenerateNormal(MacroAssembler* masm, int argc);
2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void GenerateMonomorphicCacheProbe(MacroAssembler* masm,
2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            int argc,
2563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            Code::Kind kind,
2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            Code::ExtraICState extra_state);
2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Code::Kind kind_;
2603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class IC;
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochclass CallIC: public CallICBase {
2667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch public:
26744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  explicit CallIC(Isolate* isolate) : CallICBase(Code::CALL_IC, isolate) {
26844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(target()->is_call_stub());
26944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
2707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Code generator routines.
272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void GenerateInitialize(MacroAssembler* masm,
273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 int argc,
2743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Code::ExtraICState extra_state) {
2753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GenerateMiss(masm, argc, extra_state);
276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void GenerateMiss(MacroAssembler* masm,
279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                           int argc,
2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Code::ExtraICState extra_state) {
2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallICBase::GenerateMiss(masm, argc, IC::kCallIC_Miss, extra_state);
2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
284257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void GenerateMegamorphic(MacroAssembler* masm,
285257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                  int argc,
286257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                  Code::ExtraICState extra_ic_state);
2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void GenerateNormal(MacroAssembler* masm, int argc) {
2893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallICBase::GenerateNormal(masm, argc);
2903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GenerateMiss(masm, argc, Code::kNoExtraICState);
2913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch};
2937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochclass KeyedCallIC: public CallICBase {
2967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch public:
29744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  explicit KeyedCallIC(Isolate* isolate)
29844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : CallICBase(Code::KEYED_CALL_IC, isolate) {
2997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    ASSERT(target()->is_keyed_call_stub());
3007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
3017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3025913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  MUST_USE_RESULT MaybeObject* LoadFunction(State state,
3035913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                            Handle<Object> object,
3045913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                            Handle<Object> key);
3057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Code generator routines.
3077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  static void GenerateInitialize(MacroAssembler* masm, int argc) {
3087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    GenerateMiss(masm, argc);
3097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
3103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void GenerateMiss(MacroAssembler* masm, int argc) {
3123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallICBase::GenerateMiss(masm, argc, IC::kKeyedCallIC_Miss,
3133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             Code::kNoExtraICState);
3143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  static void GenerateMegamorphic(MacroAssembler* masm, int argc);
3177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  static void GenerateNormal(MacroAssembler* masm, int argc);
3183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  static void GenerateNonStrictArguments(MacroAssembler* masm, int argc);
3197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch};
3207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass LoadIC: public IC {
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
32444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  explicit LoadIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {
32544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(target()->is_load_stub());
32644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3285913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  MUST_USE_RESULT MaybeObject* Load(State state,
3295913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                    Handle<Object> object,
3305913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                    Handle<String> name);
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Code generator routines.
333402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
334402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  static void GeneratePreMonomorphic(MacroAssembler* masm) {
335402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    GenerateMiss(masm);
336402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void GenerateMiss(MacroAssembler* masm);
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void GenerateMegamorphic(MacroAssembler* masm);
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void GenerateNormal(MacroAssembler* masm);
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Specialized code generator routines.
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void GenerateArrayLength(MacroAssembler* masm);
3431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static void GenerateStringLength(MacroAssembler* masm,
3441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                   bool support_wrappers);
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void GenerateFunctionPrototype(MacroAssembler* masm);
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update the inline cache and the global stub cache based on the
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // lookup result.
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void UpdateCaches(LookupResult* lookup,
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    State state,
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Handle<Object> object,
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Handle<String> name);
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stub accessors.
3563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> megamorphic_stub() {
3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return isolate()->builtins()->LoadIC_Megamorphic();
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static Code* initialize_stub() {
36044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return Isolate::Current()->builtins()->builtin(
36144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Builtins::kLoadIC_Initialize);
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> pre_monomorphic_stub() {
3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return isolate()->builtins()->LoadIC_PreMonomorphic();
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void Clear(Address address, Code* target);
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  friend class IC;
370257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch};
371053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
372053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
373257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass KeyedIC: public IC {
374257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch public:
3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  enum StubKind {
3763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LOAD,
3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    STORE_NO_TRANSITION,
3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    STORE_TRANSITION_SMI_TO_OBJECT,
3793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    STORE_TRANSITION_SMI_TO_DOUBLE,
3803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    STORE_TRANSITION_DOUBLE_TO_OBJECT,
3813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    STORE_AND_GROW_NO_TRANSITION,
3823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT,
3833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE,
3843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    STORE_AND_GROW_TRANSITION_DOUBLE_TO_OBJECT
3853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
3863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int kGrowICDelta = STORE_AND_GROW_NO_TRANSITION -
3883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      STORE_NO_TRANSITION;
3893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(kGrowICDelta ==
3903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT -
3913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                STORE_TRANSITION_SMI_TO_OBJECT);
3923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(kGrowICDelta ==
3933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE -
3943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                STORE_TRANSITION_SMI_TO_DOUBLE);
3953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(kGrowICDelta ==
3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                STORE_AND_GROW_TRANSITION_DOUBLE_TO_OBJECT -
3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                STORE_TRANSITION_DOUBLE_TO_OBJECT);
3983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  explicit KeyedIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {}
400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  virtual ~KeyedIC() {}
401257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static inline KeyedAccessGrowMode GetGrowModeFromStubKind(
4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      StubKind stub_kind) {
4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return (stub_kind >= STORE_AND_GROW_NO_TRANSITION)
4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ? ALLOW_JSARRAY_GROWTH
4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : DO_NOT_ALLOW_JSARRAY_GROWTH;
4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static inline StubKind GetGrowStubKind(StubKind stub_kind) {
4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(stub_kind != LOAD);
4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (stub_kind < STORE_AND_GROW_NO_TRANSITION) {
4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      stub_kind = static_cast<StubKind>(static_cast<int>(stub_kind) +
4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        kGrowICDelta);
4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return stub_kind;
4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual Handle<Code> GetElementStubWithoutMapCheck(
4193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      bool is_js_array,
4203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ElementsKind elements_kind,
4213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      KeyedAccessGrowMode grow_mode) = 0;
422257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
423257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch protected:
4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual Handle<Code> string_stub() {
4253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Handle<Code>::null();
426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
427257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
428257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  virtual Code::Kind kind() const = 0;
429257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ComputeStub(Handle<JSObject> receiver,
4313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           StubKind stub_kind,
432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                           StrictModeFlag strict_mode,
4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Handle<Code> default_stub);
434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual Handle<Code> ComputePolymorphicStub(
4363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      MapHandleList* receiver_maps,
4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      StrictModeFlag strict_mode,
4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      KeyedAccessGrowMode grow_mode) = 0;
439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ComputeMonomorphicStubWithoutMapCheck(
4413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<Map> receiver_map,
4423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      StrictModeFlag strict_mode,
4433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      KeyedAccessGrowMode grow_mode);
444592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
4453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private:
4463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void GetReceiverMapsForStub(Handle<Code> stub, MapHandleList* result);
4475d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
4483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ComputeMonomorphicStub(Handle<JSObject> receiver,
4493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      StubKind stub_kind,
45085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch                                      StrictModeFlag strict_mode,
4513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Handle<Code> default_stub);
4523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Map> ComputeTransitionedMap(Handle<JSObject> receiver,
4543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     StubKind stub_kind);
4553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static bool IsTransitionStubKind(StubKind stub_kind) {
4573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return stub_kind > STORE_NO_TRANSITION &&
4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        stub_kind != STORE_AND_GROW_NO_TRANSITION;
4593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static bool IsGrowStubKind(StubKind stub_kind) {
4623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return stub_kind >= STORE_AND_GROW_NO_TRANSITION;
4633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass KeyedLoadIC: public KeyedIC {
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  explicit KeyedLoadIC(Isolate* isolate) : KeyedIC(isolate) {
47044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(target()->is_keyed_load_stub());
47144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4735913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  MUST_USE_RESULT MaybeObject* Load(State state,
4745913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                    Handle<Object> object,
475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Handle<Object> key,
476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    bool force_generic_stub);
477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Code generator routines.
479257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void GenerateMiss(MacroAssembler* masm, bool force_generic);
480402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  static void GenerateRuntimeGetProperty(MacroAssembler* masm);
481257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void GenerateInitialize(MacroAssembler* masm) {
482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    GenerateMiss(masm, false);
483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
484402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  static void GeneratePreMonomorphic(MacroAssembler* masm) {
485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    GenerateMiss(masm, false);
486402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void GenerateGeneric(MacroAssembler* masm);
488e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  static void GenerateString(MacroAssembler* masm);
489402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  static void GenerateIndexedInterceptor(MacroAssembler* masm);
4903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  static void GenerateNonStrictArguments(MacroAssembler* masm);
4913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
492d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Bit mask to be tested against bit field for the cases when
493d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // generic stub should go into slow case.
494d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Access check is necessary explicitly since generic stub does not perform
495d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // map checks.
496d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  static const int kSlowCaseBitFieldMask =
497d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor);
498d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual Handle<Code> GetElementStubWithoutMapCheck(
5003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      bool is_js_array,
5013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ElementsKind elements_kind,
5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      KeyedAccessGrowMode grow_mode);
5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual bool IsGeneric() const {
5053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return target() == *generic_stub();
5063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
507c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
508257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch protected:
509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  virtual Code::Kind kind() const { return Code::KEYED_LOAD_IC; }
510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
5113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual Handle<Code> ComputePolymorphicStub(MapHandleList* receiver_maps,
5123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              StrictModeFlag strict_mode,
5133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              KeyedAccessGrowMode grow_mode);
514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
5153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual Handle<Code> string_stub() {
5163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return isolate()->builtins()->KeyedLoadIC_String();
517257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
518257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
5196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update the inline cache.
521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void UpdateCaches(LookupResult* lookup,
522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    State state,
523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Handle<Object> object,
524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Handle<String> name);
525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stub accessors.
527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static Code* initialize_stub() {
52844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return Isolate::Current()->builtins()->builtin(
52944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Builtins::kKeyedLoadIC_Initialize);
530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> megamorphic_stub() {
5323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return isolate()->builtins()->KeyedLoadIC_Generic();
533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> generic_stub() const {
5353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return isolate()->builtins()->KeyedLoadIC_Generic();
536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> pre_monomorphic_stub() {
5383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return isolate()->builtins()->KeyedLoadIC_PreMonomorphic();
539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> indexed_interceptor_stub() {
5413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return isolate()->builtins()->KeyedLoadIC_IndexedInterceptor();
542402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
5433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> non_strict_arguments_stub() {
5443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return isolate()->builtins()->KeyedLoadIC_NonStrictArguments();
5453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
546402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void Clear(Address address, Code* target);
548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class IC;
550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass StoreIC: public IC {
554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
55544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  explicit StoreIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {
55644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(target()->is_store_stub());
55744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5595913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  MUST_USE_RESULT MaybeObject* Store(State state,
560e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                     StrictModeFlag strict_mode,
5615913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                     Handle<Object> object,
5625913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                     Handle<String> name,
5635913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                     Handle<Object> value);
564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Code generators for stub routines. Only called once at startup.
5664515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void GenerateMiss(MacroAssembler* masm);
5681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static void GenerateMegamorphic(MacroAssembler* masm,
569e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                  StrictModeFlag strict_mode);
5706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static void GenerateArrayLength(MacroAssembler* masm);
5718defd9ff6930b4e24729971a61cf7469daf119beSteve Block  static void GenerateNormal(MacroAssembler* masm);
572e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  static void GenerateGlobalProxy(MacroAssembler* masm,
573e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                  StrictModeFlag strict_mode);
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update the inline cache and the global stub cache based on the
577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // lookup result.
578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void UpdateCaches(LookupResult* lookup,
5791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                    State state,
580e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                    StrictModeFlag strict_mode,
5811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                    Handle<JSObject> receiver,
582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Handle<String> name,
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Handle<Object> value);
584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
585e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void set_target(Code* code) {
586e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Strict mode must be preserved across IC patching.
5873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(Code::GetStrictMode(code->extra_ic_state()) ==
5883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Code::GetStrictMode(target()->extra_ic_state()));
589e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    IC::set_target(code);
590e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
591e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stub accessors.
59344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Code* megamorphic_stub() {
59444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return isolate()->builtins()->builtin(
59544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Builtins::kStoreIC_Megamorphic);
596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
59744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Code* megamorphic_stub_strict() {
59844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return isolate()->builtins()->builtin(
59944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Builtins::kStoreIC_Megamorphic_Strict);
6001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static Code* initialize_stub() {
60244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return Isolate::Current()->builtins()->builtin(
60344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Builtins::kStoreIC_Initialize);
604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
6051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static Code* initialize_stub_strict() {
60644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return Isolate::Current()->builtins()->builtin(
60744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Builtins::kStoreIC_Initialize_Strict);
6081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
6093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> global_proxy_stub() {
6103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return isolate()->builtins()->StoreIC_GlobalProxy();
611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
6123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> global_proxy_stub_strict() {
6133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return isolate()->builtins()->StoreIC_GlobalProxy_Strict();
6141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void Clear(Address address, Code* target);
61750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class IC;
619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
622257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass KeyedStoreIC: public KeyedIC {
623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  explicit KeyedStoreIC(Isolate* isolate) : KeyedIC(isolate) {
625257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(target()->is_keyed_store_stub());
626257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6285913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  MUST_USE_RESULT MaybeObject* Store(State state,
629257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   StrictModeFlag strict_mode,
6305913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                     Handle<Object> object,
6315913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                     Handle<Object> name,
632257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Handle<Object> value,
633257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     bool force_generic);
634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Code generators for stub routines.  Only called once at startup.
636257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void GenerateInitialize(MacroAssembler* masm) {
637257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    GenerateMiss(masm, false);
638257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
639257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void GenerateMiss(MacroAssembler* masm, bool force_generic);
640257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void GenerateSlow(MacroAssembler* masm);
641e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  static void GenerateRuntimeSetProperty(MacroAssembler* masm,
642e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         StrictModeFlag strict_mode);
643e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  static void GenerateGeneric(MacroAssembler* masm, StrictModeFlag strict_mode);
6443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  static void GenerateNonStrictArguments(MacroAssembler* masm);
6453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void GenerateTransitionElementsSmiToDouble(MacroAssembler* masm);
6463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void GenerateTransitionElementsDoubleToObject(MacroAssembler* masm);
647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual Handle<Code> GetElementStubWithoutMapCheck(
6493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      bool is_js_array,
6503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ElementsKind elements_kind,
6513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      KeyedAccessGrowMode grow_mode);
6523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual bool IsGeneric() const {
6543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return target() == *generic_stub() ||
6553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        target() == *generic_stub_strict();
6563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
657c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch protected:
659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  virtual Code::Kind kind() const { return Code::KEYED_STORE_IC; }
660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual Handle<Code> ComputePolymorphicStub(MapHandleList* receiver_maps,
6623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              StrictModeFlag strict_mode,
6633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              KeyedAccessGrowMode grow_mode);
664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  private:
666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update the inline cache.
667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void UpdateCaches(LookupResult* lookup,
668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    State state,
669e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                    StrictModeFlag strict_mode,
670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Handle<JSObject> receiver,
671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Handle<String> name,
672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Handle<Object> value);
673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
674e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void set_target(Code* code) {
675e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Strict mode must be preserved across IC patching.
6763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(Code::GetStrictMode(code->extra_ic_state()) ==
6773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Code::GetStrictMode(target()->extra_ic_state()));
678e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    IC::set_target(code);
679e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
680e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stub accessors.
682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static Code* initialize_stub() {
68344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return Isolate::Current()->builtins()->builtin(
68444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Builtins::kKeyedStoreIC_Initialize);
685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
68644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static Code* initialize_stub_strict() {
68744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return Isolate::Current()->builtins()->builtin(
68844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Builtins::kKeyedStoreIC_Initialize_Strict);
689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
6903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> megamorphic_stub() {
6913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return isolate()->builtins()->KeyedStoreIC_Generic();
692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
6933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> megamorphic_stub_strict() {
6943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return isolate()->builtins()->KeyedStoreIC_Generic_Strict();
695e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
6963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> generic_stub() const {
6973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return isolate()->builtins()->KeyedStoreIC_Generic();
698592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
6993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> generic_stub_strict() const {
7003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return isolate()->builtins()->KeyedStoreIC_Generic_Strict();
7013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
7023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> non_strict_arguments_stub() {
7033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return isolate()->builtins()->KeyedStoreIC_NonStrictArguments();
7043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void Clear(Address address, Code* target);
707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StubKind GetStubKind(Handle<JSObject> receiver,
7093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       Handle<Object> key,
7103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       Handle<Object> value);
7113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class IC;
713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
716257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass UnaryOpIC: public IC {
717257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch public:
718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // sorted: increasingly more unspecific (ignoring UNINITIALIZED)
719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // TODO(svenpanne) Using enums+switch is an antipattern, use a class instead.
720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  enum TypeInfo {
721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    UNINITIALIZED,
722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    SMI,
723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HEAP_NUMBER,
724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    GENERIC
725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  };
726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
727257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  explicit UnaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void patch(Code* code);
730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static const char* GetName(TypeInfo type_info);
732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static State ToState(TypeInfo type_info);
734257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static TypeInfo GetTypeInfo(Handle<Object> operand);
736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
737257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static TypeInfo ComputeNewType(TypeInfo type, TypeInfo previous);
738257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch};
739257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
740257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Type Recording BinaryOpIC, that records the types of the inputs and outputs.
742257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass BinaryOpIC: public IC {
743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  enum TypeInfo {
745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    UNINITIALIZED,
746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    SMI,
747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    INT32,
748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HEAP_NUMBER,
74944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ODDBALL,
750257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    BOTH_STRING,  // Only used for addition operation.
751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    STRING,  // Only used for addition operation.  At least one string operand.
752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    GENERIC
753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  };
754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
755257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  explicit BinaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void patch(Code* code);
758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static const char* GetName(TypeInfo type_info);
760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static State ToState(TypeInfo type_info);
762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static TypeInfo GetTypeInfo(Handle<Object> left, Handle<Object> right);
764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static TypeInfo JoinTypes(TypeInfo x, TypeInfo y);
766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass CompareIC: public IC {
770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  enum State {
772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    UNINITIALIZED,
773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    SMIS,
774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HEAP_NUMBERS,
775257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    SYMBOLS,
776257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    STRINGS,
777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    OBJECTS,
7783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    KNOWN_OBJECTS,
779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    GENERIC
780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  };
781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
78244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CompareIC(Isolate* isolate, Token::Value op)
78344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : IC(EXTRA_CALL_FRAME, isolate), op_(op) { }
784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Update the inline cache for the given operands.
786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void UpdateCaches(Handle<Object> x, Handle<Object> y);
787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Factory method for getting an uninitialized compare stub.
789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static Handle<Code> GetUninitialized(Token::Value op);
790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Helper function for computing the condition for a compare operation.
792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static Condition ComputeCondition(Token::Value op);
793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
794b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Helper function for determining the state of a compare IC.
795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static State ComputeState(Code* target);
796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
797b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static const char* GetStateName(State state);
798b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
799b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  State TargetState(State state, bool has_inlined_smi_code,
801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    Handle<Object> x, Handle<Object> y);
802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
803b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool strict() const { return op_ == Token::EQ_STRICT; }
804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Condition GetCondition() const { return ComputeCondition(op_); }
805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  State GetState() { return ComputeState(target()); }
806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
807b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Token::Value op_;
808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
81069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
81169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochclass ToBooleanIC: public IC {
81269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch public:
81369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  explicit ToBooleanIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
81469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
81569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  void patch(Code* code);
81669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch};
81769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
81869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
819257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Helper for BinaryOpIC and CompareIC.
820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid PatchInlinedSmiCode(Address address);
821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // V8_IC_H_
825