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 11 namespace v8 { 12 namespace 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) \ 24 ICU(SharedStoreIC_ExtendStorage) \ 25 ICU(KeyedStoreIC_Miss) \ 26 ICU(KeyedStoreIC_Slow) \ 27 /* Utilities for IC stubs. */ \ 28 ICU(StoreCallbackProperty) \ 29 ICU(LoadPropertyWithInterceptorOnly) \ 30 ICU(LoadPropertyWithInterceptor) \ 31 ICU(LoadElementWithInterceptor) \ 32 ICU(StorePropertyWithInterceptor) \ 33 ICU(CompareIC_Miss) \ 34 ICU(BinaryOpIC_Miss) \ 35 ICU(CompareNilIC_Miss) \ 36 ICU(Unreachable) \ 37 ICU(ToBooleanIC_Miss) 38 // 39 // IC is the base class for LoadIC, StoreIC, KeyedLoadIC, and KeyedStoreIC. 40 // 41 class IC { 42 public: 43 // The ids for utility called from the generated code. 44 enum UtilityId { 45 #define CONST_NAME(name) k##name, 46 IC_UTIL_LIST(CONST_NAME) 47 #undef CONST_NAME 48 kUtilityCount 49 }; 50 51 // Looks up the address of the named utility. 52 static Address AddressFromUtilityId(UtilityId id); 53 54 // Alias the inline cache state type to make the IC code more readable. 55 typedef InlineCacheState State; 56 57 // The IC code is either invoked with no extra frames on the stack 58 // or with a single extra frame for supporting calls. 59 enum FrameDepth { NO_EXTRA_FRAME = 0, EXTRA_CALL_FRAME = 1 }; 60 61 // Construct the IC structure with the given number of extra 62 // JavaScript frames on the stack. 63 IC(FrameDepth depth, Isolate* isolate); ~IC()64 virtual ~IC() {} 65 state()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); MarkPrototypeFailure(Handle<Object> name)73 void MarkPrototypeFailure(Handle<Object> name) { 74 DCHECK(IsNameCompatibleWithPrototypeFailure(name)); 75 state_ = PROTOTYPE_FAILURE; 76 } 77 78 // If the stub contains weak maps then this function adds the stub to 79 // the dependent code array of each weak map. 80 static void RegisterWeakMapDependency(Handle<Code> stub); 81 82 // This function is called when a weak map in the stub is dying, 83 // invalidates the stub by setting maps in it to undefined. 84 static void InvalidateMaps(Code* stub); 85 86 // Clear the inline cache to initial state. 87 static void Clear(Isolate* isolate, Address address, 88 ConstantPoolArray* constant_pool); 89 90 #ifdef DEBUG IsLoadStub()91 bool IsLoadStub() const { 92 return target()->is_load_stub() || target()->is_keyed_load_stub(); 93 } 94 IsStoreStub()95 bool IsStoreStub() const { 96 return target()->is_store_stub() || target()->is_keyed_store_stub(); 97 } 98 IsCallStub()99 bool IsCallStub() const { return target()->is_call_stub(); } 100 #endif 101 102 template <class TypeClass> 103 static JSFunction* GetRootConstructor(TypeClass* type, 104 Context* native_context); 105 static inline Handle<Map> GetHandlerCacheHolder(HeapType* type, 106 bool receiver_is_holder, 107 Isolate* isolate, 108 CacheHolderFlag* flag); 109 static inline Handle<Map> GetICCacheHolder(HeapType* type, Isolate* isolate, 110 CacheHolderFlag* flag); 111 IsCleared(Code * code)112 static bool IsCleared(Code* code) { 113 InlineCacheState state = code->ic_state(); 114 return state == UNINITIALIZED || state == PREMONOMORPHIC; 115 } 116 117 // Utility functions to convert maps to types and back. There are two special 118 // cases: 119 // - The heap_number_map is used as a marker which includes heap numbers as 120 // well as smis. 121 // - The oddball map is only used for booleans. 122 static Handle<Map> TypeToMap(HeapType* type, Isolate* isolate); 123 template <class T> 124 static typename T::TypeHandle MapToType(Handle<Map> map, 125 typename T::Region* region); 126 127 static Handle<HeapType> CurrentTypeOf(Handle<Object> object, 128 Isolate* isolate); 129 130 protected: 131 // Get the call-site target; used for determining the state. target()132 Handle<Code> target() const { return target_; } 133 fp()134 Address fp() const { return fp_; } pc()135 Address pc() const { return *pc_address_; } isolate()136 Isolate* isolate() const { return isolate_; } 137 138 // Get the shared function info of the caller. 139 SharedFunctionInfo* GetSharedFunctionInfo() const; 140 // Get the code object of the caller. 141 Code* GetCode() const; 142 // Get the original (non-breakpointed) code object of the caller. 143 Code* GetOriginalCode() const; 144 145 // Set the call-site target. 146 inline void set_target(Code* code); is_target_set()147 bool is_target_set() { return target_set_; } 148 149 char TransitionMarkFromState(IC::State state); 150 void TraceIC(const char* type, Handle<Object> name); 151 void TraceIC(const char* type, Handle<Object> name, State old_state, 152 State new_state); 153 154 MaybeHandle<Object> TypeError(const char* type, Handle<Object> object, 155 Handle<Object> key); 156 MaybeHandle<Object> ReferenceError(const char* type, Handle<Name> name); 157 158 // Access the target code for the given IC address. 159 static inline Code* GetTargetAtAddress(Address address, 160 ConstantPoolArray* constant_pool); 161 static inline void SetTargetAtAddress(Address address, Code* target, 162 ConstantPoolArray* constant_pool); 163 static void OnTypeFeedbackChanged(Isolate* isolate, Address address, 164 State old_state, State new_state, 165 bool target_remains_ic_stub); 166 static void PostPatching(Address address, Code* target, Code* old_target); 167 168 // Compute the handler either by compiling or by retrieving a cached version. 169 Handle<Code> ComputeHandler(LookupIterator* lookup, 170 Handle<Object> value = Handle<Code>::null()); CompileHandler(LookupIterator * lookup,Handle<Object> value,CacheHolderFlag cache_holder)171 virtual Handle<Code> CompileHandler(LookupIterator* lookup, 172 Handle<Object> value, 173 CacheHolderFlag cache_holder) { 174 UNREACHABLE(); 175 return Handle<Code>::null(); 176 } 177 178 void UpdateMonomorphicIC(Handle<Code> handler, Handle<Name> name); 179 bool UpdatePolymorphicIC(Handle<Name> name, Handle<Code> code); 180 void UpdateMegamorphicCache(HeapType* type, Name* name, Code* code); 181 182 void CopyICToMegamorphicCache(Handle<Name> name); 183 bool IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map); 184 void PatchCache(Handle<Name> name, Handle<Code> code); kind()185 Code::Kind kind() const { return kind_; } handler_kind()186 Code::Kind handler_kind() const { 187 if (kind_ == Code::KEYED_LOAD_IC) return Code::LOAD_IC; 188 DCHECK(kind_ == Code::LOAD_IC || kind_ == Code::STORE_IC || 189 kind_ == Code::KEYED_STORE_IC); 190 return kind_; 191 } megamorphic_stub()192 virtual Handle<Code> megamorphic_stub() { 193 UNREACHABLE(); 194 return Handle<Code>::null(); 195 } 196 197 bool TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver, 198 Handle<String> name); 199 extra_ic_state()200 ExtraICState extra_ic_state() const { return extra_ic_state_; } set_extra_ic_state(ExtraICState state)201 void set_extra_ic_state(ExtraICState state) { extra_ic_state_ = state; } 202 receiver_type()203 Handle<HeapType> receiver_type() { return receiver_type_; } update_receiver_type(Handle<Object> receiver)204 void update_receiver_type(Handle<Object> receiver) { 205 receiver_type_ = CurrentTypeOf(receiver, isolate_); 206 } 207 TargetMaps(MapHandleList * list)208 void TargetMaps(MapHandleList* list) { 209 FindTargetMaps(); 210 for (int i = 0; i < target_maps_.length(); i++) { 211 list->Add(target_maps_.at(i)); 212 } 213 } 214 TargetTypes(TypeHandleList * list)215 void TargetTypes(TypeHandleList* list) { 216 FindTargetMaps(); 217 for (int i = 0; i < target_maps_.length(); i++) { 218 list->Add(MapToType<HeapType>(target_maps_.at(i), isolate_)); 219 } 220 } 221 FirstTargetMap()222 Map* FirstTargetMap() { 223 FindTargetMaps(); 224 return target_maps_.length() > 0 ? *target_maps_.at(0) : NULL; 225 } 226 227 protected: 228 inline void UpdateTarget(); 229 230 private: 231 inline Code* raw_target() const; 232 inline ConstantPoolArray* constant_pool() const; 233 inline ConstantPoolArray* raw_constant_pool() const; 234 FindTargetMaps()235 void FindTargetMaps() { 236 if (target_maps_set_) return; 237 target_maps_set_ = true; 238 if (state_ == MONOMORPHIC) { 239 Map* map = target_->FindFirstMap(); 240 if (map != NULL) target_maps_.Add(handle(map)); 241 } else if (state_ != UNINITIALIZED && state_ != PREMONOMORPHIC) { 242 target_->FindAllMaps(&target_maps_); 243 } 244 } 245 246 // Frame pointer for the frame that uses (calls) the IC. 247 Address fp_; 248 249 // All access to the program counter of an IC structure is indirect 250 // to make the code GC safe. This feature is crucial since 251 // GetProperty and SetProperty are called and they in turn might 252 // invoke the garbage collector. 253 Address* pc_address_; 254 255 Isolate* isolate_; 256 257 // The constant pool of the code which originally called the IC (which might 258 // be for the breakpointed copy of the original code). 259 Handle<ConstantPoolArray> raw_constant_pool_; 260 261 // The original code target that missed. 262 Handle<Code> target_; 263 bool target_set_; 264 State state_; 265 Code::Kind kind_; 266 Handle<HeapType> receiver_type_; 267 MaybeHandle<Code> maybe_handler_; 268 269 ExtraICState extra_ic_state_; 270 MapHandleList target_maps_; 271 bool target_maps_set_; 272 273 DISALLOW_IMPLICIT_CONSTRUCTORS(IC); 274 }; 275 276 277 // An IC_Utility encapsulates IC::UtilityId. It exists mainly because you 278 // cannot make forward declarations to an enum. 279 class IC_Utility { 280 public: IC_Utility(IC::UtilityId id)281 explicit IC_Utility(IC::UtilityId id) 282 : address_(IC::AddressFromUtilityId(id)), id_(id) {} 283 address()284 Address address() const { return address_; } 285 id()286 IC::UtilityId id() const { return id_; } 287 288 private: 289 Address address_; 290 IC::UtilityId id_; 291 }; 292 293 294 class CallIC : public IC { 295 public: CallIC(Isolate * isolate)296 explicit CallIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) {} 297 298 void PatchMegamorphic(Handle<Object> function, 299 Handle<TypeFeedbackVector> vector, Handle<Smi> slot); 300 301 void HandleMiss(Handle<Object> receiver, Handle<Object> function, 302 Handle<TypeFeedbackVector> vector, Handle<Smi> slot); 303 304 // Returns true if a custom handler was installed. 305 bool DoCustomHandler(Handle<Object> receiver, Handle<Object> function, 306 Handle<TypeFeedbackVector> vector, Handle<Smi> slot, 307 const CallICState& state); 308 309 // Code generator routines. 310 static Handle<Code> initialize_stub(Isolate* isolate, int argc, 311 CallICState::CallType call_type); 312 313 static void Clear(Isolate* isolate, Address address, Code* target, 314 ConstantPoolArray* constant_pool); 315 316 private: 317 inline IC::State FeedbackToState(Handle<TypeFeedbackVector> vector, 318 Handle<Smi> slot) const; 319 }; 320 321 322 class LoadIC : public IC { 323 public: ComputeExtraICState(ContextualMode contextual_mode)324 static ExtraICState ComputeExtraICState(ContextualMode contextual_mode) { 325 return LoadICState(contextual_mode).GetExtraICState(); 326 } 327 contextual_mode()328 ContextualMode contextual_mode() const { 329 return LoadICState::GetContextualMode(extra_ic_state()); 330 } 331 LoadIC(FrameDepth depth,Isolate * isolate)332 explicit LoadIC(FrameDepth depth, Isolate* isolate) : IC(depth, isolate) { 333 DCHECK(IsLoadStub()); 334 } 335 336 // Returns if this IC is for contextual (no explicit receiver) 337 // access to properties. IsUndeclaredGlobal(Handle<Object> receiver)338 bool IsUndeclaredGlobal(Handle<Object> receiver) { 339 if (receiver->IsGlobalObject()) { 340 return contextual_mode() == CONTEXTUAL; 341 } else { 342 DCHECK(contextual_mode() != CONTEXTUAL); 343 return false; 344 } 345 } 346 347 // Code generator routines. GenerateInitialize(MacroAssembler * masm)348 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); } GeneratePreMonomorphic(MacroAssembler * masm)349 static void GeneratePreMonomorphic(MacroAssembler* masm) { 350 GenerateMiss(masm); 351 } 352 static void GenerateMiss(MacroAssembler* masm); 353 static void GenerateNormal(MacroAssembler* masm); 354 static void GenerateRuntimeGetProperty(MacroAssembler* masm); 355 356 static Handle<Code> initialize_stub(Isolate* isolate, 357 ExtraICState extra_state); 358 359 MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Object> object, 360 Handle<Name> name); 361 362 protected: 363 inline void set_target(Code* code); 364 slow_stub()365 Handle<Code> slow_stub() const { 366 if (kind() == Code::LOAD_IC) { 367 return isolate()->builtins()->LoadIC_Slow(); 368 } else { 369 DCHECK_EQ(Code::KEYED_LOAD_IC, kind()); 370 return isolate()->builtins()->KeyedLoadIC_Slow(); 371 } 372 } 373 374 virtual Handle<Code> megamorphic_stub() OVERRIDE; 375 376 // Update the inline cache and the global stub cache based on the 377 // lookup result. 378 void UpdateCaches(LookupIterator* lookup); 379 380 virtual Handle<Code> CompileHandler(LookupIterator* lookup, 381 Handle<Object> unused, 382 CacheHolderFlag cache_holder); 383 384 private: 385 virtual Handle<Code> pre_monomorphic_stub() const; 386 static Handle<Code> pre_monomorphic_stub(Isolate* isolate, 387 ExtraICState extra_state); 388 389 Handle<Code> SimpleFieldLoad(FieldIndex index); 390 391 static void Clear(Isolate* isolate, Address address, Code* target, 392 ConstantPoolArray* constant_pool); 393 394 friend class IC; 395 }; 396 397 398 class KeyedLoadIC : public LoadIC { 399 public: KeyedLoadIC(FrameDepth depth,Isolate * isolate)400 explicit KeyedLoadIC(FrameDepth depth, Isolate* isolate) 401 : LoadIC(depth, isolate) { 402 DCHECK(target()->is_keyed_load_stub()); 403 } 404 405 MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Object> object, 406 Handle<Object> key); 407 408 // Code generator routines. 409 static void GenerateMiss(MacroAssembler* masm); 410 static void GenerateRuntimeGetProperty(MacroAssembler* masm); GenerateInitialize(MacroAssembler * masm)411 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); } GeneratePreMonomorphic(MacroAssembler * masm)412 static void GeneratePreMonomorphic(MacroAssembler* masm) { 413 GenerateMiss(masm); 414 } 415 static void GenerateGeneric(MacroAssembler* masm); 416 static void GenerateString(MacroAssembler* masm); 417 418 // Bit mask to be tested against bit field for the cases when 419 // generic stub should go into slow case. 420 // Access check is necessary explicitly since generic stub does not perform 421 // map checks. 422 static const int kSlowCaseBitFieldMask = 423 (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor); 424 425 static Handle<Code> generic_stub(Isolate* isolate); 426 static Handle<Code> pre_monomorphic_stub(Isolate* isolate); 427 428 protected: 429 Handle<Code> LoadElementStub(Handle<JSObject> receiver); pre_monomorphic_stub()430 virtual Handle<Code> pre_monomorphic_stub() const { 431 return pre_monomorphic_stub(isolate()); 432 } 433 434 private: generic_stub()435 Handle<Code> generic_stub() const { return generic_stub(isolate()); } string_stub()436 Handle<Code> string_stub() { 437 return isolate()->builtins()->KeyedLoadIC_String(); 438 } 439 440 static void Clear(Isolate* isolate, Address address, Code* target, 441 ConstantPoolArray* constant_pool); 442 443 friend class IC; 444 }; 445 446 447 class StoreIC : public IC { 448 public: 449 class StrictModeState : public BitField<StrictMode, 1, 1> {}; ComputeExtraICState(StrictMode flag)450 static ExtraICState ComputeExtraICState(StrictMode flag) { 451 return StrictModeState::encode(flag); 452 } GetStrictMode(ExtraICState state)453 static StrictMode GetStrictMode(ExtraICState state) { 454 return StrictModeState::decode(state); 455 } 456 457 // For convenience, a statically declared encoding of strict mode extra 458 // IC state. 459 static const ExtraICState kStrictModeState = 1 << StrictModeState::kShift; 460 StoreIC(FrameDepth depth,Isolate * isolate)461 StoreIC(FrameDepth depth, Isolate* isolate) : IC(depth, isolate) { 462 DCHECK(IsStoreStub()); 463 } 464 strict_mode()465 StrictMode strict_mode() const { 466 return StrictModeState::decode(extra_ic_state()); 467 } 468 469 // Code generators for stub routines. Only called once at startup. 470 static void GenerateSlow(MacroAssembler* masm); GenerateInitialize(MacroAssembler * masm)471 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); } GeneratePreMonomorphic(MacroAssembler * masm)472 static void GeneratePreMonomorphic(MacroAssembler* masm) { 473 GenerateMiss(masm); 474 } 475 static void GenerateMiss(MacroAssembler* masm); 476 static void GenerateMegamorphic(MacroAssembler* masm); 477 static void GenerateNormal(MacroAssembler* masm); 478 static void GenerateRuntimeSetProperty(MacroAssembler* masm, 479 StrictMode strict_mode); 480 481 static Handle<Code> initialize_stub(Isolate* isolate, StrictMode strict_mode); 482 483 MUST_USE_RESULT MaybeHandle<Object> Store( 484 Handle<Object> object, Handle<Name> name, Handle<Object> value, 485 JSReceiver::StoreFromKeyed store_mode = 486 JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED); 487 488 bool LookupForWrite(LookupIterator* it, Handle<Object> value, 489 JSReceiver::StoreFromKeyed store_mode); 490 491 protected: 492 virtual Handle<Code> megamorphic_stub() OVERRIDE; 493 494 // Stub accessors. 495 Handle<Code> generic_stub() const; 496 497 Handle<Code> slow_stub() const; 498 pre_monomorphic_stub()499 virtual Handle<Code> pre_monomorphic_stub() const { 500 return pre_monomorphic_stub(isolate(), strict_mode()); 501 } 502 503 static Handle<Code> pre_monomorphic_stub(Isolate* isolate, 504 StrictMode strict_mode); 505 506 // Update the inline cache and the global stub cache based on the 507 // lookup result. 508 void UpdateCaches(LookupIterator* lookup, Handle<Object> value, 509 JSReceiver::StoreFromKeyed store_mode); 510 virtual Handle<Code> CompileHandler(LookupIterator* lookup, 511 Handle<Object> value, 512 CacheHolderFlag cache_holder); 513 514 private: 515 inline void set_target(Code* code); 516 517 static void Clear(Isolate* isolate, Address address, Code* target, 518 ConstantPoolArray* constant_pool); 519 520 friend class IC; 521 }; 522 523 524 enum KeyedStoreCheckMap { kDontCheckMap, kCheckMap }; 525 526 527 enum KeyedStoreIncrementLength { kDontIncrementLength, kIncrementLength }; 528 529 530 class KeyedStoreIC : public StoreIC { 531 public: 532 // ExtraICState bits (building on IC) 533 // ExtraICState bits 534 class ExtraICStateKeyedAccessStoreMode 535 : public BitField<KeyedAccessStoreMode, 2, 4> {}; // NOLINT 536 ComputeExtraICState(StrictMode flag,KeyedAccessStoreMode mode)537 static ExtraICState ComputeExtraICState(StrictMode flag, 538 KeyedAccessStoreMode mode) { 539 return StrictModeState::encode(flag) | 540 ExtraICStateKeyedAccessStoreMode::encode(mode); 541 } 542 GetKeyedAccessStoreMode(ExtraICState extra_state)543 static KeyedAccessStoreMode GetKeyedAccessStoreMode( 544 ExtraICState extra_state) { 545 return ExtraICStateKeyedAccessStoreMode::decode(extra_state); 546 } 547 KeyedStoreIC(FrameDepth depth,Isolate * isolate)548 KeyedStoreIC(FrameDepth depth, Isolate* isolate) : StoreIC(depth, isolate) { 549 DCHECK(target()->is_keyed_store_stub()); 550 } 551 552 MUST_USE_RESULT MaybeHandle<Object> Store(Handle<Object> object, 553 Handle<Object> name, 554 Handle<Object> value); 555 556 // Code generators for stub routines. Only called once at startup. GenerateInitialize(MacroAssembler * masm)557 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); } GeneratePreMonomorphic(MacroAssembler * masm)558 static void GeneratePreMonomorphic(MacroAssembler* masm) { 559 GenerateMiss(masm); 560 } 561 static void GenerateMiss(MacroAssembler* masm); 562 static void GenerateSlow(MacroAssembler* masm); 563 static void GenerateGeneric(MacroAssembler* masm, StrictMode strict_mode); 564 static void GenerateSloppyArguments(MacroAssembler* masm); 565 566 protected: pre_monomorphic_stub()567 virtual Handle<Code> pre_monomorphic_stub() const { 568 return pre_monomorphic_stub(isolate(), strict_mode()); 569 } pre_monomorphic_stub(Isolate * isolate,StrictMode strict_mode)570 static Handle<Code> pre_monomorphic_stub(Isolate* isolate, 571 StrictMode strict_mode) { 572 if (strict_mode == STRICT) { 573 return isolate->builtins()->KeyedStoreIC_PreMonomorphic_Strict(); 574 } else { 575 return isolate->builtins()->KeyedStoreIC_PreMonomorphic(); 576 } 577 } 578 579 Handle<Code> StoreElementStub(Handle<JSObject> receiver, 580 KeyedAccessStoreMode store_mode); 581 582 private: 583 inline void set_target(Code* code); 584 585 // Stub accessors. sloppy_arguments_stub()586 Handle<Code> sloppy_arguments_stub() { 587 return isolate()->builtins()->KeyedStoreIC_SloppyArguments(); 588 } 589 590 static void Clear(Isolate* isolate, Address address, Code* target, 591 ConstantPoolArray* constant_pool); 592 593 KeyedAccessStoreMode GetStoreMode(Handle<JSObject> receiver, 594 Handle<Object> key, Handle<Object> value); 595 596 Handle<Map> ComputeTransitionedMap(Handle<Map> map, 597 KeyedAccessStoreMode store_mode); 598 599 friend class IC; 600 }; 601 602 603 // Type Recording BinaryOpIC, that records the types of the inputs and outputs. 604 class BinaryOpIC : public IC { 605 public: BinaryOpIC(Isolate * isolate)606 explicit BinaryOpIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) {} 607 608 static Builtins::JavaScript TokenToJSBuiltin(Token::Value op); 609 610 MaybeHandle<Object> Transition(Handle<AllocationSite> allocation_site, 611 Handle<Object> left, 612 Handle<Object> right) WARN_UNUSED_RESULT; 613 }; 614 615 616 class CompareIC : public IC { 617 public: CompareIC(Isolate * isolate,Token::Value op)618 CompareIC(Isolate* isolate, Token::Value op) 619 : IC(EXTRA_CALL_FRAME, isolate), op_(op) {} 620 621 // Update the inline cache for the given operands. 622 Code* UpdateCaches(Handle<Object> x, Handle<Object> y); 623 624 // Helper function for computing the condition for a compare operation. 625 static Condition ComputeCondition(Token::Value op); 626 627 // Factory method for getting an uninitialized compare stub. 628 static Handle<Code> GetUninitialized(Isolate* isolate, Token::Value op); 629 630 private: 631 static bool HasInlinedSmiCode(Address address); 632 strict()633 bool strict() const { return op_ == Token::EQ_STRICT; } GetCondition()634 Condition GetCondition() const { return ComputeCondition(op_); } 635 636 static Code* GetRawUninitialized(Isolate* isolate, Token::Value op); 637 638 static void Clear(Isolate* isolate, Address address, Code* target, 639 ConstantPoolArray* constant_pool); 640 641 Token::Value op_; 642 643 friend class IC; 644 }; 645 646 647 class CompareNilIC : public IC { 648 public: CompareNilIC(Isolate * isolate)649 explicit CompareNilIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) {} 650 651 Handle<Object> CompareNil(Handle<Object> object); 652 653 static Handle<Code> GetUninitialized(); 654 655 static void Clear(Address address, Code* target, 656 ConstantPoolArray* constant_pool); 657 658 static Handle<Object> DoCompareNilSlow(Isolate* isolate, NilValue nil, 659 Handle<Object> object); 660 }; 661 662 663 class ToBooleanIC : public IC { 664 public: ToBooleanIC(Isolate * isolate)665 explicit ToBooleanIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) {} 666 667 Handle<Object> ToBoolean(Handle<Object> object); 668 }; 669 670 671 // Helper for BinaryOpIC and CompareIC. 672 enum InlinedSmiCheck { ENABLE_INLINED_SMI_CHECK, DISABLE_INLINED_SMI_CHECK }; 673 void PatchInlinedSmiCode(Address address, InlinedSmiCheck check); 674 675 DECLARE_RUNTIME_FUNCTION(KeyedLoadIC_MissFromStubFailure); 676 DECLARE_RUNTIME_FUNCTION(KeyedStoreIC_MissFromStubFailure); 677 DECLARE_RUNTIME_FUNCTION(UnaryOpIC_Miss); 678 DECLARE_RUNTIME_FUNCTION(StoreIC_MissFromStubFailure); 679 DECLARE_RUNTIME_FUNCTION(ElementsTransitionAndStoreIC_Miss); 680 DECLARE_RUNTIME_FUNCTION(BinaryOpIC_Miss); 681 DECLARE_RUNTIME_FUNCTION(BinaryOpIC_MissWithAllocationSite); 682 DECLARE_RUNTIME_FUNCTION(CompareNilIC_Miss); 683 DECLARE_RUNTIME_FUNCTION(ToBooleanIC_Miss); 684 DECLARE_RUNTIME_FUNCTION(VectorLoadIC_MissFromStubFailure); 685 DECLARE_RUNTIME_FUNCTION(VectorKeyedLoadIC_MissFromStubFailure); 686 687 // Support functions for callbacks handlers. 688 DECLARE_RUNTIME_FUNCTION(StoreCallbackProperty); 689 690 // Support functions for interceptor handlers. 691 DECLARE_RUNTIME_FUNCTION(LoadPropertyWithInterceptorOnly); 692 DECLARE_RUNTIME_FUNCTION(LoadPropertyWithInterceptor); 693 DECLARE_RUNTIME_FUNCTION(LoadElementWithInterceptor); 694 DECLARE_RUNTIME_FUNCTION(StorePropertyWithInterceptor); 695 } 696 } // namespace v8::internal 697 698 #endif // V8_IC_H_ 699