blob: 541fa0c7dce1fc565e459085569ae01371527534 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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_H_
6#define V8_IC_H_
7
8#include "src/ic/ic-state.h"
9#include "src/macro-assembler.h"
10
11namespace v8 {
12namespace internal {
13
14
15// IC_UTIL_LIST defines all utility functions called from generated
16// inline caching code. The argument for the macro, ICU, is the function name.
17#define IC_UTIL_LIST(ICU) \
18 ICU(LoadIC_Miss) \
19 ICU(KeyedLoadIC_Miss) \
20 ICU(CallIC_Miss) \
21 ICU(CallIC_Customization_Miss) \
22 ICU(StoreIC_Miss) \
23 ICU(StoreIC_Slow) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000024 ICU(KeyedStoreIC_Miss) \
25 ICU(KeyedStoreIC_Slow) \
26 /* Utilities for IC stubs. */ \
27 ICU(StoreCallbackProperty) \
28 ICU(LoadPropertyWithInterceptorOnly) \
29 ICU(LoadPropertyWithInterceptor) \
30 ICU(LoadElementWithInterceptor) \
31 ICU(StorePropertyWithInterceptor) \
32 ICU(CompareIC_Miss) \
33 ICU(BinaryOpIC_Miss) \
34 ICU(CompareNilIC_Miss) \
35 ICU(Unreachable) \
36 ICU(ToBooleanIC_Miss)
37//
38// IC is the base class for LoadIC, StoreIC, KeyedLoadIC, and KeyedStoreIC.
39//
40class IC {
41 public:
42 // The ids for utility called from the generated code.
43 enum UtilityId {
44#define CONST_NAME(name) k##name,
45 IC_UTIL_LIST(CONST_NAME)
46#undef CONST_NAME
47 kUtilityCount
48 };
49
50 // Looks up the address of the named utility.
51 static Address AddressFromUtilityId(UtilityId id);
52
53 // Alias the inline cache state type to make the IC code more readable.
54 typedef InlineCacheState State;
55
56 // The IC code is either invoked with no extra frames on the stack
57 // or with a single extra frame for supporting calls.
58 enum FrameDepth { NO_EXTRA_FRAME = 0, EXTRA_CALL_FRAME = 1 };
59
60 // Construct the IC structure with the given number of extra
61 // JavaScript frames on the stack.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040062 IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus = NULL,
63 bool for_queries_only = false);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000064 virtual ~IC() {}
65
66 State state() const { return state_; }
67 inline Address address() const;
68
69 // Compute the current IC state based on the target stub, receiver and name.
70 void UpdateState(Handle<Object> receiver, Handle<Object> name);
71
72 bool IsNameCompatibleWithPrototypeFailure(Handle<Object> name);
73 void MarkPrototypeFailure(Handle<Object> name) {
74 DCHECK(IsNameCompatibleWithPrototypeFailure(name));
Emily Bernierd0a1eb72015-03-24 16:35:39 -040075 old_state_ = state_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000076 state_ = PROTOTYPE_FAILURE;
77 }
78
Ben Murdochb8a8cc12014-11-26 15:28:44 +000079 // Clear the inline cache to initial state.
80 static void Clear(Isolate* isolate, Address address,
81 ConstantPoolArray* constant_pool);
82
83#ifdef DEBUG
84 bool IsLoadStub() const {
85 return target()->is_load_stub() || target()->is_keyed_load_stub();
86 }
87
88 bool IsStoreStub() const {
89 return target()->is_store_stub() || target()->is_keyed_store_stub();
90 }
91
92 bool IsCallStub() const { return target()->is_call_stub(); }
93#endif
94
95 template <class TypeClass>
96 static JSFunction* GetRootConstructor(TypeClass* type,
97 Context* native_context);
98 static inline Handle<Map> GetHandlerCacheHolder(HeapType* type,
99 bool receiver_is_holder,
100 Isolate* isolate,
101 CacheHolderFlag* flag);
102 static inline Handle<Map> GetICCacheHolder(HeapType* type, Isolate* isolate,
103 CacheHolderFlag* flag);
104
105 static bool IsCleared(Code* code) {
106 InlineCacheState state = code->ic_state();
107 return state == UNINITIALIZED || state == PREMONOMORPHIC;
108 }
109
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400110 static bool IsCleared(FeedbackNexus* nexus) {
111 InlineCacheState state = nexus->StateFromFeedback();
112 return state == UNINITIALIZED || state == PREMONOMORPHIC;
113 }
114
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000115 // Utility functions to convert maps to types and back. There are two special
116 // cases:
117 // - The heap_number_map is used as a marker which includes heap numbers as
118 // well as smis.
119 // - The oddball map is only used for booleans.
120 static Handle<Map> TypeToMap(HeapType* type, Isolate* isolate);
121 template <class T>
122 static typename T::TypeHandle MapToType(Handle<Map> map,
123 typename T::Region* region);
124
125 static Handle<HeapType> CurrentTypeOf(Handle<Object> object,
126 Isolate* isolate);
127
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400128 static bool ICUseVector(Code::Kind kind) {
129 return (FLAG_vector_ics &&
130 (kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC)) ||
131 kind == Code::CALL_IC;
132 }
133
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000134 protected:
135 // Get the call-site target; used for determining the state.
136 Handle<Code> target() const { return target_; }
137
138 Address fp() const { return fp_; }
139 Address pc() const { return *pc_address_; }
140 Isolate* isolate() const { return isolate_; }
141
142 // Get the shared function info of the caller.
143 SharedFunctionInfo* GetSharedFunctionInfo() const;
144 // Get the code object of the caller.
145 Code* GetCode() const;
146 // Get the original (non-breakpointed) code object of the caller.
147 Code* GetOriginalCode() const;
148
149 // Set the call-site target.
150 inline void set_target(Code* code);
151 bool is_target_set() { return target_set_; }
152
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400153 bool UseVector() const {
154 bool use = ICUseVector(kind());
155 // If we are supposed to use the nexus, verify the nexus is non-null.
156 DCHECK(!use || nexus_ != NULL);
157 return use;
158 }
159
160 // Configure for most states.
161 void ConfigureVectorState(IC::State new_state);
162 // Configure the vector for MONOMORPHIC.
163 void ConfigureVectorState(Handle<Name> name, Handle<HeapType> type,
164 Handle<Code> handler);
165 // Configure the vector for POLYMORPHIC.
166 void ConfigureVectorState(Handle<Name> name, TypeHandleList* types,
167 CodeHandleList* handlers);
168
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000169 char TransitionMarkFromState(IC::State state);
170 void TraceIC(const char* type, Handle<Object> name);
171 void TraceIC(const char* type, Handle<Object> name, State old_state,
172 State new_state);
173
174 MaybeHandle<Object> TypeError(const char* type, Handle<Object> object,
175 Handle<Object> key);
176 MaybeHandle<Object> ReferenceError(const char* type, Handle<Name> name);
177
178 // Access the target code for the given IC address.
179 static inline Code* GetTargetAtAddress(Address address,
180 ConstantPoolArray* constant_pool);
181 static inline void SetTargetAtAddress(Address address, Code* target,
182 ConstantPoolArray* constant_pool);
183 static void OnTypeFeedbackChanged(Isolate* isolate, Address address,
184 State old_state, State new_state,
185 bool target_remains_ic_stub);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400186 // As a vector-based IC, type feedback must be updated differently.
187 static void OnTypeFeedbackChanged(Isolate* isolate, Code* host,
188 TypeFeedbackVector* vector, State old_state,
189 State new_state);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000190 static void PostPatching(Address address, Code* target, Code* old_target);
191
192 // Compute the handler either by compiling or by retrieving a cached version.
193 Handle<Code> ComputeHandler(LookupIterator* lookup,
194 Handle<Object> value = Handle<Code>::null());
195 virtual Handle<Code> CompileHandler(LookupIterator* lookup,
196 Handle<Object> value,
197 CacheHolderFlag cache_holder) {
198 UNREACHABLE();
199 return Handle<Code>::null();
200 }
201
202 void UpdateMonomorphicIC(Handle<Code> handler, Handle<Name> name);
203 bool UpdatePolymorphicIC(Handle<Name> name, Handle<Code> code);
204 void UpdateMegamorphicCache(HeapType* type, Name* name, Code* code);
205
206 void CopyICToMegamorphicCache(Handle<Name> name);
207 bool IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map);
208 void PatchCache(Handle<Name> name, Handle<Code> code);
209 Code::Kind kind() const { return kind_; }
210 Code::Kind handler_kind() const {
211 if (kind_ == Code::KEYED_LOAD_IC) return Code::LOAD_IC;
212 DCHECK(kind_ == Code::LOAD_IC || kind_ == Code::STORE_IC ||
213 kind_ == Code::KEYED_STORE_IC);
214 return kind_;
215 }
216 virtual Handle<Code> megamorphic_stub() {
217 UNREACHABLE();
218 return Handle<Code>::null();
219 }
220
221 bool TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver,
222 Handle<String> name);
223
224 ExtraICState extra_ic_state() const { return extra_ic_state_; }
225 void set_extra_ic_state(ExtraICState state) { extra_ic_state_ = state; }
226
227 Handle<HeapType> receiver_type() { return receiver_type_; }
228 void update_receiver_type(Handle<Object> receiver) {
229 receiver_type_ = CurrentTypeOf(receiver, isolate_);
230 }
231
232 void TargetMaps(MapHandleList* list) {
233 FindTargetMaps();
234 for (int i = 0; i < target_maps_.length(); i++) {
235 list->Add(target_maps_.at(i));
236 }
237 }
238
239 void TargetTypes(TypeHandleList* list) {
240 FindTargetMaps();
241 for (int i = 0; i < target_maps_.length(); i++) {
242 list->Add(MapToType<HeapType>(target_maps_.at(i), isolate_));
243 }
244 }
245
246 Map* FirstTargetMap() {
247 FindTargetMaps();
248 return target_maps_.length() > 0 ? *target_maps_.at(0) : NULL;
249 }
250
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000251 inline void UpdateTarget();
252
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400253 Handle<TypeFeedbackVector> vector() const { return nexus()->vector_handle(); }
254 FeedbackVectorICSlot slot() const { return nexus()->slot(); }
255 State saved_state() const {
256 return state() == PROTOTYPE_FAILURE ? old_state_ : state();
257 }
258
259 template <class NexusClass>
260 NexusClass* casted_nexus() {
261 return static_cast<NexusClass*>(nexus_);
262 }
263 FeedbackNexus* nexus() const { return nexus_; }
264
265 inline Code* get_host();
266
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000267 private:
268 inline Code* raw_target() const;
269 inline ConstantPoolArray* constant_pool() const;
270 inline ConstantPoolArray* raw_constant_pool() const;
271
272 void FindTargetMaps() {
273 if (target_maps_set_) return;
274 target_maps_set_ = true;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400275 if (UseVector()) {
276 nexus()->ExtractMaps(&target_maps_);
277 } else {
278 if (state_ == MONOMORPHIC) {
279 Map* map = target_->FindFirstMap();
280 if (map != NULL) target_maps_.Add(handle(map));
281 } else if (state_ != UNINITIALIZED && state_ != PREMONOMORPHIC) {
282 target_->FindAllMaps(&target_maps_);
283 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000284 }
285 }
286
287 // Frame pointer for the frame that uses (calls) the IC.
288 Address fp_;
289
290 // All access to the program counter of an IC structure is indirect
291 // to make the code GC safe. This feature is crucial since
292 // GetProperty and SetProperty are called and they in turn might
293 // invoke the garbage collector.
294 Address* pc_address_;
295
296 Isolate* isolate_;
297
298 // The constant pool of the code which originally called the IC (which might
299 // be for the breakpointed copy of the original code).
300 Handle<ConstantPoolArray> raw_constant_pool_;
301
302 // The original code target that missed.
303 Handle<Code> target_;
304 bool target_set_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400305 State old_state_; // For saving if we marked as prototype failure.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000306 State state_;
307 Code::Kind kind_;
308 Handle<HeapType> receiver_type_;
309 MaybeHandle<Code> maybe_handler_;
310
311 ExtraICState extra_ic_state_;
312 MapHandleList target_maps_;
313 bool target_maps_set_;
314
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400315 FeedbackNexus* nexus_;
316
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000317 DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
318};
319
320
321// An IC_Utility encapsulates IC::UtilityId. It exists mainly because you
322// cannot make forward declarations to an enum.
323class IC_Utility {
324 public:
325 explicit IC_Utility(IC::UtilityId id)
326 : address_(IC::AddressFromUtilityId(id)), id_(id) {}
327
328 Address address() const { return address_; }
329
330 IC::UtilityId id() const { return id_; }
331
332 private:
333 Address address_;
334 IC::UtilityId id_;
335};
336
337
338class CallIC : public IC {
339 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400340 CallIC(Isolate* isolate, CallICNexus* nexus)
341 : IC(EXTRA_CALL_FRAME, isolate, nexus) {
342 DCHECK(nexus != NULL);
343 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000344
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400345 void PatchMegamorphic(Handle<Object> function);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000346
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400347 void HandleMiss(Handle<Object> receiver, Handle<Object> function);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000348
349 // Returns true if a custom handler was installed.
350 bool DoCustomHandler(Handle<Object> receiver, Handle<Object> function,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400351 const CallICState& callic_state);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000352
353 // Code generator routines.
354 static Handle<Code> initialize_stub(Isolate* isolate, int argc,
355 CallICState::CallType call_type);
356
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400357 static void Clear(Isolate* isolate, Code* host, CallICNexus* nexus);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000358};
359
360
361class LoadIC : public IC {
362 public:
363 static ExtraICState ComputeExtraICState(ContextualMode contextual_mode) {
364 return LoadICState(contextual_mode).GetExtraICState();
365 }
366
367 ContextualMode contextual_mode() const {
368 return LoadICState::GetContextualMode(extra_ic_state());
369 }
370
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400371 LoadIC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus = NULL)
372 : IC(depth, isolate, nexus) {
373 DCHECK(!FLAG_vector_ics || nexus != NULL);
374 DCHECK(IsLoadStub());
375 }
376
377 // TODO(mvstanton): The for_queries_only is because we have a case where we
378 // construct an IC only to gather the contextual mode, and we don't have
379 // vector/slot information. for_queries_only is a temporary hack to enable the
380 // strong DCHECK protection around vector/slot.
381 LoadIC(FrameDepth depth, Isolate* isolate, bool for_queries_only)
382 : IC(depth, isolate, NULL, for_queries_only) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000383 DCHECK(IsLoadStub());
384 }
385
386 // Returns if this IC is for contextual (no explicit receiver)
387 // access to properties.
388 bool IsUndeclaredGlobal(Handle<Object> receiver) {
389 if (receiver->IsGlobalObject()) {
390 return contextual_mode() == CONTEXTUAL;
391 } else {
392 DCHECK(contextual_mode() != CONTEXTUAL);
393 return false;
394 }
395 }
396
397 // Code generator routines.
398 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
399 static void GeneratePreMonomorphic(MacroAssembler* masm) {
400 GenerateMiss(masm);
401 }
402 static void GenerateMiss(MacroAssembler* masm);
403 static void GenerateNormal(MacroAssembler* masm);
404 static void GenerateRuntimeGetProperty(MacroAssembler* masm);
405
406 static Handle<Code> initialize_stub(Isolate* isolate,
407 ExtraICState extra_state);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400408 static Handle<Code> initialize_stub_in_optimized_code(
409 Isolate* isolate, ExtraICState extra_state);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000410
411 MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Object> object,
412 Handle<Name> name);
413
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400414 static void Clear(Isolate* isolate, Code* host, LoadICNexus* nexus);
415
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000416 protected:
417 inline void set_target(Code* code);
418
419 Handle<Code> slow_stub() const {
420 if (kind() == Code::LOAD_IC) {
421 return isolate()->builtins()->LoadIC_Slow();
422 } else {
423 DCHECK_EQ(Code::KEYED_LOAD_IC, kind());
424 return isolate()->builtins()->KeyedLoadIC_Slow();
425 }
426 }
427
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400428 Handle<Code> megamorphic_stub() OVERRIDE;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000429
430 // Update the inline cache and the global stub cache based on the
431 // lookup result.
432 void UpdateCaches(LookupIterator* lookup);
433
434 virtual Handle<Code> CompileHandler(LookupIterator* lookup,
435 Handle<Object> unused,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400436 CacheHolderFlag cache_holder) OVERRIDE;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000437
438 private:
439 virtual Handle<Code> pre_monomorphic_stub() const;
440 static Handle<Code> pre_monomorphic_stub(Isolate* isolate,
441 ExtraICState extra_state);
442
443 Handle<Code> SimpleFieldLoad(FieldIndex index);
444
445 static void Clear(Isolate* isolate, Address address, Code* target,
446 ConstantPoolArray* constant_pool);
447
448 friend class IC;
449};
450
451
452class KeyedLoadIC : public LoadIC {
453 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400454 // ExtraICState bits (building on IC)
455 class IcCheckTypeField : public BitField<IcCheckType, 1, 1> {};
456
457 static ExtraICState ComputeExtraICState(ContextualMode contextual_mode,
458 IcCheckType key_type) {
459 return LoadICState(contextual_mode).GetExtraICState() |
460 IcCheckTypeField::encode(key_type);
461 }
462
463 static IcCheckType GetKeyType(ExtraICState extra_state) {
464 return IcCheckTypeField::decode(extra_state);
465 }
466
467 KeyedLoadIC(FrameDepth depth, Isolate* isolate,
468 KeyedLoadICNexus* nexus = NULL)
469 : LoadIC(depth, isolate, nexus) {
470 DCHECK(!FLAG_vector_ics || nexus != NULL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000471 DCHECK(target()->is_keyed_load_stub());
472 }
473
474 MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Object> object,
475 Handle<Object> key);
476
477 // Code generator routines.
478 static void GenerateMiss(MacroAssembler* masm);
479 static void GenerateRuntimeGetProperty(MacroAssembler* masm);
480 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
481 static void GeneratePreMonomorphic(MacroAssembler* masm) {
482 GenerateMiss(masm);
483 }
484 static void GenerateGeneric(MacroAssembler* masm);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000485
486 // Bit mask to be tested against bit field for the cases when
487 // generic stub should go into slow case.
488 // Access check is necessary explicitly since generic stub does not perform
489 // map checks.
490 static const int kSlowCaseBitFieldMask =
491 (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor);
492
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400493 static Handle<Code> initialize_stub(Isolate* isolate);
494 static Handle<Code> initialize_stub_in_optimized_code(Isolate* isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000495 static Handle<Code> generic_stub(Isolate* isolate);
496 static Handle<Code> pre_monomorphic_stub(Isolate* isolate);
497
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400498 static void Clear(Isolate* isolate, Code* host, KeyedLoadICNexus* nexus);
499
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000500 protected:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400501 // receiver is HeapObject because it could be a String or a JSObject
502 Handle<Code> LoadElementStub(Handle<HeapObject> receiver);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000503 virtual Handle<Code> pre_monomorphic_stub() const {
504 return pre_monomorphic_stub(isolate());
505 }
506
507 private:
508 Handle<Code> generic_stub() const { return generic_stub(isolate()); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000509
510 static void Clear(Isolate* isolate, Address address, Code* target,
511 ConstantPoolArray* constant_pool);
512
513 friend class IC;
514};
515
516
517class StoreIC : public IC {
518 public:
519 class StrictModeState : public BitField<StrictMode, 1, 1> {};
520 static ExtraICState ComputeExtraICState(StrictMode flag) {
521 return StrictModeState::encode(flag);
522 }
523 static StrictMode GetStrictMode(ExtraICState state) {
524 return StrictModeState::decode(state);
525 }
526
527 // For convenience, a statically declared encoding of strict mode extra
528 // IC state.
529 static const ExtraICState kStrictModeState = 1 << StrictModeState::kShift;
530
531 StoreIC(FrameDepth depth, Isolate* isolate) : IC(depth, isolate) {
532 DCHECK(IsStoreStub());
533 }
534
535 StrictMode strict_mode() const {
536 return StrictModeState::decode(extra_ic_state());
537 }
538
539 // Code generators for stub routines. Only called once at startup.
540 static void GenerateSlow(MacroAssembler* masm);
541 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
542 static void GeneratePreMonomorphic(MacroAssembler* masm) {
543 GenerateMiss(masm);
544 }
545 static void GenerateMiss(MacroAssembler* masm);
546 static void GenerateMegamorphic(MacroAssembler* masm);
547 static void GenerateNormal(MacroAssembler* masm);
548 static void GenerateRuntimeSetProperty(MacroAssembler* masm,
549 StrictMode strict_mode);
550
551 static Handle<Code> initialize_stub(Isolate* isolate, StrictMode strict_mode);
552
553 MUST_USE_RESULT MaybeHandle<Object> Store(
554 Handle<Object> object, Handle<Name> name, Handle<Object> value,
555 JSReceiver::StoreFromKeyed store_mode =
556 JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED);
557
558 bool LookupForWrite(LookupIterator* it, Handle<Object> value,
559 JSReceiver::StoreFromKeyed store_mode);
560
561 protected:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400562 Handle<Code> megamorphic_stub() OVERRIDE;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000563
564 // Stub accessors.
565 Handle<Code> generic_stub() const;
566
567 Handle<Code> slow_stub() const;
568
569 virtual Handle<Code> pre_monomorphic_stub() const {
570 return pre_monomorphic_stub(isolate(), strict_mode());
571 }
572
573 static Handle<Code> pre_monomorphic_stub(Isolate* isolate,
574 StrictMode strict_mode);
575
576 // Update the inline cache and the global stub cache based on the
577 // lookup result.
578 void UpdateCaches(LookupIterator* lookup, Handle<Object> value,
579 JSReceiver::StoreFromKeyed store_mode);
580 virtual Handle<Code> CompileHandler(LookupIterator* lookup,
581 Handle<Object> value,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400582 CacheHolderFlag cache_holder) OVERRIDE;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000583
584 private:
585 inline void set_target(Code* code);
586
587 static void Clear(Isolate* isolate, Address address, Code* target,
588 ConstantPoolArray* constant_pool);
589
590 friend class IC;
591};
592
593
594enum KeyedStoreCheckMap { kDontCheckMap, kCheckMap };
595
596
597enum KeyedStoreIncrementLength { kDontIncrementLength, kIncrementLength };
598
599
600class KeyedStoreIC : public StoreIC {
601 public:
602 // ExtraICState bits (building on IC)
603 // ExtraICState bits
604 class ExtraICStateKeyedAccessStoreMode
605 : public BitField<KeyedAccessStoreMode, 2, 4> {}; // NOLINT
606
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400607 class IcCheckTypeField : public BitField<IcCheckType, 6, 1> {};
608
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000609 static ExtraICState ComputeExtraICState(StrictMode flag,
610 KeyedAccessStoreMode mode) {
611 return StrictModeState::encode(flag) |
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400612 ExtraICStateKeyedAccessStoreMode::encode(mode) |
613 IcCheckTypeField::encode(ELEMENT);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000614 }
615
616 static KeyedAccessStoreMode GetKeyedAccessStoreMode(
617 ExtraICState extra_state) {
618 return ExtraICStateKeyedAccessStoreMode::decode(extra_state);
619 }
620
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400621 static IcCheckType GetKeyType(ExtraICState extra_state) {
622 return IcCheckTypeField::decode(extra_state);
623 }
624
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000625 KeyedStoreIC(FrameDepth depth, Isolate* isolate) : StoreIC(depth, isolate) {
626 DCHECK(target()->is_keyed_store_stub());
627 }
628
629 MUST_USE_RESULT MaybeHandle<Object> Store(Handle<Object> object,
630 Handle<Object> name,
631 Handle<Object> value);
632
633 // Code generators for stub routines. Only called once at startup.
634 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
635 static void GeneratePreMonomorphic(MacroAssembler* masm) {
636 GenerateMiss(masm);
637 }
638 static void GenerateMiss(MacroAssembler* masm);
639 static void GenerateSlow(MacroAssembler* masm);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400640 static void GenerateMegamorphic(MacroAssembler* masm, StrictMode strict_mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000641 static void GenerateGeneric(MacroAssembler* masm, StrictMode strict_mode);
642 static void GenerateSloppyArguments(MacroAssembler* masm);
643
644 protected:
645 virtual Handle<Code> pre_monomorphic_stub() const {
646 return pre_monomorphic_stub(isolate(), strict_mode());
647 }
648 static Handle<Code> pre_monomorphic_stub(Isolate* isolate,
649 StrictMode strict_mode) {
650 if (strict_mode == STRICT) {
651 return isolate->builtins()->KeyedStoreIC_PreMonomorphic_Strict();
652 } else {
653 return isolate->builtins()->KeyedStoreIC_PreMonomorphic();
654 }
655 }
656
657 Handle<Code> StoreElementStub(Handle<JSObject> receiver,
658 KeyedAccessStoreMode store_mode);
659
660 private:
661 inline void set_target(Code* code);
662
663 // Stub accessors.
664 Handle<Code> sloppy_arguments_stub() {
665 return isolate()->builtins()->KeyedStoreIC_SloppyArguments();
666 }
667
668 static void Clear(Isolate* isolate, Address address, Code* target,
669 ConstantPoolArray* constant_pool);
670
671 KeyedAccessStoreMode GetStoreMode(Handle<JSObject> receiver,
672 Handle<Object> key, Handle<Object> value);
673
674 Handle<Map> ComputeTransitionedMap(Handle<Map> map,
675 KeyedAccessStoreMode store_mode);
676
677 friend class IC;
678};
679
680
681// Type Recording BinaryOpIC, that records the types of the inputs and outputs.
682class BinaryOpIC : public IC {
683 public:
684 explicit BinaryOpIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) {}
685
686 static Builtins::JavaScript TokenToJSBuiltin(Token::Value op);
687
688 MaybeHandle<Object> Transition(Handle<AllocationSite> allocation_site,
689 Handle<Object> left,
690 Handle<Object> right) WARN_UNUSED_RESULT;
691};
692
693
694class CompareIC : public IC {
695 public:
696 CompareIC(Isolate* isolate, Token::Value op)
697 : IC(EXTRA_CALL_FRAME, isolate), op_(op) {}
698
699 // Update the inline cache for the given operands.
700 Code* UpdateCaches(Handle<Object> x, Handle<Object> y);
701
702 // Helper function for computing the condition for a compare operation.
703 static Condition ComputeCondition(Token::Value op);
704
705 // Factory method for getting an uninitialized compare stub.
706 static Handle<Code> GetUninitialized(Isolate* isolate, Token::Value op);
707
708 private:
709 static bool HasInlinedSmiCode(Address address);
710
711 bool strict() const { return op_ == Token::EQ_STRICT; }
712 Condition GetCondition() const { return ComputeCondition(op_); }
713
714 static Code* GetRawUninitialized(Isolate* isolate, Token::Value op);
715
716 static void Clear(Isolate* isolate, Address address, Code* target,
717 ConstantPoolArray* constant_pool);
718
719 Token::Value op_;
720
721 friend class IC;
722};
723
724
725class CompareNilIC : public IC {
726 public:
727 explicit CompareNilIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) {}
728
729 Handle<Object> CompareNil(Handle<Object> object);
730
731 static Handle<Code> GetUninitialized();
732
733 static void Clear(Address address, Code* target,
734 ConstantPoolArray* constant_pool);
735
736 static Handle<Object> DoCompareNilSlow(Isolate* isolate, NilValue nil,
737 Handle<Object> object);
738};
739
740
741class ToBooleanIC : public IC {
742 public:
743 explicit ToBooleanIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) {}
744
745 Handle<Object> ToBoolean(Handle<Object> object);
746};
747
748
749// Helper for BinaryOpIC and CompareIC.
750enum InlinedSmiCheck { ENABLE_INLINED_SMI_CHECK, DISABLE_INLINED_SMI_CHECK };
751void PatchInlinedSmiCode(Address address, InlinedSmiCheck check);
752
753DECLARE_RUNTIME_FUNCTION(KeyedLoadIC_MissFromStubFailure);
754DECLARE_RUNTIME_FUNCTION(KeyedStoreIC_MissFromStubFailure);
755DECLARE_RUNTIME_FUNCTION(UnaryOpIC_Miss);
756DECLARE_RUNTIME_FUNCTION(StoreIC_MissFromStubFailure);
757DECLARE_RUNTIME_FUNCTION(ElementsTransitionAndStoreIC_Miss);
758DECLARE_RUNTIME_FUNCTION(BinaryOpIC_Miss);
759DECLARE_RUNTIME_FUNCTION(BinaryOpIC_MissWithAllocationSite);
760DECLARE_RUNTIME_FUNCTION(CompareNilIC_Miss);
761DECLARE_RUNTIME_FUNCTION(ToBooleanIC_Miss);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400762DECLARE_RUNTIME_FUNCTION(LoadIC_MissFromStubFailure);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000763
764// Support functions for callbacks handlers.
765DECLARE_RUNTIME_FUNCTION(StoreCallbackProperty);
766
767// Support functions for interceptor handlers.
768DECLARE_RUNTIME_FUNCTION(LoadPropertyWithInterceptorOnly);
769DECLARE_RUNTIME_FUNCTION(LoadPropertyWithInterceptor);
770DECLARE_RUNTIME_FUNCTION(LoadElementWithInterceptor);
771DECLARE_RUNTIME_FUNCTION(StorePropertyWithInterceptor);
772}
773} // namespace v8::internal
774
775#endif // V8_IC_H_