Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7)

Side by Side Diff: src/ic.h

Issue 483683005: Move IC code into a subdir and move ic-compilation related code from stub-cache into ic-compiler (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fix BUILD.gn Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/stub-cache-ia32.cc ('k') | src/ic.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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_H_
6 #define V8_IC_H_
7
8 #include "src/macro-assembler.h"
9
10 namespace v8 {
11 namespace internal {
12
13
14 const int kMaxKeyedPolymorphism = 4;
15
16
17 // IC_UTIL_LIST defines all utility functions called from generated
18 // inline caching code. The argument for the macro, ICU, is the function name.
19 #define IC_UTIL_LIST(ICU) \
20 ICU(LoadIC_Miss) \
21 ICU(KeyedLoadIC_Miss) \
22 ICU(CallIC_Miss) \
23 ICU(CallIC_Customization_Miss) \
24 ICU(StoreIC_Miss) \
25 ICU(StoreIC_Slow) \
26 ICU(SharedStoreIC_ExtendStorage) \
27 ICU(KeyedStoreIC_Miss) \
28 ICU(KeyedStoreIC_Slow) \
29 /* Utilities for IC stubs. */ \
30 ICU(StoreCallbackProperty) \
31 ICU(LoadPropertyWithInterceptorOnly) \
32 ICU(LoadPropertyWithInterceptor) \
33 ICU(LoadElementWithInterceptor) \
34 ICU(StorePropertyWithInterceptor) \
35 ICU(CompareIC_Miss) \
36 ICU(BinaryOpIC_Miss) \
37 ICU(CompareNilIC_Miss) \
38 ICU(Unreachable) \
39 ICU(ToBooleanIC_Miss)
40 //
41 // IC is the base class for LoadIC, StoreIC, KeyedLoadIC, and KeyedStoreIC.
42 //
43 class IC {
44 public:
45 // The ids for utility called from the generated code.
46 enum UtilityId {
47 #define CONST_NAME(name) k##name,
48 IC_UTIL_LIST(CONST_NAME)
49 #undef CONST_NAME
50 kUtilityCount
51 };
52
53 // Looks up the address of the named utility.
54 static Address AddressFromUtilityId(UtilityId id);
55
56 // Alias the inline cache state type to make the IC code more readable.
57 typedef InlineCacheState State;
58
59 // The IC code is either invoked with no extra frames on the stack
60 // or with a single extra frame for supporting calls.
61 enum FrameDepth {
62 NO_EXTRA_FRAME = 0,
63 EXTRA_CALL_FRAME = 1
64 };
65
66 // Construct the IC structure with the given number of extra
67 // JavaScript frames on the stack.
68 IC(FrameDepth depth, Isolate* isolate);
69 virtual ~IC() {}
70
71 State state() const { return state_; }
72 inline Address address() const;
73
74 // Compute the current IC state based on the target stub, receiver and name.
75 void UpdateState(Handle<Object> receiver, Handle<Object> name);
76
77 bool IsNameCompatibleWithPrototypeFailure(Handle<Object> name);
78 void MarkPrototypeFailure(Handle<Object> name) {
79 DCHECK(IsNameCompatibleWithPrototypeFailure(name));
80 state_ = PROTOTYPE_FAILURE;
81 }
82
83 // If the stub contains weak maps then this function adds the stub to
84 // the dependent code array of each weak map.
85 static void RegisterWeakMapDependency(Handle<Code> stub);
86
87 // This function is called when a weak map in the stub is dying,
88 // invalidates the stub by setting maps in it to undefined.
89 static void InvalidateMaps(Code* stub);
90
91 // Clear the inline cache to initial state.
92 static void Clear(Isolate* isolate,
93 Address address,
94 ConstantPoolArray* constant_pool);
95
96 #ifdef DEBUG
97 bool IsLoadStub() const {
98 return target()->is_load_stub() || target()->is_keyed_load_stub();
99 }
100
101 bool IsStoreStub() const {
102 return target()->is_store_stub() || target()->is_keyed_store_stub();
103 }
104
105 bool IsCallStub() const {
106 return target()->is_call_stub();
107 }
108 #endif
109
110 template <class TypeClass>
111 static JSFunction* GetRootConstructor(TypeClass* type,
112 Context* native_context);
113 static inline Handle<Map> GetHandlerCacheHolder(HeapType* type,
114 bool receiver_is_holder,
115 Isolate* isolate,
116 CacheHolderFlag* flag);
117 static inline Handle<Map> GetICCacheHolder(HeapType* type, Isolate* isolate,
118 CacheHolderFlag* flag);
119
120 static bool IsCleared(Code* code) {
121 InlineCacheState state = code->ic_state();
122 return state == UNINITIALIZED || state == PREMONOMORPHIC;
123 }
124
125 // Utility functions to convert maps to types and back. There are two special
126 // cases:
127 // - The heap_number_map is used as a marker which includes heap numbers as
128 // well as smis.
129 // - The oddball map is only used for booleans.
130 static Handle<Map> TypeToMap(HeapType* type, Isolate* isolate);
131 template <class T>
132 static typename T::TypeHandle MapToType(Handle<Map> map,
133 typename T::Region* region);
134
135 static Handle<HeapType> CurrentTypeOf(Handle<Object> object,
136 Isolate* isolate);
137
138 protected:
139 // Get the call-site target; used for determining the state.
140 Handle<Code> target() const { return target_; }
141
142 Address fp() const { return fp_; }
143 Address pc() const { return *pc_address_; }
144 Isolate* isolate() const { return isolate_; }
145
146 // Get the shared function info of the caller.
147 SharedFunctionInfo* GetSharedFunctionInfo() const;
148 // Get the code object of the caller.
149 Code* GetCode() const;
150 // Get the original (non-breakpointed) code object of the caller.
151 Code* GetOriginalCode() const;
152
153 // Set the call-site target.
154 void set_target(Code* code) {
155 #ifdef VERIFY_HEAP
156 code->VerifyEmbeddedObjectsDependency();
157 #endif
158 SetTargetAtAddress(address(), code, constant_pool());
159 target_set_ = true;
160 }
161
162 bool is_target_set() { return target_set_; }
163
164 char TransitionMarkFromState(IC::State state);
165 void TraceIC(const char* type, Handle<Object> name);
166 void TraceIC(const char* type, Handle<Object> name, State old_state,
167 State new_state);
168
169 MaybeHandle<Object> TypeError(const char* type,
170 Handle<Object> object,
171 Handle<Object> key);
172 MaybeHandle<Object> ReferenceError(const char* type, Handle<Name> name);
173
174 // Access the target code for the given IC address.
175 static inline Code* GetTargetAtAddress(Address address,
176 ConstantPoolArray* constant_pool);
177 static inline void SetTargetAtAddress(Address address,
178 Code* target,
179 ConstantPoolArray* constant_pool);
180 static void OnTypeFeedbackChanged(Isolate* isolate, Address address,
181 State old_state, State new_state,
182 bool target_remains_ic_stub);
183 static void PostPatching(Address address, Code* target, Code* old_target);
184
185 // Compute the handler either by compiling or by retrieving a cached version.
186 Handle<Code> ComputeHandler(LookupIterator* lookup,
187 Handle<Object> value = Handle<Code>::null());
188 virtual Handle<Code> CompileHandler(LookupIterator* lookup,
189 Handle<Object> value,
190 CacheHolderFlag cache_holder) {
191 UNREACHABLE();
192 return Handle<Code>::null();
193 }
194
195 void UpdateMonomorphicIC(Handle<Code> handler, Handle<Name> name);
196 bool UpdatePolymorphicIC(Handle<Name> name, Handle<Code> code);
197 void UpdateMegamorphicCache(HeapType* type, Name* name, Code* code);
198
199 void CopyICToMegamorphicCache(Handle<Name> name);
200 bool IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map);
201 void PatchCache(Handle<Name> name, Handle<Code> code);
202 Code::Kind kind() const { return kind_; }
203 Code::Kind handler_kind() const {
204 if (kind_ == Code::KEYED_LOAD_IC) return Code::LOAD_IC;
205 DCHECK(kind_ == Code::LOAD_IC || kind_ == Code::STORE_IC ||
206 kind_ == Code::KEYED_STORE_IC);
207 return kind_;
208 }
209 virtual Handle<Code> megamorphic_stub() {
210 UNREACHABLE();
211 return Handle<Code>::null();
212 }
213
214 bool TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver,
215 Handle<String> name);
216
217 ExtraICState extra_ic_state() const { return extra_ic_state_; }
218 void set_extra_ic_state(ExtraICState state) {
219 extra_ic_state_ = state;
220 }
221
222 Handle<HeapType> receiver_type() { return receiver_type_; }
223 void update_receiver_type(Handle<Object> receiver) {
224 receiver_type_ = CurrentTypeOf(receiver, isolate_);
225 }
226
227 void TargetMaps(MapHandleList* list) {
228 FindTargetMaps();
229 for (int i = 0; i < target_maps_.length(); i++) {
230 list->Add(target_maps_.at(i));
231 }
232 }
233
234 void TargetTypes(TypeHandleList* list) {
235 FindTargetMaps();
236 for (int i = 0; i < target_maps_.length(); i++) {
237 list->Add(IC::MapToType<HeapType>(target_maps_.at(i), isolate_));
238 }
239 }
240
241 Map* FirstTargetMap() {
242 FindTargetMaps();
243 return target_maps_.length() > 0 ? *target_maps_.at(0) : NULL;
244 }
245
246 protected:
247 void UpdateTarget() {
248 target_ = handle(raw_target(), isolate_);
249 }
250
251 private:
252 Code* raw_target() const {
253 return GetTargetAtAddress(address(), constant_pool());
254 }
255 inline ConstantPoolArray* constant_pool() const;
256 inline ConstantPoolArray* raw_constant_pool() const;
257
258 void FindTargetMaps() {
259 if (target_maps_set_) return;
260 target_maps_set_ = true;
261 if (state_ == MONOMORPHIC) {
262 Map* map = target_->FindFirstMap();
263 if (map != NULL) target_maps_.Add(handle(map));
264 } else if (state_ != UNINITIALIZED && state_ != PREMONOMORPHIC) {
265 target_->FindAllMaps(&target_maps_);
266 }
267 }
268
269 // Frame pointer for the frame that uses (calls) the IC.
270 Address fp_;
271
272 // All access to the program counter of an IC structure is indirect
273 // to make the code GC safe. This feature is crucial since
274 // GetProperty and SetProperty are called and they in turn might
275 // invoke the garbage collector.
276 Address* pc_address_;
277
278 Isolate* isolate_;
279
280 // The constant pool of the code which originally called the IC (which might
281 // be for the breakpointed copy of the original code).
282 Handle<ConstantPoolArray> raw_constant_pool_;
283
284 // The original code target that missed.
285 Handle<Code> target_;
286 bool target_set_;
287 State state_;
288 Code::Kind kind_;
289 Handle<HeapType> receiver_type_;
290 MaybeHandle<Code> maybe_handler_;
291
292 ExtraICState extra_ic_state_;
293 MapHandleList target_maps_;
294 bool target_maps_set_;
295
296 DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
297 };
298
299
300 // An IC_Utility encapsulates IC::UtilityId. It exists mainly because you
301 // cannot make forward declarations to an enum.
302 class IC_Utility {
303 public:
304 explicit IC_Utility(IC::UtilityId id)
305 : address_(IC::AddressFromUtilityId(id)), id_(id) {}
306
307 Address address() const { return address_; }
308
309 IC::UtilityId id() const { return id_; }
310 private:
311 Address address_;
312 IC::UtilityId id_;
313 };
314
315
316 class CallIC: public IC {
317 public:
318 enum CallType { METHOD, FUNCTION };
319
320 class State V8_FINAL BASE_EMBEDDED {
321 public:
322 explicit State(ExtraICState extra_ic_state);
323
324 State(int argc, CallType call_type)
325 : argc_(argc), call_type_(call_type) {
326 }
327
328 ExtraICState GetExtraICState() const;
329
330 static void GenerateAheadOfTime(
331 Isolate*, void (*Generate)(Isolate*, const State&));
332
333 int arg_count() const { return argc_; }
334 CallType call_type() const { return call_type_; }
335
336 bool CallAsMethod() const { return call_type_ == METHOD; }
337
338 private:
339 class ArgcBits: public BitField<int, 0, Code::kArgumentsBits> {};
340 class CallTypeBits: public BitField<CallType, Code::kArgumentsBits, 1> {};
341
342 const int argc_;
343 const CallType call_type_;
344 };
345
346 explicit CallIC(Isolate* isolate)
347 : IC(EXTRA_CALL_FRAME, isolate) {
348 }
349
350 void PatchMegamorphic(Handle<Object> function, Handle<FixedArray> vector,
351 Handle<Smi> slot);
352
353 void HandleMiss(Handle<Object> receiver,
354 Handle<Object> function,
355 Handle<FixedArray> vector,
356 Handle<Smi> slot);
357
358 // Returns true if a custom handler was installed.
359 bool DoCustomHandler(Handle<Object> receiver,
360 Handle<Object> function,
361 Handle<FixedArray> vector,
362 Handle<Smi> slot,
363 const State& state);
364
365 // Code generator routines.
366 static Handle<Code> initialize_stub(Isolate* isolate,
367 int argc,
368 CallType call_type);
369
370 static void Clear(Isolate* isolate, Address address, Code* target,
371 ConstantPoolArray* constant_pool);
372
373 private:
374 inline IC::State FeedbackToState(Handle<FixedArray> vector,
375 Handle<Smi> slot) const;
376 };
377
378
379 OStream& operator<<(OStream& os, const CallIC::State& s);
380
381
382 class LoadIC: public IC {
383 public:
384 enum ParameterIndices {
385 kReceiverIndex,
386 kNameIndex,
387 kParameterCount
388 };
389 static const Register ReceiverRegister();
390 static const Register NameRegister();
391
392 // With flag vector-ics, there is an additional argument. And for calls from
393 // crankshaft, yet another.
394 static const Register SlotRegister();
395 static const Register VectorRegister();
396
397 class State V8_FINAL BASE_EMBEDDED {
398 public:
399 explicit State(ExtraICState extra_ic_state)
400 : state_(extra_ic_state) {}
401
402 explicit State(ContextualMode mode)
403 : state_(ContextualModeBits::encode(mode)) {}
404
405 ExtraICState GetExtraICState() const { return state_; }
406
407 ContextualMode contextual_mode() const {
408 return ContextualModeBits::decode(state_);
409 }
410
411 private:
412 class ContextualModeBits: public BitField<ContextualMode, 0, 1> {};
413 STATIC_ASSERT(static_cast<int>(NOT_CONTEXTUAL) == 0);
414
415 const ExtraICState state_;
416 };
417
418 static ExtraICState ComputeExtraICState(ContextualMode contextual_mode) {
419 return State(contextual_mode).GetExtraICState();
420 }
421
422 static ContextualMode GetContextualMode(ExtraICState state) {
423 return State(state).contextual_mode();
424 }
425
426 ContextualMode contextual_mode() const {
427 return GetContextualMode(extra_ic_state());
428 }
429
430 explicit LoadIC(FrameDepth depth, Isolate* isolate)
431 : IC(depth, isolate) {
432 DCHECK(IsLoadStub());
433 }
434
435 // Returns if this IC is for contextual (no explicit receiver)
436 // access to properties.
437 bool IsUndeclaredGlobal(Handle<Object> receiver) {
438 if (receiver->IsGlobalObject()) {
439 return contextual_mode() == CONTEXTUAL;
440 } else {
441 DCHECK(contextual_mode() != CONTEXTUAL);
442 return false;
443 }
444 }
445
446 // Code generator routines.
447 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
448 static void GeneratePreMonomorphic(MacroAssembler* masm) {
449 GenerateMiss(masm);
450 }
451 static void GenerateMiss(MacroAssembler* masm);
452 static void GenerateMegamorphic(MacroAssembler* masm);
453 static void GenerateNormal(MacroAssembler* masm);
454 static void GenerateRuntimeGetProperty(MacroAssembler* masm);
455
456 static Handle<Code> initialize_stub(Isolate* isolate,
457 ExtraICState extra_state);
458
459 MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Object> object,
460 Handle<Name> name);
461
462 protected:
463 void set_target(Code* code) {
464 // The contextual mode must be preserved across IC patching.
465 DCHECK(GetContextualMode(code->extra_ic_state()) ==
466 GetContextualMode(target()->extra_ic_state()));
467
468 IC::set_target(code);
469 }
470
471 Handle<Code> slow_stub() const {
472 if (kind() == Code::LOAD_IC) {
473 return isolate()->builtins()->LoadIC_Slow();
474 } else {
475 DCHECK_EQ(Code::KEYED_LOAD_IC, kind());
476 return isolate()->builtins()->KeyedLoadIC_Slow();
477 }
478 }
479
480 virtual Handle<Code> megamorphic_stub();
481
482 // Update the inline cache and the global stub cache based on the
483 // lookup result.
484 void UpdateCaches(LookupIterator* lookup);
485
486 virtual Handle<Code> CompileHandler(LookupIterator* lookup,
487 Handle<Object> unused,
488 CacheHolderFlag cache_holder);
489
490 private:
491 virtual Handle<Code> pre_monomorphic_stub() const;
492 static Handle<Code> pre_monomorphic_stub(Isolate* isolate,
493 ExtraICState extra_state);
494
495 Handle<Code> SimpleFieldLoad(FieldIndex index);
496
497 static void Clear(Isolate* isolate,
498 Address address,
499 Code* target,
500 ConstantPoolArray* constant_pool);
501
502 friend class IC;
503 };
504
505
506 class KeyedLoadIC: public LoadIC {
507 public:
508 explicit KeyedLoadIC(FrameDepth depth, Isolate* isolate)
509 : LoadIC(depth, isolate) {
510 DCHECK(target()->is_keyed_load_stub());
511 }
512
513 MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Object> object,
514 Handle<Object> key);
515
516 // Code generator routines.
517 static void GenerateMiss(MacroAssembler* masm);
518 static void GenerateRuntimeGetProperty(MacroAssembler* masm);
519 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
520 static void GeneratePreMonomorphic(MacroAssembler* masm) {
521 GenerateMiss(masm);
522 }
523 static void GenerateGeneric(MacroAssembler* masm);
524 static void GenerateString(MacroAssembler* masm);
525 static void GenerateIndexedInterceptor(MacroAssembler* masm);
526 static void GenerateSloppyArguments(MacroAssembler* masm);
527
528 // Bit mask to be tested against bit field for the cases when
529 // generic stub should go into slow case.
530 // Access check is necessary explicitly since generic stub does not perform
531 // map checks.
532 static const int kSlowCaseBitFieldMask =
533 (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor);
534
535 static Handle<Code> generic_stub(Isolate* isolate);
536 static Handle<Code> pre_monomorphic_stub(Isolate* isolate);
537
538 protected:
539 Handle<Code> LoadElementStub(Handle<JSObject> receiver);
540 virtual Handle<Code> pre_monomorphic_stub() const {
541 return pre_monomorphic_stub(isolate());
542 }
543
544 private:
545 Handle<Code> generic_stub() const { return generic_stub(isolate()); }
546 Handle<Code> indexed_interceptor_stub() {
547 return isolate()->builtins()->KeyedLoadIC_IndexedInterceptor();
548 }
549 Handle<Code> sloppy_arguments_stub() {
550 return isolate()->builtins()->KeyedLoadIC_SloppyArguments();
551 }
552 Handle<Code> string_stub() {
553 return isolate()->builtins()->KeyedLoadIC_String();
554 }
555
556 static void Clear(Isolate* isolate,
557 Address address,
558 Code* target,
559 ConstantPoolArray* constant_pool);
560
561 friend class IC;
562 };
563
564
565 class StoreIC: public IC {
566 public:
567 class StrictModeState: public BitField<StrictMode, 1, 1> {};
568 static ExtraICState ComputeExtraICState(StrictMode flag) {
569 return StrictModeState::encode(flag);
570 }
571 static StrictMode GetStrictMode(ExtraICState state) {
572 return StrictModeState::decode(state);
573 }
574
575 // For convenience, a statically declared encoding of strict mode extra
576 // IC state.
577 static const ExtraICState kStrictModeState =
578 1 << StrictModeState::kShift;
579
580 enum ParameterIndices {
581 kReceiverIndex,
582 kNameIndex,
583 kValueIndex,
584 kParameterCount
585 };
586 static const Register ReceiverRegister();
587 static const Register NameRegister();
588 static const Register ValueRegister();
589
590 StoreIC(FrameDepth depth, Isolate* isolate)
591 : IC(depth, isolate) {
592 DCHECK(IsStoreStub());
593 }
594
595 StrictMode strict_mode() const {
596 return StrictModeState::decode(extra_ic_state());
597 }
598
599 // Code generators for stub routines. Only called once at startup.
600 static void GenerateSlow(MacroAssembler* masm);
601 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
602 static void GeneratePreMonomorphic(MacroAssembler* masm) {
603 GenerateMiss(masm);
604 }
605 static void GenerateMiss(MacroAssembler* masm);
606 static void GenerateMegamorphic(MacroAssembler* masm);
607 static void GenerateNormal(MacroAssembler* masm);
608 static void GenerateRuntimeSetProperty(MacroAssembler* masm,
609 StrictMode strict_mode);
610
611 static Handle<Code> initialize_stub(Isolate* isolate,
612 StrictMode strict_mode);
613
614 MUST_USE_RESULT MaybeHandle<Object> Store(
615 Handle<Object> object,
616 Handle<Name> name,
617 Handle<Object> value,
618 JSReceiver::StoreFromKeyed store_mode =
619 JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED);
620
621 bool LookupForWrite(LookupIterator* it, Handle<Object> value,
622 JSReceiver::StoreFromKeyed store_mode);
623
624 protected:
625 virtual Handle<Code> megamorphic_stub();
626
627 // Stub accessors.
628 virtual Handle<Code> generic_stub() const;
629
630 virtual Handle<Code> slow_stub() const {
631 return isolate()->builtins()->StoreIC_Slow();
632 }
633
634 virtual Handle<Code> pre_monomorphic_stub() const {
635 return pre_monomorphic_stub(isolate(), strict_mode());
636 }
637
638 static Handle<Code> pre_monomorphic_stub(Isolate* isolate,
639 StrictMode strict_mode);
640
641 // Update the inline cache and the global stub cache based on the
642 // lookup result.
643 void UpdateCaches(LookupIterator* lookup, Handle<Object> value,
644 JSReceiver::StoreFromKeyed store_mode);
645 virtual Handle<Code> CompileHandler(LookupIterator* lookup,
646 Handle<Object> value,
647 CacheHolderFlag cache_holder);
648
649 private:
650 void set_target(Code* code) {
651 // Strict mode must be preserved across IC patching.
652 DCHECK(GetStrictMode(code->extra_ic_state()) ==
653 GetStrictMode(target()->extra_ic_state()));
654 IC::set_target(code);
655 }
656
657 static void Clear(Isolate* isolate,
658 Address address,
659 Code* target,
660 ConstantPoolArray* constant_pool);
661
662 friend class IC;
663 };
664
665
666 enum KeyedStoreCheckMap {
667 kDontCheckMap,
668 kCheckMap
669 };
670
671
672 enum KeyedStoreIncrementLength {
673 kDontIncrementLength,
674 kIncrementLength
675 };
676
677
678 class KeyedStoreIC: public StoreIC {
679 public:
680 // ExtraICState bits (building on IC)
681 // ExtraICState bits
682 class ExtraICStateKeyedAccessStoreMode:
683 public BitField<KeyedAccessStoreMode, 2, 4> {}; // NOLINT
684
685 static ExtraICState ComputeExtraICState(StrictMode flag,
686 KeyedAccessStoreMode mode) {
687 return StrictModeState::encode(flag) |
688 ExtraICStateKeyedAccessStoreMode::encode(mode);
689 }
690
691 static KeyedAccessStoreMode GetKeyedAccessStoreMode(
692 ExtraICState extra_state) {
693 return ExtraICStateKeyedAccessStoreMode::decode(extra_state);
694 }
695
696 // The map register isn't part of the normal call specification, but
697 // ElementsTransitionAndStoreStub, used in polymorphic keyed store
698 // stub implementations requires it to be initialized.
699 static const Register MapRegister();
700
701 KeyedStoreIC(FrameDepth depth, Isolate* isolate)
702 : StoreIC(depth, isolate) {
703 DCHECK(target()->is_keyed_store_stub());
704 }
705
706 MUST_USE_RESULT MaybeHandle<Object> Store(Handle<Object> object,
707 Handle<Object> name,
708 Handle<Object> value);
709
710 // Code generators for stub routines. Only called once at startup.
711 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
712 static void GeneratePreMonomorphic(MacroAssembler* masm) {
713 GenerateMiss(masm);
714 }
715 static void GenerateMiss(MacroAssembler* masm);
716 static void GenerateSlow(MacroAssembler* masm);
717 static void GenerateRuntimeSetProperty(MacroAssembler* masm,
718 StrictMode strict_mode);
719 static void GenerateGeneric(MacroAssembler* masm, StrictMode strict_mode);
720 static void GenerateSloppyArguments(MacroAssembler* masm);
721
722 protected:
723 virtual Handle<Code> pre_monomorphic_stub() const {
724 return pre_monomorphic_stub(isolate(), strict_mode());
725 }
726 static Handle<Code> pre_monomorphic_stub(Isolate* isolate,
727 StrictMode strict_mode) {
728 if (strict_mode == STRICT) {
729 return isolate->builtins()->KeyedStoreIC_PreMonomorphic_Strict();
730 } else {
731 return isolate->builtins()->KeyedStoreIC_PreMonomorphic();
732 }
733 }
734 virtual Handle<Code> slow_stub() const {
735 return isolate()->builtins()->KeyedStoreIC_Slow();
736 }
737 virtual Handle<Code> megamorphic_stub() {
738 if (strict_mode() == STRICT) {
739 return isolate()->builtins()->KeyedStoreIC_Generic_Strict();
740 } else {
741 return isolate()->builtins()->KeyedStoreIC_Generic();
742 }
743 }
744
745 Handle<Code> StoreElementStub(Handle<JSObject> receiver,
746 KeyedAccessStoreMode store_mode);
747
748 private:
749 void set_target(Code* code) {
750 // Strict mode must be preserved across IC patching.
751 DCHECK(GetStrictMode(code->extra_ic_state()) == strict_mode());
752 IC::set_target(code);
753 }
754
755 // Stub accessors.
756 virtual Handle<Code> generic_stub() const {
757 if (strict_mode() == STRICT) {
758 return isolate()->builtins()->KeyedStoreIC_Generic_Strict();
759 } else {
760 return isolate()->builtins()->KeyedStoreIC_Generic();
761 }
762 }
763
764 Handle<Code> sloppy_arguments_stub() {
765 return isolate()->builtins()->KeyedStoreIC_SloppyArguments();
766 }
767
768 static void Clear(Isolate* isolate,
769 Address address,
770 Code* target,
771 ConstantPoolArray* constant_pool);
772
773 KeyedAccessStoreMode GetStoreMode(Handle<JSObject> receiver,
774 Handle<Object> key,
775 Handle<Object> value);
776
777 Handle<Map> ComputeTransitionedMap(Handle<Map> map,
778 KeyedAccessStoreMode store_mode);
779
780 friend class IC;
781 };
782
783
784 // Mode to overwrite BinaryExpression values.
785 enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
786
787 // Type Recording BinaryOpIC, that records the types of the inputs and outputs.
788 class BinaryOpIC: public IC {
789 public:
790 class State V8_FINAL BASE_EMBEDDED {
791 public:
792 State(Isolate* isolate, ExtraICState extra_ic_state);
793
794 State(Isolate* isolate, Token::Value op, OverwriteMode mode)
795 : op_(op), mode_(mode), left_kind_(NONE), right_kind_(NONE),
796 result_kind_(NONE), isolate_(isolate) {
797 DCHECK_LE(FIRST_TOKEN, op);
798 DCHECK_LE(op, LAST_TOKEN);
799 }
800
801 InlineCacheState GetICState() const {
802 if (Max(left_kind_, right_kind_) == NONE) {
803 return ::v8::internal::UNINITIALIZED;
804 }
805 if (Max(left_kind_, right_kind_) == GENERIC) {
806 return ::v8::internal::MEGAMORPHIC;
807 }
808 if (Min(left_kind_, right_kind_) == GENERIC) {
809 return ::v8::internal::GENERIC;
810 }
811 return ::v8::internal::MONOMORPHIC;
812 }
813
814 ExtraICState GetExtraICState() const;
815
816 static void GenerateAheadOfTime(
817 Isolate*, void (*Generate)(Isolate*, const State&));
818
819 bool CanReuseDoubleBox() const {
820 return (result_kind_ > SMI && result_kind_ <= NUMBER) &&
821 ((mode_ == OVERWRITE_LEFT &&
822 left_kind_ > SMI && left_kind_ <= NUMBER) ||
823 (mode_ == OVERWRITE_RIGHT &&
824 right_kind_ > SMI && right_kind_ <= NUMBER));
825 }
826
827 // Returns true if the IC _could_ create allocation mementos.
828 bool CouldCreateAllocationMementos() const {
829 if (left_kind_ == STRING || right_kind_ == STRING) {
830 DCHECK_EQ(Token::ADD, op_);
831 return true;
832 }
833 return false;
834 }
835
836 // Returns true if the IC _should_ create allocation mementos.
837 bool ShouldCreateAllocationMementos() const {
838 return FLAG_allocation_site_pretenuring &&
839 CouldCreateAllocationMementos();
840 }
841
842 bool HasSideEffects() const {
843 return Max(left_kind_, right_kind_) == GENERIC;
844 }
845
846 // Returns true if the IC should enable the inline smi code (i.e. if either
847 // parameter may be a smi).
848 bool UseInlinedSmiCode() const {
849 return KindMaybeSmi(left_kind_) || KindMaybeSmi(right_kind_);
850 }
851
852 static const int FIRST_TOKEN = Token::BIT_OR;
853 static const int LAST_TOKEN = Token::MOD;
854
855 Token::Value op() const { return op_; }
856 OverwriteMode mode() const { return mode_; }
857 Maybe<int> fixed_right_arg() const { return fixed_right_arg_; }
858
859 Type* GetLeftType(Zone* zone) const {
860 return KindToType(left_kind_, zone);
861 }
862 Type* GetRightType(Zone* zone) const {
863 return KindToType(right_kind_, zone);
864 }
865 Type* GetResultType(Zone* zone) const;
866
867 void Update(Handle<Object> left,
868 Handle<Object> right,
869 Handle<Object> result);
870
871 Isolate* isolate() const { return isolate_; }
872
873 private:
874 friend OStream& operator<<(OStream& os, const BinaryOpIC::State& s);
875
876 enum Kind { NONE, SMI, INT32, NUMBER, STRING, GENERIC };
877
878 Kind UpdateKind(Handle<Object> object, Kind kind) const;
879
880 static const char* KindToString(Kind kind);
881 static Type* KindToType(Kind kind, Zone* zone);
882 static bool KindMaybeSmi(Kind kind) {
883 return (kind >= SMI && kind <= NUMBER) || kind == GENERIC;
884 }
885
886 // We truncate the last bit of the token.
887 STATIC_ASSERT(LAST_TOKEN - FIRST_TOKEN < (1 << 4));
888 class OpField: public BitField<int, 0, 4> {};
889 class OverwriteModeField: public BitField<OverwriteMode, 4, 2> {};
890 class ResultKindField: public BitField<Kind, 6, 3> {};
891 class LeftKindField: public BitField<Kind, 9, 3> {};
892 // When fixed right arg is set, we don't need to store the right kind.
893 // Thus the two fields can overlap.
894 class HasFixedRightArgField: public BitField<bool, 12, 1> {};
895 class FixedRightArgValueField: public BitField<int, 13, 4> {};
896 class RightKindField: public BitField<Kind, 13, 3> {};
897
898 Token::Value op_;
899 OverwriteMode mode_;
900 Kind left_kind_;
901 Kind right_kind_;
902 Kind result_kind_;
903 Maybe<int> fixed_right_arg_;
904 Isolate* isolate_;
905 };
906
907 explicit BinaryOpIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) { }
908
909 static Builtins::JavaScript TokenToJSBuiltin(Token::Value op);
910
911 MaybeHandle<Object> Transition(Handle<AllocationSite> allocation_site,
912 Handle<Object> left,
913 Handle<Object> right) V8_WARN_UNUSED_RESULT;
914 };
915
916
917 OStream& operator<<(OStream& os, const BinaryOpIC::State& s);
918
919
920 class CompareIC: public IC {
921 public:
922 // The type/state lattice is defined by the following inequations:
923 // UNINITIALIZED < ...
924 // ... < GENERIC
925 // SMI < NUMBER
926 // INTERNALIZED_STRING < STRING
927 // KNOWN_OBJECT < OBJECT
928 enum State {
929 UNINITIALIZED,
930 SMI,
931 NUMBER,
932 STRING,
933 INTERNALIZED_STRING,
934 UNIQUE_NAME, // Symbol or InternalizedString
935 OBJECT, // JSObject
936 KNOWN_OBJECT, // JSObject with specific map (faster check)
937 GENERIC
938 };
939
940 static State NewInputState(State old_state, Handle<Object> value);
941
942 static Type* StateToType(Zone* zone,
943 State state,
944 Handle<Map> map = Handle<Map>());
945
946 static void StubInfoToType(uint32_t stub_key, Type** left_type,
947 Type** right_type, Type** overall_type,
948 Handle<Map> map, Zone* zone);
949
950 CompareIC(Isolate* isolate, Token::Value op)
951 : IC(EXTRA_CALL_FRAME, isolate), op_(op) { }
952
953 // Update the inline cache for the given operands.
954 Code* UpdateCaches(Handle<Object> x, Handle<Object> y);
955
956
957 // Factory method for getting an uninitialized compare stub.
958 static Handle<Code> GetUninitialized(Isolate* isolate, Token::Value op);
959
960 // Helper function for computing the condition for a compare operation.
961 static Condition ComputeCondition(Token::Value op);
962
963 static const char* GetStateName(State state);
964
965 private:
966 static bool HasInlinedSmiCode(Address address);
967
968 State TargetState(State old_state,
969 State old_left,
970 State old_right,
971 bool has_inlined_smi_code,
972 Handle<Object> x,
973 Handle<Object> y);
974
975 bool strict() const { return op_ == Token::EQ_STRICT; }
976 Condition GetCondition() const { return ComputeCondition(op_); }
977
978 static Code* GetRawUninitialized(Isolate* isolate, Token::Value op);
979
980 static void Clear(Isolate* isolate,
981 Address address,
982 Code* target,
983 ConstantPoolArray* constant_pool);
984
985 Token::Value op_;
986
987 friend class IC;
988 };
989
990
991 class CompareNilIC: public IC {
992 public:
993 explicit CompareNilIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) {}
994
995 Handle<Object> CompareNil(Handle<Object> object);
996
997 static Handle<Code> GetUninitialized();
998
999 static void Clear(Address address,
1000 Code* target,
1001 ConstantPoolArray* constant_pool);
1002
1003 static Handle<Object> DoCompareNilSlow(Isolate* isolate, NilValue nil,
1004 Handle<Object> object);
1005 };
1006
1007
1008 class ToBooleanIC: public IC {
1009 public:
1010 explicit ToBooleanIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) { }
1011
1012 Handle<Object> ToBoolean(Handle<Object> object);
1013 };
1014
1015
1016 // Helper for BinaryOpIC and CompareIC.
1017 enum InlinedSmiCheck { ENABLE_INLINED_SMI_CHECK, DISABLE_INLINED_SMI_CHECK };
1018 void PatchInlinedSmiCode(Address address, InlinedSmiCheck check);
1019
1020 DECLARE_RUNTIME_FUNCTION(KeyedLoadIC_MissFromStubFailure);
1021 DECLARE_RUNTIME_FUNCTION(KeyedStoreIC_MissFromStubFailure);
1022 DECLARE_RUNTIME_FUNCTION(UnaryOpIC_Miss);
1023 DECLARE_RUNTIME_FUNCTION(StoreIC_MissFromStubFailure);
1024 DECLARE_RUNTIME_FUNCTION(ElementsTransitionAndStoreIC_Miss);
1025 DECLARE_RUNTIME_FUNCTION(BinaryOpIC_Miss);
1026 DECLARE_RUNTIME_FUNCTION(BinaryOpIC_MissWithAllocationSite);
1027 DECLARE_RUNTIME_FUNCTION(CompareNilIC_Miss);
1028 DECLARE_RUNTIME_FUNCTION(ToBooleanIC_Miss);
1029
1030
1031 } } // namespace v8::internal
1032
1033 #endif // V8_IC_H_
OLDNEW
« no previous file with comments | « src/ia32/stub-cache-ia32.cc ('k') | src/ic.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698