V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
ic.h
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_IC_IC_H_
6 #define V8_IC_IC_H_
7 
8 #include <vector>
9 
10 #include "src/feedback-vector.h"
11 #include "src/heap/factory.h"
12 #include "src/ic/stub-cache.h"
13 #include "src/isolate.h"
14 #include "src/message-template.h"
15 #include "src/objects/map.h"
16 #include "src/objects/maybe-object.h"
17 #include "src/objects/smi.h"
18 
19 namespace v8 {
20 namespace internal {
21 
22 //
23 // IC is the base class for LoadIC, StoreIC, KeyedLoadIC, and KeyedStoreIC.
24 //
25 class IC {
26  public:
27  // Alias the inline cache state type to make the IC code more readable.
28  typedef InlineCacheState State;
29 
30  static constexpr int kMaxKeyedPolymorphism = 4;
31 
32  // A polymorphic IC can handle at most 4 distinct maps before transitioning
33  // to megamorphic state.
34  static constexpr int kMaxPolymorphicMapCount = 4;
35 
36  // Construct the IC structure with the given number of extra
37  // JavaScript frames on the stack.
38  IC(Isolate* isolate, Handle<FeedbackVector> vector, FeedbackSlot slot);
39  virtual ~IC() = default;
40 
41  State state() const { return state_; }
42  inline Address address() const;
43 
44  // Compute the current IC state based on the target stub, receiver and name.
45  void UpdateState(Handle<Object> receiver, Handle<Object> name);
46 
47  bool RecomputeHandlerForName(Handle<Object> name);
48  void MarkRecomputeHandler(Handle<Object> name) {
49  DCHECK(RecomputeHandlerForName(name));
50  old_state_ = state_;
51  state_ = RECOMPUTE_HANDLER;
52  }
53 
54  bool IsAnyLoad() const {
55  return IsLoadIC() || IsLoadGlobalIC() || IsKeyedLoadIC();
56  }
57  bool IsAnyStore() const {
58  return IsStoreIC() || IsStoreOwnIC() || IsStoreGlobalIC() ||
59  IsKeyedStoreIC() || IsStoreInArrayLiteralICKind(kind());
60  }
61 
62  static inline bool IsHandler(MaybeObject object);
63 
64  // Nofity the IC system that a feedback has changed.
65  static void OnFeedbackChanged(Isolate* isolate, FeedbackVector* vector,
66  FeedbackSlot slot, JSFunction* host_function,
67  const char* reason);
68 
69  static void OnFeedbackChanged(Isolate* isolate, FeedbackNexus* nexus,
70  JSFunction* host_function, const char* reason);
71 
72  protected:
73  Address fp() const { return fp_; }
74  Address pc() const { return *pc_address_; }
75 
76  void set_slow_stub_reason(const char* reason) { slow_stub_reason_ = reason; }
77 
78  Isolate* isolate() const { return isolate_; }
79 
80  // Get the caller function object.
81  JSFunction* GetHostFunction() const;
82 
83  inline bool AddressIsDeoptimizedCode() const;
84  inline static bool AddressIsDeoptimizedCode(Isolate* isolate,
85  Address address);
86 
87  bool is_vector_set() { return vector_set_; }
88  inline bool vector_needs_update();
89 
90  // Configure for most states.
91  bool ConfigureVectorState(IC::State new_state, Handle<Object> key);
92  // Configure the vector for PREMONOMORPHIC.
93  void ConfigureVectorState(Handle<Map> map);
94  // Configure the vector for MONOMORPHIC.
95  void ConfigureVectorState(Handle<Name> name, Handle<Map> map,
96  Handle<Object> handler);
97  void ConfigureVectorState(Handle<Name> name, Handle<Map> map,
98  const MaybeObjectHandle& handler);
99  // Configure the vector for POLYMORPHIC.
100  void ConfigureVectorState(Handle<Name> name, MapHandles const& maps,
101  MaybeObjectHandles* handlers);
102 
103  char TransitionMarkFromState(IC::State state);
104  void TraceIC(const char* type, Handle<Object> name);
105  void TraceIC(const char* type, Handle<Object> name, State old_state,
106  State new_state);
107 
108  MaybeHandle<Object> TypeError(MessageTemplate, Handle<Object> object,
109  Handle<Object> key);
110  MaybeHandle<Object> ReferenceError(Handle<Name> name);
111 
112  void TraceHandlerCacheHitStats(LookupIterator* lookup);
113 
114  void UpdateMonomorphicIC(const MaybeObjectHandle& handler, Handle<Name> name);
115  bool UpdatePolymorphicIC(Handle<Name> name, const MaybeObjectHandle& handler);
116  void UpdateMegamorphicCache(Handle<Map> map, Handle<Name> name,
117  const MaybeObjectHandle& handler);
118 
119  StubCache* stub_cache();
120 
121  void CopyICToMegamorphicCache(Handle<Name> name);
122  bool IsTransitionOfMonomorphicTarget(Map source_map, Map target_map);
123  void PatchCache(Handle<Name> name, Handle<Object> handler);
124  void PatchCache(Handle<Name> name, const MaybeObjectHandle& handler);
125  FeedbackSlotKind kind() const { return kind_; }
126  bool IsGlobalIC() const { return IsLoadGlobalIC() || IsStoreGlobalIC(); }
127  bool IsLoadIC() const { return IsLoadICKind(kind_); }
128  bool IsLoadGlobalIC() const { return IsLoadGlobalICKind(kind_); }
129  bool IsKeyedLoadIC() const { return IsKeyedLoadICKind(kind_); }
130  bool IsStoreGlobalIC() const { return IsStoreGlobalICKind(kind_); }
131  bool IsStoreIC() const { return IsStoreICKind(kind_); }
132  bool IsStoreOwnIC() const { return IsStoreOwnICKind(kind_); }
133  bool IsKeyedStoreIC() const { return IsKeyedStoreICKind(kind_); }
134  bool is_keyed() const {
135  return IsKeyedLoadIC() || IsKeyedStoreIC() ||
136  IsStoreInArrayLiteralICKind(kind_);
137  }
138  bool ShouldRecomputeHandler(Handle<String> name);
139 
140  Handle<Map> receiver_map() { return receiver_map_; }
141  inline void update_receiver_map(Handle<Object> receiver);
142 
143  void TargetMaps(MapHandles* list) {
144  FindTargetMaps();
145  for (Handle<Map> map : target_maps_) {
146  list->push_back(map);
147  }
148  }
149 
150  Map FirstTargetMap() {
151  FindTargetMaps();
152  return !target_maps_.empty() ? *target_maps_[0] : Map();
153  }
154 
155  State saved_state() const {
156  return state() == RECOMPUTE_HANDLER ? old_state_ : state();
157  }
158 
159  const FeedbackNexus* nexus() const { return &nexus_; }
160  FeedbackNexus* nexus() { return &nexus_; }
161 
162  private:
163  inline Address constant_pool() const;
164  inline Address raw_constant_pool() const;
165 
166  void FindTargetMaps() {
167  if (target_maps_set_) return;
168  target_maps_set_ = true;
169  nexus()->ExtractMaps(&target_maps_);
170  }
171 
172  // Frame pointer for the frame that uses (calls) the IC.
173  Address fp_;
174 
175  // All access to the program counter and constant pool of an IC structure is
176  // indirect to make the code GC safe. This feature is crucial since
177  // GetProperty and SetProperty are called and they in turn might
178  // invoke the garbage collector.
179  Address* pc_address_;
180 
181  // The constant pool of the code which originally called the IC (which might
182  // be for the breakpointed copy of the original code).
183  Address* constant_pool_address_;
184 
185  Isolate* isolate_;
186 
187  bool vector_set_;
188  State old_state_; // For saving if we marked as prototype failure.
189  State state_;
190  FeedbackSlotKind kind_;
191  Handle<Map> receiver_map_;
192  MaybeObjectHandle maybe_handler_;
193 
194  MapHandles target_maps_;
195  bool target_maps_set_;
196 
197  const char* slow_stub_reason_;
198 
199  FeedbackNexus nexus_;
200 
201  DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
202 };
203 
204 
205 class LoadIC : public IC {
206  public:
207  LoadIC(Isolate* isolate, Handle<FeedbackVector> vector, FeedbackSlot slot)
208  : IC(isolate, vector, slot) {
209  DCHECK(IsAnyLoad());
210  }
211 
212  static bool ShouldThrowReferenceError(FeedbackSlotKind kind) {
213  return kind == FeedbackSlotKind::kLoadGlobalNotInsideTypeof;
214  }
215 
216  bool ShouldThrowReferenceError() const {
217  return ShouldThrowReferenceError(kind());
218  }
219 
220  V8_WARN_UNUSED_RESULT MaybeHandle<Object> Load(Handle<Object> object,
221  Handle<Name> name);
222 
223  protected:
224  virtual Handle<Code> slow_stub() const {
225  return BUILTIN_CODE(isolate(), LoadIC_Slow);
226  }
227 
228  // Update the inline cache and the global stub cache based on the
229  // lookup result.
230  void UpdateCaches(LookupIterator* lookup);
231 
232  private:
233  Handle<Object> ComputeHandler(LookupIterator* lookup);
234 
235  friend class IC;
236  friend class NamedLoadHandlerCompiler;
237 };
238 
239 class LoadGlobalIC : public LoadIC {
240  public:
242  FeedbackSlot slot)
243  : LoadIC(isolate, vector, slot) {}
244 
245  V8_WARN_UNUSED_RESULT MaybeHandle<Object> Load(Handle<Name> name);
246 
247  protected:
248  Handle<Code> slow_stub() const override {
249  return BUILTIN_CODE(isolate(), LoadGlobalIC_Slow);
250  }
251 };
252 
253 class KeyedLoadIC : public LoadIC {
254  public:
255  KeyedLoadIC(Isolate* isolate, Handle<FeedbackVector> vector,
256  FeedbackSlot slot)
257  : LoadIC(isolate, vector, slot) {}
258 
259  V8_WARN_UNUSED_RESULT MaybeHandle<Object> Load(Handle<Object> object,
260  Handle<Object> key);
261 
262  protected:
263  // receiver is HeapObject because it could be a String or a JSObject
264  void UpdateLoadElement(Handle<HeapObject> receiver,
265  KeyedAccessLoadMode load_mode);
266 
267  private:
268  friend class IC;
269 
270  Handle<Object> LoadElementHandler(Handle<Map> receiver_map,
271  KeyedAccessLoadMode load_mode);
272 
273  void LoadElementPolymorphicHandlers(MapHandles* receiver_maps,
274  MaybeObjectHandles* handlers,
275  KeyedAccessLoadMode load_mode);
276 
277  // Returns true if the receiver_map has a kElement or kIndexedString
278  // handler in the nexus currently but didn't yet allow out of bounds
279  // accesses.
280  bool CanChangeToAllowOutOfBounds(Handle<Map> receiver_map);
281 };
282 
283 
284 class StoreIC : public IC {
285  public:
286  StoreIC(Isolate* isolate, Handle<FeedbackVector> vector, FeedbackSlot slot)
287  : IC(isolate, vector, slot) {
288  DCHECK(IsAnyStore());
289  }
290 
291  LanguageMode language_mode() const { return nexus()->GetLanguageMode(); }
292 
293  V8_WARN_UNUSED_RESULT MaybeHandle<Object> Store(
294  Handle<Object> object, Handle<Name> name, Handle<Object> value,
295  StoreOrigin store_origin = StoreOrigin::kNamed);
296 
297  bool LookupForWrite(LookupIterator* it, Handle<Object> value,
298  StoreOrigin store_origin);
299 
300  protected:
301  // Stub accessors.
302  virtual Handle<Code> slow_stub() const {
303  // All StoreICs share the same slow stub.
304  return BUILTIN_CODE(isolate(), KeyedStoreIC_Slow);
305  }
306 
307  // Update the inline cache and the global stub cache based on the
308  // lookup result.
309  void UpdateCaches(LookupIterator* lookup, Handle<Object> value,
310  StoreOrigin store_origin);
311 
312  private:
313  MaybeObjectHandle ComputeHandler(LookupIterator* lookup);
314 
315  friend class IC;
316 };
317 
318 class StoreGlobalIC : public StoreIC {
319  public:
321  FeedbackSlot slot)
322  : StoreIC(isolate, vector, slot) {}
323 
324  V8_WARN_UNUSED_RESULT MaybeHandle<Object> Store(Handle<Name> name,
325  Handle<Object> value);
326 
327  protected:
328  Handle<Code> slow_stub() const override {
329  return BUILTIN_CODE(isolate(), StoreGlobalIC_Slow);
330  }
331 };
332 
333 enum KeyedStoreCheckMap { kDontCheckMap, kCheckMap };
334 
335 
336 enum KeyedStoreIncrementLength { kDontIncrementLength, kIncrementLength };
337 
338 
339 class KeyedStoreIC : public StoreIC {
340  public:
341  KeyedAccessStoreMode GetKeyedAccessStoreMode() {
342  return nexus()->GetKeyedAccessStoreMode();
343  }
344 
346  FeedbackSlot slot)
347  : StoreIC(isolate, vector, slot) {}
348 
349  V8_WARN_UNUSED_RESULT MaybeHandle<Object> Store(Handle<Object> object,
350  Handle<Object> name,
351  Handle<Object> value);
352 
353  protected:
354  void UpdateStoreElement(Handle<Map> receiver_map,
355  KeyedAccessStoreMode store_mode,
356  bool receiver_was_cow);
357 
358  Handle<Code> slow_stub() const override {
359  return BUILTIN_CODE(isolate(), KeyedStoreIC_Slow);
360  }
361 
362  private:
363  Handle<Map> ComputeTransitionedMap(Handle<Map> map,
364  KeyedAccessStoreMode store_mode);
365 
366  Handle<Object> StoreElementHandler(Handle<Map> receiver_map,
367  KeyedAccessStoreMode store_mode);
368 
369  void StoreElementPolymorphicHandlers(MapHandles* receiver_maps,
370  MaybeObjectHandles* handlers,
371  KeyedAccessStoreMode store_mode);
372 
373  friend class IC;
374 };
375 
377  public:
379  FeedbackSlot slot)
380  : KeyedStoreIC(isolate, vector, slot) {
381  DCHECK(IsStoreInArrayLiteralICKind(kind()));
382  }
383 
384  void Store(Handle<JSArray> array, Handle<Object> index, Handle<Object> value);
385 
386  private:
387  Handle<Code> slow_stub() const override {
388  return BUILTIN_CODE(isolate(), StoreInArrayLiteralIC_Slow);
389  }
390 };
391 
392 } // namespace internal
393 } // namespace v8
394 
395 #endif // V8_IC_IC_H_
Definition: libplatform.h:13