1 // Copyright 2012 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 #ifndef V8_IC_H_ 29 #define V8_IC_H_ 30 31 #include "macro-assembler.h" 32 #include "type-info.h" 33 34 namespace v8 { 35 namespace internal { 36 37 38 // IC_UTIL_LIST defines all utility functions called from generated 39 // inline caching code. The argument for the macro, ICU, is the function name. 40 #define IC_UTIL_LIST(ICU) \ 41 ICU(LoadIC_Miss) \ 42 ICU(KeyedLoadIC_Miss) \ 43 ICU(KeyedLoadIC_MissForceGeneric) \ 44 ICU(CallIC_Miss) \ 45 ICU(KeyedCallIC_Miss) \ 46 ICU(StoreIC_Miss) \ 47 ICU(StoreIC_ArrayLength) \ 48 ICU(StoreIC_Slow) \ 49 ICU(SharedStoreIC_ExtendStorage) \ 50 ICU(KeyedStoreIC_Miss) \ 51 ICU(KeyedStoreIC_MissForceGeneric) \ 52 ICU(KeyedStoreIC_Slow) \ 53 /* Utilities for IC stubs. */ \ 54 ICU(StoreCallbackProperty) \ 55 ICU(LoadPropertyWithInterceptorOnly) \ 56 ICU(LoadPropertyWithInterceptorForLoad) \ 57 ICU(LoadPropertyWithInterceptorForCall) \ 58 ICU(KeyedLoadPropertyWithInterceptor) \ 59 ICU(StoreInterceptorProperty) \ 60 ICU(BinaryOp_Patch) \ 61 ICU(CompareIC_Miss) \ 62 ICU(CompareNilIC_Miss) \ 63 ICU(Unreachable) \ 64 ICU(ToBooleanIC_Miss) 65 // 66 // IC is the base class for LoadIC, StoreIC, CallIC, KeyedLoadIC, 67 // and KeyedStoreIC. 68 // 69 class IC { 70 public: 71 // The ids for utility called from the generated code. 72 enum UtilityId { 73 #define CONST_NAME(name) k##name, 74 IC_UTIL_LIST(CONST_NAME) 75 #undef CONST_NAME 76 kUtilityCount 77 }; 78 79 // Looks up the address of the named utility. 80 static Address AddressFromUtilityId(UtilityId id); 81 82 // Alias the inline cache state type to make the IC code more readable. 83 typedef InlineCacheState State; 84 85 // The IC code is either invoked with no extra frames on the stack 86 // or with a single extra frame for supporting calls. 87 enum FrameDepth { 88 NO_EXTRA_FRAME = 0, 89 EXTRA_CALL_FRAME = 1 90 }; 91 92 // Construct the IC structure with the given number of extra 93 // JavaScript frames on the stack. 94 IC(FrameDepth depth, Isolate* isolate); 95 virtual ~IC() {} 96 97 // Get the call-site target; used for determining the state. 98 Code* target() const { return GetTargetAtAddress(address()); } 99 inline Address address() const; 100 101 // Compute the current IC state based on the target stub, receiver and name. 102 static State StateFrom(Code* target, Object* receiver, Object* name); 103 104 // Clear the inline cache to initial state. 105 static void Clear(Address address); 106 107 // Computes the reloc info for this IC. This is a fairly expensive 108 // operation as it has to search through the heap to find the code 109 // object that contains this IC site. 110 RelocInfo::Mode ComputeMode(); 111 112 // Returns if this IC is for contextual (no explicit receiver) 113 // access to properties. 114 bool IsUndeclaredGlobal(Handle<Object> receiver) { 115 if (receiver->IsGlobalObject()) { 116 return SlowIsUndeclaredGlobal(); 117 } else { 118 ASSERT(!SlowIsUndeclaredGlobal()); 119 return false; 120 } 121 } 122 123 bool SlowIsUndeclaredGlobal() { 124 return ComputeMode() == RelocInfo::CODE_TARGET_CONTEXT; 125 } 126 127 // Determines which map must be used for keeping the code stub. 128 // These methods should not be called with undefined or null. 129 static inline InlineCacheHolderFlag GetCodeCacheForObject(Object* object, 130 JSObject* holder); 131 static inline InlineCacheHolderFlag GetCodeCacheForObject(JSObject* object, 132 JSObject* holder); 133 static inline JSObject* GetCodeCacheHolder(Isolate* isolate, 134 Object* object, 135 InlineCacheHolderFlag holder); 136 137 protected: 138 Address fp() const { return fp_; } 139 Address pc() const { return *pc_address_; } 140 Isolate* isolate() const { return isolate_; } 141 142 #ifdef ENABLE_DEBUGGER_SUPPORT 143 // Computes the address in the original code when the code running is 144 // containing break points (calls to DebugBreakXXX builtins). 145 Address OriginalCodeAddress() const; 146 #endif 147 148 // Set the call-site target. 149 void set_target(Code* code) { SetTargetAtAddress(address(), code); } 150 151 #ifdef DEBUG 152 char TransitionMarkFromState(IC::State state); 153 154 void TraceIC(const char* type, 155 Handle<Object> name, 156 State old_state, 157 Code* new_target); 158 #endif 159 160 Failure* TypeError(const char* type, 161 Handle<Object> object, 162 Handle<Object> key); 163 Failure* ReferenceError(const char* type, Handle<String> name); 164 165 // Access the target code for the given IC address. 166 static inline Code* GetTargetAtAddress(Address address); 167 static inline void SetTargetAtAddress(Address address, Code* target); 168 static void PostPatching(Address address, Code* target, Code* old_target); 169 170 virtual void UpdateMonomorphicIC(Handle<JSObject> receiver, 171 Handle<Code> handler, 172 Handle<String> name, 173 StrictModeFlag strict_mode) { 174 set_target(*handler); 175 } 176 bool UpdatePolymorphicIC(State state, 177 Handle<JSObject> receiver, 178 Handle<String> name, 179 Handle<Code> code, 180 StrictModeFlag strict_mode); 181 182 virtual Handle<Code> ComputePolymorphicIC(MapHandleList* receiver_maps, 183 CodeHandleList* handlers, 184 int number_of_valid_maps, 185 Handle<Name> name, 186 StrictModeFlag strict_mode) { 187 UNREACHABLE(); 188 return Handle<Code>::null(); 189 }; 190 191 void CopyICToMegamorphicCache(Handle<String> name); 192 bool IsTransitionedMapOfMonomorphicTarget(Map* receiver_map); 193 void PatchCache(State state, 194 StrictModeFlag strict_mode, 195 Handle<JSObject> receiver, 196 Handle<String> name, 197 Handle<Code> code); 198 virtual void UpdateMegamorphicCache(Map* map, Name* name, Code* code); 199 virtual Handle<Code> megamorphic_stub() { 200 UNREACHABLE(); 201 return Handle<Code>::null(); 202 } 203 virtual Handle<Code> megamorphic_stub_strict() { 204 UNREACHABLE(); 205 return Handle<Code>::null(); 206 } 207 virtual Handle<Code> generic_stub() const { 208 UNREACHABLE(); 209 return Handle<Code>::null(); 210 } 211 virtual Handle<Code> generic_stub_strict() const { 212 UNREACHABLE(); 213 return Handle<Code>::null(); 214 } 215 216 private: 217 // Frame pointer for the frame that uses (calls) the IC. 218 Address fp_; 219 220 // All access to the program counter of an IC structure is indirect 221 // to make the code GC safe. This feature is crucial since 222 // GetProperty and SetProperty are called and they in turn might 223 // invoke the garbage collector. 224 Address* pc_address_; 225 226 Isolate* isolate_; 227 228 DISALLOW_IMPLICIT_CONSTRUCTORS(IC); 229 }; 230 231 232 // An IC_Utility encapsulates IC::UtilityId. It exists mainly because you 233 // cannot make forward declarations to an enum. 234 class IC_Utility { 235 public: 236 explicit IC_Utility(IC::UtilityId id) 237 : address_(IC::AddressFromUtilityId(id)), id_(id) {} 238 239 Address address() const { return address_; } 240 241 IC::UtilityId id() const { return id_; } 242 private: 243 Address address_; 244 IC::UtilityId id_; 245 }; 246 247 248 class CallICBase: public IC { 249 public: 250 class Contextual: public BitField<bool, 0, 1> {}; 251 class StringStubState: public BitField<StringStubFeedback, 1, 1> {}; 252 253 // Returns a JSFunction or a Failure. 254 MUST_USE_RESULT MaybeObject* LoadFunction(State state, 255 Code::ExtraICState extra_ic_state, 256 Handle<Object> object, 257 Handle<String> name); 258 259 protected: 260 CallICBase(Code::Kind kind, Isolate* isolate) 261 : IC(EXTRA_CALL_FRAME, isolate), kind_(kind) {} 262 263 bool TryUpdateExtraICState(LookupResult* lookup, 264 Handle<Object> object, 265 Code::ExtraICState* extra_ic_state); 266 267 // Compute a monomorphic stub if possible, otherwise return a null handle. 268 Handle<Code> ComputeMonomorphicStub(LookupResult* lookup, 269 State state, 270 Code::ExtraICState extra_state, 271 Handle<Object> object, 272 Handle<String> name); 273 274 // Update the inline cache and the global stub cache based on the lookup 275 // result. 276 void UpdateCaches(LookupResult* lookup, 277 State state, 278 Code::ExtraICState extra_ic_state, 279 Handle<Object> object, 280 Handle<String> name); 281 282 // Returns a JSFunction if the object can be called as a function, and 283 // patches the stack to be ready for the call. Otherwise, it returns the 284 // undefined value. 285 Handle<Object> TryCallAsFunction(Handle<Object> object); 286 287 void ReceiverToObjectIfRequired(Handle<Object> callee, Handle<Object> object); 288 289 static void Clear(Address address, Code* target); 290 291 // Platform-specific code generation functions used by both call and 292 // keyed call. 293 static void GenerateMiss(MacroAssembler* masm, 294 int argc, 295 IC::UtilityId id, 296 Code::ExtraICState extra_state); 297 298 static void GenerateNormal(MacroAssembler* masm, int argc); 299 300 static void GenerateMonomorphicCacheProbe(MacroAssembler* masm, 301 int argc, 302 Code::Kind kind, 303 Code::ExtraICState extra_state); 304 305 Code::Kind kind_; 306 307 friend class IC; 308 }; 309 310 311 class CallIC: public CallICBase { 312 public: 313 explicit CallIC(Isolate* isolate) : CallICBase(Code::CALL_IC, isolate) { 314 ASSERT(target()->is_call_stub()); 315 } 316 317 // Code generator routines. 318 static void GenerateInitialize(MacroAssembler* masm, 319 int argc, 320 Code::ExtraICState extra_state) { 321 GenerateMiss(masm, argc, extra_state); 322 } 323 324 static void GenerateMiss(MacroAssembler* masm, 325 int argc, 326 Code::ExtraICState extra_state) { 327 CallICBase::GenerateMiss(masm, argc, IC::kCallIC_Miss, extra_state); 328 } 329 330 static void GenerateMegamorphic(MacroAssembler* masm, 331 int argc, 332 Code::ExtraICState extra_ic_state); 333 334 static void GenerateNormal(MacroAssembler* masm, int argc) { 335 CallICBase::GenerateNormal(masm, argc); 336 GenerateMiss(masm, argc, Code::kNoExtraICState); 337 } 338 }; 339 340 341 class KeyedCallIC: public CallICBase { 342 public: 343 explicit KeyedCallIC(Isolate* isolate) 344 : CallICBase(Code::KEYED_CALL_IC, isolate) { 345 ASSERT(target()->is_keyed_call_stub()); 346 } 347 348 MUST_USE_RESULT MaybeObject* LoadFunction(State state, 349 Handle<Object> object, 350 Handle<Object> key); 351 352 // Code generator routines. 353 static void GenerateInitialize(MacroAssembler* masm, int argc) { 354 GenerateMiss(masm, argc); 355 } 356 357 static void GenerateMiss(MacroAssembler* masm, int argc) { 358 CallICBase::GenerateMiss(masm, argc, IC::kKeyedCallIC_Miss, 359 Code::kNoExtraICState); 360 } 361 362 static void GenerateMegamorphic(MacroAssembler* masm, int argc); 363 static void GenerateNormal(MacroAssembler* masm, int argc); 364 static void GenerateNonStrictArguments(MacroAssembler* masm, int argc); 365 }; 366 367 368 class LoadIC: public IC { 369 public: 370 explicit LoadIC(FrameDepth depth, Isolate* isolate) : IC(depth, isolate) { 371 ASSERT(target()->is_load_stub() || target()->is_keyed_load_stub()); 372 } 373 374 // Code generator routines. 375 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); } 376 static void GeneratePreMonomorphic(MacroAssembler* masm) { 377 GenerateMiss(masm); 378 } 379 static void GenerateMiss(MacroAssembler* masm); 380 static void GenerateMegamorphic(MacroAssembler* masm); 381 static void GenerateNormal(MacroAssembler* masm); 382 static void GenerateRuntimeGetProperty(MacroAssembler* masm); 383 384 MUST_USE_RESULT MaybeObject* Load(State state, 385 Handle<Object> object, 386 Handle<String> name); 387 388 protected: 389 virtual Code::Kind kind() const { return Code::LOAD_IC; } 390 391 virtual Handle<Code> generic_stub() const { 392 return isolate()->builtins()->LoadIC_Slow(); 393 } 394 395 virtual Handle<Code> megamorphic_stub() { 396 return isolate()->builtins()->LoadIC_Megamorphic(); 397 } 398 399 // Update the inline cache and the global stub cache based on the 400 // lookup result. 401 void UpdateCaches(LookupResult* lookup, 402 State state, 403 Handle<Object> object, 404 Handle<String> name); 405 406 virtual void UpdateMonomorphicIC(Handle<JSObject> receiver, 407 Handle<Code> handler, 408 Handle<String> name, 409 StrictModeFlag strict_mode); 410 411 virtual Handle<Code> ComputePolymorphicIC(MapHandleList* receiver_maps, 412 CodeHandleList* handlers, 413 int number_of_valid_maps, 414 Handle<Name> name, 415 StrictModeFlag strict_mode); 416 417 virtual Handle<Code> ComputeLoadHandler(LookupResult* lookup, 418 Handle<JSObject> receiver, 419 Handle<String> name); 420 421 private: 422 // Stub accessors. 423 static Handle<Code> initialize_stub() { 424 return Isolate::Current()->builtins()->LoadIC_Initialize(); 425 } 426 virtual Handle<Code> pre_monomorphic_stub() { 427 return isolate()->builtins()->LoadIC_PreMonomorphic(); 428 } 429 430 static void Clear(Address address, Code* target); 431 432 friend class IC; 433 }; 434 435 436 enum ICMissMode { 437 MISS_FORCE_GENERIC, 438 MISS 439 }; 440 441 442 class KeyedLoadIC: public LoadIC { 443 public: 444 explicit KeyedLoadIC(FrameDepth depth, Isolate* isolate) 445 : LoadIC(depth, isolate) { 446 ASSERT(target()->is_keyed_load_stub()); 447 } 448 449 MUST_USE_RESULT MaybeObject* Load(State state, 450 Handle<Object> object, 451 Handle<Object> key, 452 ICMissMode force_generic); 453 454 // Code generator routines. 455 static void GenerateMiss(MacroAssembler* masm, ICMissMode force_generic); 456 static void GenerateRuntimeGetProperty(MacroAssembler* masm); 457 static void GenerateInitialize(MacroAssembler* masm) { 458 GenerateMiss(masm, MISS); 459 } 460 static void GeneratePreMonomorphic(MacroAssembler* masm) { 461 GenerateMiss(masm, MISS); 462 } 463 static void GenerateGeneric(MacroAssembler* masm); 464 static void GenerateString(MacroAssembler* masm); 465 static void GenerateIndexedInterceptor(MacroAssembler* masm); 466 static void GenerateNonStrictArguments(MacroAssembler* masm); 467 468 // Bit mask to be tested against bit field for the cases when 469 // generic stub should go into slow case. 470 // Access check is necessary explicitly since generic stub does not perform 471 // map checks. 472 static const int kSlowCaseBitFieldMask = 473 (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor); 474 475 protected: 476 virtual Code::Kind kind() const { return Code::KEYED_LOAD_IC; } 477 478 Handle<Code> LoadElementStub(Handle<JSObject> receiver); 479 480 virtual Handle<Code> megamorphic_stub() { 481 return isolate()->builtins()->KeyedLoadIC_Generic(); 482 } 483 virtual Handle<Code> generic_stub() const { 484 return isolate()->builtins()->KeyedLoadIC_Generic(); 485 } 486 487 // Update the inline cache. 488 virtual void UpdateMonomorphicIC(Handle<JSObject> receiver, 489 Handle<Code> handler, 490 Handle<String> name, 491 StrictModeFlag strict_mode); 492 virtual Handle<Code> ComputeLoadHandler(LookupResult* lookup, 493 Handle<JSObject> receiver, 494 Handle<String> name); 495 virtual void UpdateMegamorphicCache(Map* map, Name* name, Code* code) { } 496 497 private: 498 // Stub accessors. 499 static Handle<Code> initialize_stub() { 500 return Isolate::Current()->builtins()->KeyedLoadIC_Initialize(); 501 } 502 virtual Handle<Code> pre_monomorphic_stub() { 503 return isolate()->builtins()->KeyedLoadIC_PreMonomorphic(); 504 } 505 Handle<Code> indexed_interceptor_stub() { 506 return isolate()->builtins()->KeyedLoadIC_IndexedInterceptor(); 507 } 508 Handle<Code> non_strict_arguments_stub() { 509 return isolate()->builtins()->KeyedLoadIC_NonStrictArguments(); 510 } 511 Handle<Code> string_stub() { 512 return isolate()->builtins()->KeyedLoadIC_String(); 513 } 514 515 static void Clear(Address address, Code* target); 516 517 friend class IC; 518 }; 519 520 521 class StoreIC: public IC { 522 public: 523 StoreIC(FrameDepth depth, Isolate* isolate) : IC(depth, isolate) { 524 ASSERT(target()->is_store_stub() || target()->is_keyed_store_stub()); 525 } 526 527 // Code generators for stub routines. Only called once at startup. 528 static void GenerateSlow(MacroAssembler* masm); 529 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); } 530 static void GenerateMiss(MacroAssembler* masm); 531 static void GenerateMegamorphic(MacroAssembler* masm, 532 StrictModeFlag strict_mode); 533 static void GenerateNormal(MacroAssembler* masm); 534 static void GenerateRuntimeSetProperty(MacroAssembler* masm, 535 StrictModeFlag strict_mode); 536 537 MUST_USE_RESULT MaybeObject* Store( 538 State state, 539 StrictModeFlag strict_mode, 540 Handle<Object> object, 541 Handle<String> name, 542 Handle<Object> value, 543 JSReceiver::StoreFromKeyed store_mode = 544 JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED); 545 546 protected: 547 virtual Code::Kind kind() const { return Code::STORE_IC; } 548 virtual Handle<Code> megamorphic_stub() { 549 return isolate()->builtins()->StoreIC_Megamorphic(); 550 } 551 // Stub accessors. 552 virtual Handle<Code> megamorphic_stub_strict() { 553 return isolate()->builtins()->StoreIC_Megamorphic_Strict(); 554 } 555 virtual Handle<Code> generic_stub() const { 556 return isolate()->builtins()->StoreIC_Generic(); 557 } 558 virtual Handle<Code> generic_stub_strict() const { 559 return isolate()->builtins()->StoreIC_Generic_Strict(); 560 } 561 virtual Handle<Code> global_proxy_stub() { 562 return isolate()->builtins()->StoreIC_GlobalProxy(); 563 } 564 virtual Handle<Code> global_proxy_stub_strict() { 565 return isolate()->builtins()->StoreIC_GlobalProxy_Strict(); 566 } 567 568 virtual void UpdateMonomorphicIC(Handle<JSObject> receiver, 569 Handle<Code> handler, 570 Handle<String> name, 571 StrictModeFlag strict_mode); 572 573 virtual Handle<Code> ComputePolymorphicIC(MapHandleList* receiver_maps, 574 CodeHandleList* handlers, 575 int number_of_valid_maps, 576 Handle<Name> name, 577 StrictModeFlag strict_mode); 578 579 // Update the inline cache and the global stub cache based on the 580 // lookup result. 581 void UpdateCaches(LookupResult* lookup, 582 State state, 583 StrictModeFlag strict_mode, 584 Handle<JSObject> receiver, 585 Handle<String> name, 586 Handle<Object> value); 587 // Compute the code stub for this store; used for rewriting to 588 // monomorphic state and making sure that the code stub is in the 589 // stub cache. 590 virtual Handle<Code> ComputeStoreMonomorphic(LookupResult* lookup, 591 StrictModeFlag strict_mode, 592 Handle<JSObject> receiver, 593 Handle<String> name, 594 Handle<Object> value); 595 596 private: 597 void set_target(Code* code) { 598 // Strict mode must be preserved across IC patching. 599 ASSERT(Code::GetStrictMode(code->extra_ic_state()) == 600 Code::GetStrictMode(target()->extra_ic_state())); 601 IC::set_target(code); 602 } 603 604 static Handle<Code> initialize_stub() { 605 return Isolate::Current()->builtins()->StoreIC_Initialize(); 606 } 607 static Handle<Code> initialize_stub_strict() { 608 return Isolate::Current()->builtins()->StoreIC_Initialize_Strict(); 609 } 610 static void Clear(Address address, Code* target); 611 612 friend class IC; 613 }; 614 615 616 enum KeyedStoreCheckMap { 617 kDontCheckMap, 618 kCheckMap 619 }; 620 621 622 enum KeyedStoreIncrementLength { 623 kDontIncrementLength, 624 kIncrementLength 625 }; 626 627 628 class KeyedStoreIC: public StoreIC { 629 public: 630 KeyedStoreIC(FrameDepth depth, Isolate* isolate) 631 : StoreIC(depth, isolate) { 632 ASSERT(target()->is_keyed_store_stub()); 633 } 634 635 MUST_USE_RESULT MaybeObject* Store(State state, 636 StrictModeFlag strict_mode, 637 Handle<Object> object, 638 Handle<Object> name, 639 Handle<Object> value, 640 ICMissMode force_generic); 641 642 // Code generators for stub routines. Only called once at startup. 643 static void GenerateInitialize(MacroAssembler* masm) { 644 GenerateMiss(masm, MISS); 645 } 646 static void GenerateMiss(MacroAssembler* masm, ICMissMode force_generic); 647 static void GenerateSlow(MacroAssembler* masm); 648 static void GenerateRuntimeSetProperty(MacroAssembler* masm, 649 StrictModeFlag strict_mode); 650 static void GenerateGeneric(MacroAssembler* masm, StrictModeFlag strict_mode); 651 static void GenerateNonStrictArguments(MacroAssembler* masm); 652 653 protected: 654 virtual Code::Kind kind() const { return Code::KEYED_STORE_IC; } 655 656 virtual Handle<Code> ComputeStoreMonomorphic(LookupResult* lookup, 657 StrictModeFlag strict_mode, 658 Handle<JSObject> receiver, 659 Handle<String> name, 660 Handle<Object> value); 661 virtual void UpdateMegamorphicCache(Map* map, Name* name, Code* code) { } 662 663 virtual Handle<Code> megamorphic_stub() { 664 return isolate()->builtins()->KeyedStoreIC_Generic(); 665 } 666 virtual Handle<Code> megamorphic_stub_strict() { 667 return isolate()->builtins()->KeyedStoreIC_Generic_Strict(); 668 } 669 670 Handle<Code> StoreElementStub(Handle<JSObject> receiver, 671 KeyedAccessStoreMode store_mode, 672 StrictModeFlag strict_mode); 673 674 virtual void UpdateMonomorphicIC(Handle<JSObject> receiver, 675 Handle<Code> handler, 676 Handle<String> name, 677 StrictModeFlag strict_mode); 678 679 private: 680 void set_target(Code* code) { 681 // Strict mode must be preserved across IC patching. 682 ASSERT(Code::GetStrictMode(code->extra_ic_state()) == 683 Code::GetStrictMode(target()->extra_ic_state())); 684 IC::set_target(code); 685 } 686 687 // Stub accessors. 688 static Handle<Code> initialize_stub() { 689 return Isolate::Current()->builtins()->KeyedStoreIC_Initialize(); 690 } 691 static Handle<Code> initialize_stub_strict() { 692 return Isolate::Current()->builtins()->KeyedStoreIC_Initialize_Strict(); 693 } 694 Handle<Code> generic_stub() const { 695 return isolate()->builtins()->KeyedStoreIC_Generic(); 696 } 697 Handle<Code> generic_stub_strict() const { 698 return isolate()->builtins()->KeyedStoreIC_Generic_Strict(); 699 } 700 Handle<Code> non_strict_arguments_stub() { 701 return isolate()->builtins()->KeyedStoreIC_NonStrictArguments(); 702 } 703 704 static void Clear(Address address, Code* target); 705 706 KeyedAccessStoreMode GetStoreMode(Handle<JSObject> receiver, 707 Handle<Object> key, 708 Handle<Object> value); 709 710 Handle<Map> ComputeTransitionedMap(Handle<JSObject> receiver, 711 KeyedAccessStoreMode store_mode); 712 713 friend class IC; 714 }; 715 716 717 // Type Recording BinaryOpIC, that records the types of the inputs and outputs. 718 class BinaryOpIC: public IC { 719 public: 720 enum TypeInfo { 721 UNINITIALIZED, 722 SMI, 723 INT32, 724 NUMBER, 725 ODDBALL, 726 STRING, // Only used for addition operation. 727 GENERIC 728 }; 729 730 static void StubInfoToType(int minor_key, 731 Handle<Type>* left, 732 Handle<Type>* right, 733 Handle<Type>* result, 734 Isolate* isolate); 735 736 explicit BinaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { } 737 738 void patch(Code* code); 739 740 static const char* GetName(TypeInfo type_info); 741 742 static State ToState(TypeInfo type_info); 743 744 private: 745 static Handle<Type> TypeInfoToType(TypeInfo binary_type, Isolate* isolate); 746 }; 747 748 749 class CompareIC: public IC { 750 public: 751 // The type/state lattice is defined by the following inequations: 752 // UNINITIALIZED < ... 753 // ... < GENERIC 754 // SMI < NUMBER 755 // INTERNALIZED_STRING < STRING 756 // KNOWN_OBJECT < OBJECT 757 enum State { 758 UNINITIALIZED, 759 SMI, 760 NUMBER, 761 STRING, 762 INTERNALIZED_STRING, 763 UNIQUE_NAME, // Symbol or InternalizedString 764 OBJECT, // JSObject 765 KNOWN_OBJECT, // JSObject with specific map (faster check) 766 GENERIC 767 }; 768 769 static State NewInputState(State old_state, Handle<Object> value); 770 771 static Handle<Type> StateToType(Isolate* isolate, 772 State state, 773 Handle<Map> map = Handle<Map>()); 774 775 static void StubInfoToType(int stub_minor_key, 776 Handle<Type>* left_type, 777 Handle<Type>* right_type, 778 Handle<Type>* overall_type, 779 Handle<Map> map, 780 Isolate* isolate); 781 782 CompareIC(Isolate* isolate, Token::Value op) 783 : IC(EXTRA_CALL_FRAME, isolate), op_(op) { } 784 785 // Update the inline cache for the given operands. 786 void UpdateCaches(Handle<Object> x, Handle<Object> y); 787 788 789 // Factory method for getting an uninitialized compare stub. 790 static Handle<Code> GetUninitialized(Isolate* isolate, Token::Value op); 791 792 // Helper function for computing the condition for a compare operation. 793 static Condition ComputeCondition(Token::Value op); 794 795 static const char* GetStateName(State state); 796 797 private: 798 static bool HasInlinedSmiCode(Address address); 799 800 State TargetState(State old_state, 801 State old_left, 802 State old_right, 803 bool has_inlined_smi_code, 804 Handle<Object> x, 805 Handle<Object> y); 806 807 bool strict() const { return op_ == Token::EQ_STRICT; } 808 Condition GetCondition() const { return ComputeCondition(op_); } 809 810 static Code* GetRawUninitialized(Token::Value op); 811 812 static void Clear(Address address, Code* target); 813 814 Token::Value op_; 815 816 friend class IC; 817 }; 818 819 820 class CompareNilIC: public IC { 821 public: 822 explicit CompareNilIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) {} 823 824 MUST_USE_RESULT MaybeObject* CompareNil(Handle<Object> object); 825 826 static Handle<Code> GetUninitialized(); 827 828 static void Clear(Address address, Code* target); 829 830 static MUST_USE_RESULT MaybeObject* DoCompareNilSlow(NilValue nil, 831 Handle<Object> object); 832 }; 833 834 835 class ToBooleanIC: public IC { 836 public: 837 explicit ToBooleanIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) { } 838 839 MaybeObject* ToBoolean(Handle<Object> object, Code::ExtraICState state); 840 }; 841 842 843 // Helper for BinaryOpIC and CompareIC. 844 enum InlinedSmiCheck { ENABLE_INLINED_SMI_CHECK, DISABLE_INLINED_SMI_CHECK }; 845 void PatchInlinedSmiCode(Address address, InlinedSmiCheck check); 846 847 DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure); 848 DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure); 849 DECLARE_RUNTIME_FUNCTION(MaybeObject*, UnaryOpIC_Miss); 850 DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure); 851 DECLARE_RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss); 852 DECLARE_RUNTIME_FUNCTION(MaybeObject*, CompareNilIC_Miss); 853 DECLARE_RUNTIME_FUNCTION(MaybeObject*, ToBooleanIC_Miss); 854 855 856 } } // namespace v8::internal 857 858 #endif // V8_IC_H_ 859