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/ic/ic-state.h" 9 #include "src/macro-assembler.h" 10 #include "src/messages.h" 11 12 namespace v8 { 13 namespace internal { 14 15 // 16 // IC is the base class for LoadIC, StoreIC, KeyedLoadIC, and KeyedStoreIC. 17 // 18 class IC { 19 public: 20 // Alias the inline cache state type to make the IC code more readable. 21 typedef InlineCacheState State; 22 23 // The IC code is either invoked with no extra frames on the stack 24 // or with a single extra frame for supporting calls. 25 enum FrameDepth { NO_EXTRA_FRAME = 0, EXTRA_CALL_FRAME = 1 }; 26 27 // Construct the IC structure with the given number of extra 28 // JavaScript frames on the stack. 29 IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus = NULL); ~IC()30 virtual ~IC() {} 31 state()32 State state() const { return state_; } 33 inline Address address() const; 34 35 // Compute the current IC state based on the target stub, receiver and name. 36 void UpdateState(Handle<Object> receiver, Handle<Object> name); 37 38 bool IsNameCompatibleWithPrototypeFailure(Handle<Object> name); MarkPrototypeFailure(Handle<Object> name)39 void MarkPrototypeFailure(Handle<Object> name) { 40 DCHECK(IsNameCompatibleWithPrototypeFailure(name)); 41 old_state_ = state_; 42 state_ = PROTOTYPE_FAILURE; 43 } 44 45 // Clear the inline cache to initial state. 46 static void Clear(Isolate* isolate, Address address, Address constant_pool); 47 48 #ifdef DEBUG IsLoadStub()49 bool IsLoadStub() const { 50 return target()->is_load_stub() || target()->is_keyed_load_stub(); 51 } 52 IsStoreStub()53 bool IsStoreStub() const { 54 return target()->is_store_stub() || target()->is_keyed_store_stub(); 55 } 56 IsCallStub()57 bool IsCallStub() const { return target()->is_call_stub(); } 58 #endif 59 60 static inline Handle<Map> GetHandlerCacheHolder(Handle<Map> receiver_map, 61 bool receiver_is_holder, 62 Isolate* isolate, 63 CacheHolderFlag* flag); 64 static inline Handle<Map> GetICCacheHolder(Handle<Map> receiver_map, 65 Isolate* isolate, 66 CacheHolderFlag* flag); 67 IsCleared(Code * code)68 static bool IsCleared(Code* code) { 69 InlineCacheState state = code->ic_state(); 70 return !FLAG_use_ic || state == UNINITIALIZED || state == PREMONOMORPHIC; 71 } 72 IsCleared(FeedbackNexus * nexus)73 static bool IsCleared(FeedbackNexus* nexus) { 74 InlineCacheState state = nexus->StateFromFeedback(); 75 return !FLAG_use_ic || state == UNINITIALIZED || state == PREMONOMORPHIC; 76 } 77 ICUseVector(Code::Kind kind)78 static bool ICUseVector(Code::Kind kind) { 79 return kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC || 80 kind == Code::CALL_IC || kind == Code::STORE_IC || 81 kind == Code::KEYED_STORE_IC; 82 } 83 84 protected: 85 // Get the call-site target; used for determining the state. target()86 Handle<Code> target() const { return target_; } 87 fp()88 Address fp() const { return fp_; } pc()89 Address pc() const { return *pc_address_; } isolate()90 Isolate* isolate() const { return isolate_; } 91 92 // Get the shared function info of the caller. 93 SharedFunctionInfo* GetSharedFunctionInfo() const; 94 // Get the code object of the caller. 95 Code* GetCode() const; 96 97 bool AddressIsOptimizedCode() const; 98 inline bool AddressIsDeoptimizedCode() const; 99 inline static bool AddressIsDeoptimizedCode(Isolate* isolate, 100 Address address); 101 102 // Set the call-site target. 103 inline void set_target(Code* code); is_target_set()104 bool is_target_set() { return target_set_; } is_vector_set()105 bool is_vector_set() { return vector_set_; } 106 UseVector()107 bool UseVector() const { 108 bool use = ICUseVector(kind()); 109 // If we are supposed to use the nexus, verify the nexus is non-null. 110 DCHECK(!use || nexus_ != NULL); 111 return use; 112 } 113 114 // Configure for most states. 115 void ConfigureVectorState(IC::State new_state); 116 // Configure the vector for MONOMORPHIC. 117 void ConfigureVectorState(Handle<Name> name, Handle<Map> map, 118 Handle<Code> handler); 119 // Configure the vector for POLYMORPHIC. 120 void ConfigureVectorState(Handle<Name> name, MapHandleList* maps, 121 CodeHandleList* handlers); 122 // Configure the vector for POLYMORPHIC with transitions (only for element 123 // keyed stores). 124 void ConfigureVectorState(MapHandleList* maps, 125 MapHandleList* transitioned_maps, 126 CodeHandleList* handlers); 127 128 char TransitionMarkFromState(IC::State state); 129 void TraceIC(const char* type, Handle<Object> name); 130 void TraceIC(const char* type, Handle<Object> name, State old_state, 131 State new_state); 132 133 MaybeHandle<Object> TypeError(MessageTemplate::Template, 134 Handle<Object> object, Handle<Object> key); 135 MaybeHandle<Object> ReferenceError(Handle<Name> name); 136 137 // Access the target code for the given IC address. 138 static inline Code* GetTargetAtAddress(Address address, 139 Address constant_pool); 140 static inline void SetTargetAtAddress(Address address, Code* target, 141 Address constant_pool); 142 static void OnTypeFeedbackChanged(Isolate* isolate, Address address, 143 State old_state, State new_state, 144 bool target_remains_ic_stub); 145 // As a vector-based IC, type feedback must be updated differently. 146 static void OnTypeFeedbackChanged(Isolate* isolate, Code* host); 147 static void PostPatching(Address address, Code* target, Code* old_target); 148 149 // Compute the handler either by compiling or by retrieving a cached version. 150 Handle<Code> ComputeHandler(LookupIterator* lookup, 151 Handle<Object> value = Handle<Code>::null()); CompileHandler(LookupIterator * lookup,Handle<Object> value,CacheHolderFlag cache_holder)152 virtual Handle<Code> CompileHandler(LookupIterator* lookup, 153 Handle<Object> value, 154 CacheHolderFlag cache_holder) { 155 UNREACHABLE(); 156 return Handle<Code>::null(); 157 } 158 159 void UpdateMonomorphicIC(Handle<Code> handler, Handle<Name> name); 160 bool UpdatePolymorphicIC(Handle<Name> name, Handle<Code> code); 161 void UpdateMegamorphicCache(Map* map, Name* name, Code* code); 162 163 void CopyICToMegamorphicCache(Handle<Name> name); 164 bool IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map); 165 void PatchCache(Handle<Name> name, Handle<Code> code); kind()166 Code::Kind kind() const { return kind_; } handler_kind()167 Code::Kind handler_kind() const { 168 if (kind_ == Code::KEYED_LOAD_IC) return Code::LOAD_IC; 169 DCHECK(kind_ == Code::LOAD_IC || kind_ == Code::STORE_IC || 170 kind_ == Code::KEYED_STORE_IC); 171 return kind_; 172 } megamorphic_stub()173 virtual Handle<Code> megamorphic_stub() { 174 UNREACHABLE(); 175 return Handle<Code>::null(); 176 } 177 178 bool TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver, 179 Handle<String> name); 180 extra_ic_state()181 ExtraICState extra_ic_state() const { return extra_ic_state_; } set_extra_ic_state(ExtraICState state)182 void set_extra_ic_state(ExtraICState state) { extra_ic_state_ = state; } 183 receiver_map()184 Handle<Map> receiver_map() { return receiver_map_; } update_receiver_map(Handle<Object> receiver)185 void update_receiver_map(Handle<Object> receiver) { 186 if (receiver->IsSmi()) { 187 receiver_map_ = isolate_->factory()->heap_number_map(); 188 } else { 189 receiver_map_ = handle(HeapObject::cast(*receiver)->map()); 190 } 191 } 192 TargetMaps(MapHandleList * list)193 void TargetMaps(MapHandleList* list) { 194 FindTargetMaps(); 195 for (int i = 0; i < target_maps_.length(); i++) { 196 list->Add(target_maps_.at(i)); 197 } 198 } 199 FirstTargetMap()200 Map* FirstTargetMap() { 201 FindTargetMaps(); 202 return target_maps_.length() > 0 ? *target_maps_.at(0) : NULL; 203 } 204 205 inline void UpdateTarget(); 206 vector()207 Handle<TypeFeedbackVector> vector() const { return nexus()->vector_handle(); } slot()208 FeedbackVectorSlot slot() const { return nexus()->slot(); } saved_state()209 State saved_state() const { 210 return state() == PROTOTYPE_FAILURE ? old_state_ : state(); 211 } 212 213 template <class NexusClass> casted_nexus()214 NexusClass* casted_nexus() { 215 return static_cast<NexusClass*>(nexus_); 216 } nexus()217 FeedbackNexus* nexus() const { return nexus_; } 218 219 inline Code* get_host(); 220 221 private: 222 inline Code* raw_target() const; 223 inline Address constant_pool() const; 224 inline Address raw_constant_pool() const; 225 FindTargetMaps()226 void FindTargetMaps() { 227 if (target_maps_set_) return; 228 target_maps_set_ = true; 229 if (UseVector()) { 230 nexus()->ExtractMaps(&target_maps_); 231 } else { 232 if (state_ == MONOMORPHIC) { 233 Map* map = target_->FindFirstMap(); 234 if (map != NULL) target_maps_.Add(handle(map)); 235 } else if (state_ != UNINITIALIZED && state_ != PREMONOMORPHIC) { 236 target_->FindAllMaps(&target_maps_); 237 } 238 } 239 } 240 241 // Frame pointer for the frame that uses (calls) the IC. 242 Address fp_; 243 244 // All access to the program counter and constant pool of an IC structure is 245 // indirect to make the code GC safe. This feature is crucial since 246 // GetProperty and SetProperty are called and they in turn might 247 // invoke the garbage collector. 248 Address* pc_address_; 249 250 // The constant pool of the code which originally called the IC (which might 251 // be for the breakpointed copy of the original code). 252 Address* constant_pool_address_; 253 254 Isolate* isolate_; 255 256 // The original code target that missed. 257 Handle<Code> target_; 258 bool target_set_; 259 bool vector_set_; 260 State old_state_; // For saving if we marked as prototype failure. 261 State state_; 262 Code::Kind kind_; 263 Handle<Map> receiver_map_; 264 MaybeHandle<Code> maybe_handler_; 265 266 ExtraICState extra_ic_state_; 267 MapHandleList target_maps_; 268 bool target_maps_set_; 269 270 FeedbackNexus* nexus_; 271 272 DISALLOW_IMPLICIT_CONSTRUCTORS(IC); 273 }; 274 275 276 class CallIC : public IC { 277 public: CallIC(Isolate * isolate,CallICNexus * nexus)278 CallIC(Isolate* isolate, CallICNexus* nexus) 279 : IC(EXTRA_CALL_FRAME, isolate, nexus) { 280 DCHECK(nexus != NULL); 281 } 282 283 void HandleMiss(Handle<Object> function); 284 285 // Code generator routines. 286 static Handle<Code> initialize_stub(Isolate* isolate, int argc, 287 ConvertReceiverMode mode); 288 static Handle<Code> initialize_stub_in_optimized_code( 289 Isolate* isolate, int argc, ConvertReceiverMode mode); 290 291 static void Clear(Isolate* isolate, Code* host, CallICNexus* nexus); 292 }; 293 294 295 class LoadIC : public IC { 296 public: ComputeExtraICState(TypeofMode typeof_mode,LanguageMode language_mode)297 static ExtraICState ComputeExtraICState(TypeofMode typeof_mode, 298 LanguageMode language_mode) { 299 return LoadICState(typeof_mode, language_mode).GetExtraICState(); 300 } 301 typeof_mode()302 TypeofMode typeof_mode() const { 303 return LoadICState::GetTypeofMode(extra_ic_state()); 304 } 305 language_mode()306 LanguageMode language_mode() const { 307 return LoadICState::GetLanguageMode(extra_ic_state()); 308 } 309 310 LoadIC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus = NULL) IC(depth,isolate,nexus)311 : IC(depth, isolate, nexus) { 312 DCHECK(nexus != NULL); 313 DCHECK(IsLoadStub()); 314 } 315 ShouldThrowReferenceError(Handle<Object> receiver)316 bool ShouldThrowReferenceError(Handle<Object> receiver) { 317 return receiver->IsJSGlobalObject() && typeof_mode() == NOT_INSIDE_TYPEOF; 318 } 319 320 // Code generator routines. 321 GenerateInitialize(MacroAssembler * masm)322 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); } 323 static void GenerateMiss(MacroAssembler* masm); 324 static void GenerateRuntimeGetProperty(MacroAssembler* masm, 325 LanguageMode language_mode); 326 static void GenerateNormal(MacroAssembler* masm, LanguageMode language_mode); 327 328 static Handle<Code> initialize_stub(Isolate* isolate, 329 ExtraICState extra_state); 330 static Handle<Code> initialize_stub_in_optimized_code( 331 Isolate* isolate, ExtraICState extra_state, State initialization_state); 332 333 MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Object> object, 334 Handle<Name> name); 335 336 static void Clear(Isolate* isolate, Code* host, LoadICNexus* nexus); 337 338 protected: 339 inline void set_target(Code* code); 340 slow_stub()341 Handle<Code> slow_stub() const { 342 if (kind() == Code::LOAD_IC) { 343 return is_strong(language_mode()) 344 ? isolate()->builtins()->LoadIC_Slow_Strong() 345 : isolate()->builtins()->LoadIC_Slow(); 346 } else { 347 DCHECK_EQ(Code::KEYED_LOAD_IC, kind()); 348 return is_strong(language_mode()) 349 ? isolate()->builtins()->KeyedLoadIC_Slow_Strong() 350 : isolate()->builtins()->KeyedLoadIC_Slow(); 351 } 352 } 353 354 Handle<Code> megamorphic_stub() override; 355 356 // Update the inline cache and the global stub cache based on the 357 // lookup result. 358 void UpdateCaches(LookupIterator* lookup); 359 360 Handle<Code> CompileHandler(LookupIterator* lookup, Handle<Object> unused, 361 CacheHolderFlag cache_holder) override; 362 363 private: 364 Handle<Code> SimpleFieldLoad(FieldIndex index); 365 366 static void Clear(Isolate* isolate, Address address, Code* target, 367 Address constant_pool); 368 369 friend class IC; 370 }; 371 372 373 class KeyedLoadIC : public LoadIC { 374 public: 375 // ExtraICState bits (building on IC) 376 class IcCheckTypeField 377 : public BitField<IcCheckType, LoadICState::kNextBitFieldOffset, 1> {}; 378 ComputeExtraICState(TypeofMode typeof_mode,LanguageMode language_mode,IcCheckType key_type)379 static ExtraICState ComputeExtraICState(TypeofMode typeof_mode, 380 LanguageMode language_mode, 381 IcCheckType key_type) { 382 return LoadICState(typeof_mode, language_mode).GetExtraICState() | 383 IcCheckTypeField::encode(key_type); 384 } 385 GetKeyType(ExtraICState extra_state)386 static IcCheckType GetKeyType(ExtraICState extra_state) { 387 return IcCheckTypeField::decode(extra_state); 388 } 389 390 KeyedLoadIC(FrameDepth depth, Isolate* isolate, 391 KeyedLoadICNexus* nexus = NULL) LoadIC(depth,isolate,nexus)392 : LoadIC(depth, isolate, nexus) { 393 DCHECK(nexus != NULL); 394 DCHECK(target()->is_keyed_load_stub()); 395 } 396 397 MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Object> object, 398 Handle<Object> key); 399 400 // Code generator routines. 401 static void GenerateMiss(MacroAssembler* masm); 402 static void GenerateRuntimeGetProperty(MacroAssembler* masm, 403 LanguageMode language_mode); GenerateInitialize(MacroAssembler * masm)404 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); } 405 static void GenerateMegamorphic(MacroAssembler* masm, 406 LanguageMode language_mode); 407 408 // Bit mask to be tested against bit field for the cases when 409 // generic stub should go into slow case. 410 // Access check is necessary explicitly since generic stub does not perform 411 // map checks. 412 static const int kSlowCaseBitFieldMask = 413 (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor); 414 415 static Handle<Code> initialize_stub(Isolate* isolate, 416 ExtraICState extra_state); 417 static Handle<Code> initialize_stub_in_optimized_code( 418 Isolate* isolate, State initialization_state, ExtraICState extra_state); 419 static Handle<Code> ChooseMegamorphicStub(Isolate* isolate, 420 ExtraICState extra_state); 421 422 static void Clear(Isolate* isolate, Code* host, KeyedLoadICNexus* nexus); 423 424 protected: 425 // receiver is HeapObject because it could be a String or a JSObject 426 Handle<Code> LoadElementStub(Handle<HeapObject> receiver); 427 428 private: 429 static void Clear(Isolate* isolate, Address address, Code* target, 430 Address constant_pool); 431 432 friend class IC; 433 }; 434 435 436 class StoreIC : public IC { 437 public: ComputeExtraICState(LanguageMode flag)438 static ExtraICState ComputeExtraICState(LanguageMode flag) { 439 return StoreICState(flag).GetExtraICState(); 440 } 441 442 StoreIC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus = NULL) IC(depth,isolate,nexus)443 : IC(depth, isolate, nexus) { 444 DCHECK(IsStoreStub()); 445 } 446 language_mode()447 LanguageMode language_mode() const { 448 return StoreICState::GetLanguageMode(extra_ic_state()); 449 } 450 451 // Code generators for stub routines. Only called once at startup. 452 static void GenerateSlow(MacroAssembler* masm); GenerateInitialize(MacroAssembler * masm)453 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); } GeneratePreMonomorphic(MacroAssembler * masm)454 static void GeneratePreMonomorphic(MacroAssembler* masm) { 455 GenerateMiss(masm); 456 } 457 static void GenerateMiss(MacroAssembler* masm); 458 static void GenerateMegamorphic(MacroAssembler* masm); 459 static void GenerateNormal(MacroAssembler* masm); 460 static void GenerateRuntimeSetProperty(MacroAssembler* masm, 461 LanguageMode language_mode); 462 463 static Handle<Code> initialize_stub(Isolate* isolate, 464 LanguageMode language_mode, 465 State initialization_state); 466 static Handle<Code> initialize_stub_in_optimized_code( 467 Isolate* isolate, LanguageMode language_mode, State initialization_state); 468 469 MUST_USE_RESULT MaybeHandle<Object> Store( 470 Handle<Object> object, Handle<Name> name, Handle<Object> value, 471 JSReceiver::StoreFromKeyed store_mode = 472 JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED); 473 474 bool LookupForWrite(LookupIterator* it, Handle<Object> value, 475 JSReceiver::StoreFromKeyed store_mode); 476 477 static void Clear(Isolate* isolate, Code* host, StoreICNexus* nexus); 478 479 protected: 480 // Stub accessors. 481 Handle<Code> megamorphic_stub() override; 482 Handle<Code> slow_stub() const; 483 pre_monomorphic_stub()484 virtual Handle<Code> pre_monomorphic_stub() const { 485 return pre_monomorphic_stub(isolate(), language_mode()); 486 } 487 488 static Handle<Code> pre_monomorphic_stub(Isolate* isolate, 489 LanguageMode language_mode); 490 491 // Update the inline cache and the global stub cache based on the 492 // lookup result. 493 void UpdateCaches(LookupIterator* lookup, Handle<Object> value, 494 JSReceiver::StoreFromKeyed store_mode); 495 Handle<Code> CompileHandler(LookupIterator* lookup, Handle<Object> value, 496 CacheHolderFlag cache_holder) override; 497 498 private: 499 inline void set_target(Code* code); 500 501 static void Clear(Isolate* isolate, Address address, Code* target, 502 Address constant_pool); 503 504 friend class IC; 505 }; 506 507 508 enum KeyedStoreCheckMap { kDontCheckMap, kCheckMap }; 509 510 511 enum KeyedStoreIncrementLength { kDontIncrementLength, kIncrementLength }; 512 513 514 class KeyedStoreIC : public StoreIC { 515 public: 516 // ExtraICState bits (building on IC) 517 // ExtraICState bits 518 // When more language modes are added, these BitFields need to move too. 519 STATIC_ASSERT(i::LANGUAGE_END == 3); 520 class ExtraICStateKeyedAccessStoreMode 521 : public BitField<KeyedAccessStoreMode, 3, 3> {}; // NOLINT 522 523 class IcCheckTypeField : public BitField<IcCheckType, 6, 1> {}; 524 ComputeExtraICState(LanguageMode flag,KeyedAccessStoreMode mode)525 static ExtraICState ComputeExtraICState(LanguageMode flag, 526 KeyedAccessStoreMode mode) { 527 return StoreICState(flag).GetExtraICState() | 528 ExtraICStateKeyedAccessStoreMode::encode(mode) | 529 IcCheckTypeField::encode(ELEMENT); 530 } 531 GetKeyedAccessStoreMode()532 KeyedAccessStoreMode GetKeyedAccessStoreMode() { 533 return casted_nexus<KeyedStoreICNexus>()->GetKeyedAccessStoreMode(); 534 } 535 536 KeyedStoreIC(FrameDepth depth, Isolate* isolate, 537 KeyedStoreICNexus* nexus = NULL) StoreIC(depth,isolate,nexus)538 : StoreIC(depth, isolate, nexus) { 539 DCHECK(target()->is_keyed_store_stub()); 540 } 541 542 MUST_USE_RESULT MaybeHandle<Object> Store(Handle<Object> object, 543 Handle<Object> name, 544 Handle<Object> value); 545 546 // Code generators for stub routines. Only called once at startup. GenerateInitialize(MacroAssembler * masm)547 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); } GeneratePreMonomorphic(MacroAssembler * masm)548 static void GeneratePreMonomorphic(MacroAssembler* masm) { 549 GenerateMiss(masm); 550 } 551 static void GenerateMiss(MacroAssembler* masm); 552 static void GenerateSlow(MacroAssembler* masm); 553 static void GenerateMegamorphic(MacroAssembler* masm, 554 LanguageMode language_mode); 555 556 static Handle<Code> initialize_stub(Isolate* isolate, 557 LanguageMode language_mode, 558 State initialization_state); 559 560 static Handle<Code> initialize_stub_in_optimized_code( 561 Isolate* isolate, LanguageMode language_mode, State initialization_state); 562 static Handle<Code> ChooseMegamorphicStub(Isolate* isolate, 563 ExtraICState extra_state); 564 565 static void Clear(Isolate* isolate, Code* host, KeyedStoreICNexus* nexus); 566 567 protected: pre_monomorphic_stub()568 virtual Handle<Code> pre_monomorphic_stub() const { 569 return pre_monomorphic_stub(isolate(), language_mode()); 570 } pre_monomorphic_stub(Isolate * isolate,LanguageMode language_mode)571 static Handle<Code> pre_monomorphic_stub(Isolate* isolate, 572 LanguageMode language_mode) { 573 if (is_strict(language_mode)) { 574 return isolate->builtins()->KeyedStoreIC_PreMonomorphic_Strict(); 575 } else { 576 return isolate->builtins()->KeyedStoreIC_PreMonomorphic(); 577 } 578 } 579 580 Handle<Code> StoreElementStub(Handle<Map> receiver_map, 581 KeyedAccessStoreMode store_mode); 582 583 private: 584 inline void set_target(Code* code); 585 586 static void Clear(Isolate* isolate, Address address, Code* target, 587 Address constant_pool); 588 589 Handle<Map> ComputeTransitionedMap(Handle<Map> map, 590 KeyedAccessStoreMode store_mode); 591 592 friend class IC; 593 }; 594 595 596 // Type Recording BinaryOpIC, that records the types of the inputs and outputs. 597 class BinaryOpIC : public IC { 598 public: BinaryOpIC(Isolate * isolate)599 explicit BinaryOpIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) {} 600 601 MaybeHandle<Object> Transition(Handle<AllocationSite> allocation_site, 602 Handle<Object> left, 603 Handle<Object> right) WARN_UNUSED_RESULT; 604 }; 605 606 607 class CompareIC : public IC { 608 public: CompareIC(Isolate * isolate,Token::Value op)609 CompareIC(Isolate* isolate, Token::Value op) 610 : IC(EXTRA_CALL_FRAME, isolate), op_(op) {} 611 612 // Update the inline cache for the given operands. 613 Code* UpdateCaches(Handle<Object> x, Handle<Object> y); 614 615 // Helper function for computing the condition for a compare operation. 616 static Condition ComputeCondition(Token::Value op); 617 618 // Factory method for getting an uninitialized compare stub. 619 static Handle<Code> GetUninitialized(Isolate* isolate, Token::Value op, 620 Strength strength); 621 622 private: 623 static bool HasInlinedSmiCode(Address address); 624 strict()625 bool strict() const { return op_ == Token::EQ_STRICT; } GetCondition()626 Condition GetCondition() const { return ComputeCondition(op_); } 627 628 static Code* GetRawUninitialized(Isolate* isolate, Token::Value op, 629 Strength strength); 630 631 static void Clear(Isolate* isolate, Address address, Code* target, 632 Address constant_pool); 633 634 Token::Value op_; 635 636 friend class IC; 637 }; 638 639 640 class CompareNilIC : public IC { 641 public: CompareNilIC(Isolate * isolate)642 explicit CompareNilIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) {} 643 644 Handle<Object> CompareNil(Handle<Object> object); 645 646 static Handle<Code> GetUninitialized(); 647 648 static void Clear(Address address, Code* target, Address constant_pool); 649 650 static Handle<Object> DoCompareNilSlow(Isolate* isolate, NilValue nil, 651 Handle<Object> object); 652 }; 653 654 655 class ToBooleanIC : public IC { 656 public: ToBooleanIC(Isolate * isolate)657 explicit ToBooleanIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) {} 658 659 Handle<Object> ToBoolean(Handle<Object> object); 660 }; 661 662 663 // Helper for BinaryOpIC and CompareIC. 664 enum InlinedSmiCheck { ENABLE_INLINED_SMI_CHECK, DISABLE_INLINED_SMI_CHECK }; 665 void PatchInlinedSmiCode(Isolate* isolate, Address address, 666 InlinedSmiCheck check); 667 668 } // namespace internal 669 } // namespace v8 670 671 #endif // V8_IC_H_ 672