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

Side by Side Diff: src/ic/ic.cc

Issue 1846963002: Use a dictionary-mode code cache on the map rather than a dual system. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Addressed comment Created 4 years, 8 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
« no previous file with comments | « src/ic/ic.h ('k') | src/ic/ic-compiler.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/ic/ic.h" 5 #include "src/ic/ic.h"
6 6
7 #include "src/accessors.h" 7 #include "src/accessors.h"
8 #include "src/api.h" 8 #include "src/api.h"
9 #include "src/api-arguments.h" 9 #include "src/api-arguments.h"
10 #include "src/arguments.h" 10 #include "src/arguments.h"
(...skipping 20 matching lines...) Expand all
31 namespace internal { 31 namespace internal {
32 32
33 char IC::TransitionMarkFromState(IC::State state) { 33 char IC::TransitionMarkFromState(IC::State state) {
34 switch (state) { 34 switch (state) {
35 case UNINITIALIZED: 35 case UNINITIALIZED:
36 return '0'; 36 return '0';
37 case PREMONOMORPHIC: 37 case PREMONOMORPHIC:
38 return '.'; 38 return '.';
39 case MONOMORPHIC: 39 case MONOMORPHIC:
40 return '1'; 40 return '1';
41 case PROTOTYPE_FAILURE: 41 case RECOMPUTE_HANDLER:
42 return '^'; 42 return '^';
43 case POLYMORPHIC: 43 case POLYMORPHIC:
44 return 'P'; 44 return 'P';
45 case MEGAMORPHIC: 45 case MEGAMORPHIC:
46 return 'N'; 46 return 'N';
47 case GENERIC: 47 case GENERIC:
48 return 'G'; 48 return 'G';
49 49
50 // We never see the debugger states here, because the state is 50 // We never see the debugger states here, because the state is
51 // computed from the original code - not the patched code. Let 51 // computed from the original code - not the patched code. Let
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 } 251 }
252 return; 252 return;
253 case LookupIterator::ACCESSOR: 253 case LookupIterator::ACCESSOR:
254 case LookupIterator::INTEGER_INDEXED_EXOTIC: 254 case LookupIterator::INTEGER_INDEXED_EXOTIC:
255 case LookupIterator::DATA: 255 case LookupIterator::DATA:
256 return; 256 return;
257 } 257 }
258 } 258 }
259 } 259 }
260 260
261 261 bool IC::ShouldRecomputeHandler(Handle<Object> receiver, Handle<String> name) {
262 bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver, 262 if (!RecomputeHandlerForName(name)) return false;
263 Handle<String> name) {
264 if (!IsNameCompatibleWithPrototypeFailure(name)) return false;
265 if (UseVector()) { 263 if (UseVector()) {
266 maybe_handler_ = nexus()->FindHandlerForMap(receiver_map()); 264 maybe_handler_ = nexus()->FindHandlerForMap(receiver_map());
267 } else { 265 } else {
268 maybe_handler_ = target()->FindHandlerForMap(*receiver_map()); 266 maybe_handler_ = target()->FindHandlerForMap(*receiver_map());
269 } 267 }
270 268
271 // The current map wasn't handled yet. There's no reason to stay monomorphic, 269 // The current map wasn't handled yet. There's no reason to stay monomorphic,
272 // *unless* we're moving from a deprecated map to its replacement, or 270 // *unless* we're moving from a deprecated map to its replacement, or
273 // to a more general elements kind. 271 // to a more general elements kind.
274 // TODO(verwaest): Check if the current map is actually what the old map 272 // TODO(verwaest): Check if the current map is actually what the old map
275 // would transition to. 273 // would transition to.
276 if (maybe_handler_.is_null()) { 274 if (maybe_handler_.is_null()) {
277 if (!receiver_map()->IsJSObjectMap()) return false; 275 if (!receiver_map()->IsJSObjectMap()) return false;
278 Map* first_map = FirstTargetMap(); 276 Map* first_map = FirstTargetMap();
279 if (first_map == NULL) return false; 277 if (first_map == NULL) return false;
280 Handle<Map> old_map(first_map); 278 Handle<Map> old_map(first_map);
281 if (old_map->is_deprecated()) return true; 279 if (old_map->is_deprecated()) return true;
282 return IsMoreGeneralElementsKindTransition(old_map->elements_kind(), 280 return IsMoreGeneralElementsKindTransition(old_map->elements_kind(),
283 receiver_map()->elements_kind()); 281 receiver_map()->elements_kind());
284 } 282 }
285 283
286 CacheHolderFlag flag;
287 Handle<Map> ic_holder_map(GetICCacheHolder(receiver_map(), isolate(), &flag));
288
289 DCHECK(flag != kCacheOnReceiver || receiver->IsJSObject());
290 DCHECK(flag != kCacheOnPrototype || !receiver->IsJSReceiver());
291 DCHECK(flag != kCacheOnPrototypeReceiverIsDictionary);
292
293 if (state() == MONOMORPHIC) {
294 int index = ic_holder_map->IndexInCodeCache(*name, *target());
295 if (index >= 0) {
296 ic_holder_map->RemoveFromCodeCache(*name, *target(), index);
297 }
298 }
299
300 if (receiver->IsJSGlobalObject()) { 284 if (receiver->IsJSGlobalObject()) {
301 Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(receiver); 285 Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(receiver);
302 LookupIterator it(global, name, LookupIterator::OWN_SKIP_INTERCEPTOR); 286 LookupIterator it(global, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
303 if (it.state() == LookupIterator::ACCESS_CHECK) return false; 287 if (it.state() == LookupIterator::ACCESS_CHECK) return false;
304 if (!it.IsFound()) return false; 288 if (!it.IsFound()) return false;
305 return it.property_details().cell_type() == PropertyCellType::kConstant; 289 return it.property_details().cell_type() == PropertyCellType::kConstant;
306 } 290 }
307 291
308 return true; 292 return true;
309 } 293 }
310 294
311 295 bool IC::RecomputeHandlerForName(Handle<Object> name) {
312 bool IC::IsNameCompatibleWithPrototypeFailure(Handle<Object> name) {
313 if (target()->is_keyed_stub()) { 296 if (target()->is_keyed_stub()) {
314 // Determine whether the failure is due to a name failure. 297 // Determine whether the failure is due to a name failure.
315 if (!name->IsName()) return false; 298 if (!name->IsName()) return false;
316 Name* stub_name = 299 Name* stub_name =
317 UseVector() ? nexus()->FindFirstName() : target()->FindFirstName(); 300 UseVector() ? nexus()->FindFirstName() : target()->FindFirstName();
318 if (*name != stub_name) return false; 301 if (*name != stub_name) return false;
319 } 302 }
320 303
321 return true; 304 return true;
322 } 305 }
323 306
324 307
325 void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) { 308 void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) {
326 update_receiver_map(receiver); 309 update_receiver_map(receiver);
327 if (!name->IsString()) return; 310 if (!name->IsString()) return;
328 if (state() != MONOMORPHIC && state() != POLYMORPHIC) return; 311 if (state() != MONOMORPHIC && state() != POLYMORPHIC) return;
329 if (receiver->IsUndefined() || receiver->IsNull()) return; 312 if (receiver->IsUndefined() || receiver->IsNull()) return;
330 313
331 // Remove the target from the code cache if it became invalid 314 // Remove the target from the code cache if it became invalid
332 // because of changes in the prototype chain to avoid hitting it 315 // because of changes in the prototype chain to avoid hitting it
333 // again. 316 // again.
334 if (TryRemoveInvalidPrototypeDependentStub(receiver, 317 if (ShouldRecomputeHandler(receiver, Handle<String>::cast(name))) {
335 Handle<String>::cast(name))) { 318 MarkRecomputeHandler(name);
336 MarkPrototypeFailure(name);
337 return;
338 } 319 }
339 } 320 }
340 321
341 322
342 MaybeHandle<Object> IC::TypeError(MessageTemplate::Template index, 323 MaybeHandle<Object> IC::TypeError(MessageTemplate::Template index,
343 Handle<Object> object, Handle<Object> key) { 324 Handle<Object> object, Handle<Object> key) {
344 HandleScope scope(isolate()); 325 HandleScope scope(isolate());
345 THROW_NEW_ERROR(isolate(), NewTypeError(index, key, object), Object); 326 THROW_NEW_ERROR(isolate(), NewTypeError(index, key, object), Object);
346 } 327 }
347 328
(...skipping 27 matching lines...) Expand all
375 } 356 }
376 break; 357 break;
377 case MEGAMORPHIC: 358 case MEGAMORPHIC:
378 case GENERIC: 359 case GENERIC:
379 if (new_state == MEGAMORPHIC || new_state == GENERIC) break; 360 if (new_state == MEGAMORPHIC || new_state == GENERIC) break;
380 *generic_delta = -1; 361 *generic_delta = -1;
381 if (new_state == MONOMORPHIC || new_state == POLYMORPHIC) { 362 if (new_state == MONOMORPHIC || new_state == POLYMORPHIC) {
382 *polymorphic_delta = 1; 363 *polymorphic_delta = 1;
383 } 364 }
384 break; 365 break;
385 case PROTOTYPE_FAILURE: 366 case RECOMPUTE_HANDLER:
386 case DEBUG_STUB: 367 case DEBUG_STUB:
387 UNREACHABLE(); 368 UNREACHABLE();
388 } 369 }
389 } 370 }
390 371
391 372
392 void IC::OnTypeFeedbackChanged(Isolate* isolate, Address address, 373 void IC::OnTypeFeedbackChanged(Isolate* isolate, Address address,
393 State old_state, State new_state, 374 State old_state, State new_state,
394 bool target_remains_ic_stub) { 375 bool target_remains_ic_stub) {
395 Code* host = 376 Code* host =
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
453 } 434 }
454 435
455 436
456 void IC::Clear(Isolate* isolate, Address address, Address constant_pool) { 437 void IC::Clear(Isolate* isolate, Address address, Address constant_pool) {
457 Code* target = GetTargetAtAddress(address, constant_pool); 438 Code* target = GetTargetAtAddress(address, constant_pool);
458 439
459 // Don't clear debug break inline cache as it will remove the break point. 440 // Don't clear debug break inline cache as it will remove the break point.
460 if (target->is_debug_stub()) return; 441 if (target->is_debug_stub()) return;
461 442
462 switch (target->kind()) { 443 switch (target->kind()) {
463 case Code::LOAD_IC:
464 case Code::KEYED_LOAD_IC:
465 case Code::STORE_IC:
466 case Code::KEYED_STORE_IC:
467 return;
468 case Code::COMPARE_IC: 444 case Code::COMPARE_IC:
469 return CompareIC::Clear(isolate, address, target, constant_pool); 445 return CompareIC::Clear(isolate, address, target, constant_pool);
446 case Code::BINARY_OP_IC:
470 case Code::CALL_IC: // CallICs are vector-based and cleared differently. 447 case Code::CALL_IC: // CallICs are vector-based and cleared differently.
471 case Code::BINARY_OP_IC: 448 case Code::KEYED_LOAD_IC:
449 case Code::KEYED_STORE_IC:
450 case Code::LOAD_IC:
451 case Code::STORE_IC:
472 case Code::TO_BOOLEAN_IC: 452 case Code::TO_BOOLEAN_IC:
473 // Clearing these is tricky and does not 453 // Clearing these is tricky and does not
474 // make any performance difference. 454 // make any performance difference.
475 return; 455 return;
476 default: 456 default:
477 UNREACHABLE(); 457 UNREACHABLE();
478 } 458 }
479 } 459 }
480 460
481 461
(...skipping 20 matching lines...) Expand all
502 } 482 }
503 483
504 484
505 void LoadIC::Clear(Isolate* isolate, Code* host, LoadICNexus* nexus) { 485 void LoadIC::Clear(Isolate* isolate, Code* host, LoadICNexus* nexus) {
506 if (IsCleared(nexus)) return; 486 if (IsCleared(nexus)) return;
507 nexus->ConfigurePremonomorphic(); 487 nexus->ConfigurePremonomorphic();
508 OnTypeFeedbackChanged(isolate, host); 488 OnTypeFeedbackChanged(isolate, host);
509 } 489 }
510 490
511 491
512 void StoreIC::Clear(Isolate* isolate, Address address, Code* target,
513 Address constant_pool) {
514 if (IsCleared(target)) return;
515 Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::STORE_IC,
516 target->extra_ic_state());
517 SetTargetAtAddress(address, code, constant_pool);
518 }
519
520
521 void StoreIC::Clear(Isolate* isolate, Code* host, StoreICNexus* nexus) { 492 void StoreIC::Clear(Isolate* isolate, Code* host, StoreICNexus* nexus) {
522 if (IsCleared(nexus)) return; 493 if (IsCleared(nexus)) return;
523 nexus->ConfigurePremonomorphic(); 494 nexus->ConfigurePremonomorphic();
524 OnTypeFeedbackChanged(isolate, host); 495 OnTypeFeedbackChanged(isolate, host);
525 } 496 }
526 497
527 498
528 void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target,
529 Address constant_pool) {
530 if (IsCleared(target)) return;
531 Handle<Code> code = pre_monomorphic_stub(
532 isolate, StoreICState::GetLanguageMode(target->extra_ic_state()));
533 SetTargetAtAddress(address, *code, constant_pool);
534 }
535
536
537 void KeyedStoreIC::Clear(Isolate* isolate, Code* host, 499 void KeyedStoreIC::Clear(Isolate* isolate, Code* host,
538 KeyedStoreICNexus* nexus) { 500 KeyedStoreICNexus* nexus) {
539 if (IsCleared(nexus)) return; 501 if (IsCleared(nexus)) return;
540 nexus->ConfigurePremonomorphic(); 502 nexus->ConfigurePremonomorphic();
541 OnTypeFeedbackChanged(isolate, host); 503 OnTypeFeedbackChanged(isolate, host);
542 } 504 }
543 505
544 506
545 void CompareIC::Clear(Isolate* isolate, Address address, Code* target, 507 void CompareIC::Clear(Isolate* isolate, Address address, Code* target,
546 Address constant_pool) { 508 Address constant_pool) {
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
735 return false; 697 return false;
736 } 698 }
737 } 699 }
738 receiver_maps->Add(new_receiver_map); 700 receiver_maps->Add(new_receiver_map);
739 return true; 701 return true;
740 } 702 }
741 703
742 704
743 bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Code> code) { 705 bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Code> code) {
744 if (!code->is_handler()) return false; 706 if (!code->is_handler()) return false;
745 if (target()->is_keyed_stub() && state() != PROTOTYPE_FAILURE) return false; 707 if (target()->is_keyed_stub() && state() != RECOMPUTE_HANDLER) return false;
746 Handle<Map> map = receiver_map(); 708 Handle<Map> map = receiver_map();
747 MapHandleList maps; 709 MapHandleList maps;
748 CodeHandleList handlers; 710 CodeHandleList handlers;
749 711
750 TargetMaps(&maps); 712 TargetMaps(&maps);
751 int number_of_maps = maps.length(); 713 int number_of_maps = maps.length();
752 int deprecated_maps = 0; 714 int deprecated_maps = 0;
753 int handler_to_overwrite = -1; 715 int handler_to_overwrite = -1;
754 716
755 for (int i = 0; i < number_of_maps; i++) { 717 for (int i = 0; i < number_of_maps; i++) {
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
836 return transitioned_map == target_map; 798 return transitioned_map == target_map;
837 } 799 }
838 800
839 801
840 void IC::PatchCache(Handle<Name> name, Handle<Code> code) { 802 void IC::PatchCache(Handle<Name> name, Handle<Code> code) {
841 switch (state()) { 803 switch (state()) {
842 case UNINITIALIZED: 804 case UNINITIALIZED:
843 case PREMONOMORPHIC: 805 case PREMONOMORPHIC:
844 UpdateMonomorphicIC(code, name); 806 UpdateMonomorphicIC(code, name);
845 break; 807 break;
846 case PROTOTYPE_FAILURE: 808 case RECOMPUTE_HANDLER:
847 case MONOMORPHIC: 809 case MONOMORPHIC:
848 case POLYMORPHIC: 810 case POLYMORPHIC:
849 if (!target()->is_keyed_stub() || state() == PROTOTYPE_FAILURE) { 811 if (!target()->is_keyed_stub() || state() == RECOMPUTE_HANDLER) {
850 if (UpdatePolymorphicIC(name, code)) break; 812 if (UpdatePolymorphicIC(name, code)) break;
851 // For keyed stubs, we can't know whether old handlers were for the 813 // For keyed stubs, we can't know whether old handlers were for the
852 // same key. 814 // same key.
853 CopyICToMegamorphicCache(name); 815 CopyICToMegamorphicCache(name);
854 } 816 }
855 if (UseVector()) { 817 if (UseVector()) {
856 ConfigureVectorState(MEGAMORPHIC); 818 ConfigureVectorState(MEGAMORPHIC);
857 } else { 819 } else {
858 set_target(*megamorphic_stub()); 820 set_target(*megamorphic_stub());
859 } 821 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
900 return KeyedLoadICStub(isolate, LoadICState(extra_state)).GetCode(); 862 return KeyedLoadICStub(isolate, LoadICState(extra_state)).GetCode();
901 } 863 }
902 return isolate->builtins()->KeyedLoadIC_Megamorphic(); 864 return isolate->builtins()->KeyedLoadIC_Megamorphic();
903 } 865 }
904 866
905 867
906 static Handle<Code> KeyedStoreICInitializeStubHelper( 868 static Handle<Code> KeyedStoreICInitializeStubHelper(
907 Isolate* isolate, LanguageMode language_mode, 869 Isolate* isolate, LanguageMode language_mode,
908 InlineCacheState initialization_state) { 870 InlineCacheState initialization_state) {
909 switch (initialization_state) { 871 switch (initialization_state) {
910 case UNINITIALIZED:
911 return is_strict(language_mode)
912 ? isolate->builtins()->KeyedStoreIC_Initialize_Strict()
913 : isolate->builtins()->KeyedStoreIC_Initialize();
914 case PREMONOMORPHIC:
915 return is_strict(language_mode)
916 ? isolate->builtins()->KeyedStoreIC_PreMonomorphic_Strict()
917 : isolate->builtins()->KeyedStoreIC_PreMonomorphic();
918 case MEGAMORPHIC: 872 case MEGAMORPHIC:
919 return is_strict(language_mode) 873 return is_strict(language_mode)
920 ? isolate->builtins()->KeyedStoreIC_Megamorphic_Strict() 874 ? isolate->builtins()->KeyedStoreIC_Megamorphic_Strict()
921 : isolate->builtins()->KeyedStoreIC_Megamorphic(); 875 : isolate->builtins()->KeyedStoreIC_Megamorphic();
922 default: 876 default:
923 UNREACHABLE(); 877 UNREACHABLE();
924 } 878 }
925 return Handle<Code>(); 879 return Handle<Code>();
926 } 880 }
927 881
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
1062 1016
1063 1017
1064 Handle<Code> IC::ComputeHandler(LookupIterator* lookup, Handle<Object> value) { 1018 Handle<Code> IC::ComputeHandler(LookupIterator* lookup, Handle<Object> value) {
1065 bool receiver_is_holder = 1019 bool receiver_is_holder =
1066 lookup->GetReceiver().is_identical_to(lookup->GetHolder<JSObject>()); 1020 lookup->GetReceiver().is_identical_to(lookup->GetHolder<JSObject>());
1067 CacheHolderFlag flag; 1021 CacheHolderFlag flag;
1068 Handle<Map> stub_holder_map = IC::GetHandlerCacheHolder( 1022 Handle<Map> stub_holder_map = IC::GetHandlerCacheHolder(
1069 receiver_map(), receiver_is_holder, isolate(), &flag); 1023 receiver_map(), receiver_is_holder, isolate(), &flag);
1070 1024
1071 Handle<Code> code = PropertyHandlerCompiler::Find( 1025 Handle<Code> code = PropertyHandlerCompiler::Find(
1072 lookup->name(), stub_holder_map, kind(), flag, 1026 lookup->name(), stub_holder_map, kind(), flag);
1073 lookup->is_dictionary_holder() ? Code::NORMAL : Code::FAST);
1074 // Use the cached value if it exists, and if it is different from the 1027 // Use the cached value if it exists, and if it is different from the
1075 // handler that just missed. 1028 // handler that just missed.
1076 if (!code.is_null()) { 1029 if (!code.is_null()) {
1077 if (!maybe_handler_.is_null() && 1030 Handle<Code> handler;
1078 !maybe_handler_.ToHandleChecked().is_identical_to(code)) { 1031 if (maybe_handler_.ToHandle(&handler)) {
1079 return code; 1032 if (!handler.is_identical_to(code)) return code;
1080 } 1033 } else {
1081 if (maybe_handler_.is_null()) {
1082 // maybe_handler_ is only populated for MONOMORPHIC and POLYMORPHIC ICs. 1034 // maybe_handler_ is only populated for MONOMORPHIC and POLYMORPHIC ICs.
1083 // In MEGAMORPHIC case, check if the handler in the megamorphic stub 1035 // In MEGAMORPHIC case, check if the handler in the megamorphic stub
1084 // cache (which just missed) is different from the cached handler. 1036 // cache (which just missed) is different from the cached handler.
1085 if (state() == MEGAMORPHIC && lookup->GetReceiver()->IsHeapObject()) { 1037 if (state() == MEGAMORPHIC && lookup->GetReceiver()->IsHeapObject()) {
1086 Map* map = Handle<HeapObject>::cast(lookup->GetReceiver())->map(); 1038 Map* map = Handle<HeapObject>::cast(lookup->GetReceiver())->map();
1087 Code* megamorphic_cached_code = 1039 Code* megamorphic_cached_code =
1088 isolate()->stub_cache()->Get(*lookup->name(), map, code->flags()); 1040 isolate()->stub_cache()->Get(*lookup->name(), map, code->flags());
1089 if (megamorphic_cached_code != *code) return code; 1041 if (megamorphic_cached_code != *code) return code;
1090 } else { 1042 } else {
1091 return code; 1043 return code;
1092 } 1044 }
1093 } 1045 }
1094 } 1046 }
1095 1047
1096 code = CompileHandler(lookup, value, flag); 1048 code = CompileHandler(lookup, value, flag);
1097 DCHECK(code->is_handler()); 1049 DCHECK(code->is_handler());
1098 1050
1099 // TODO(mvstanton): we'd only like to cache code on the map when it's custom 1051 // TODO(mvstanton): we'd only like to cache code on the map when it's custom
1100 // code compiled for this map, otherwise it's already cached in the global 1052 // code compiled for this map, otherwise it's already cached in the global
1101 // code cache. We are also guarding against installing code with flags that 1053 // code cache. We are also guarding against installing code with flags that
1102 // don't match the desired CacheHolderFlag computed above, which would lead to 1054 // don't match the desired CacheHolderFlag computed above, which would lead to
1103 // invalid lookups later. 1055 // invalid lookups later.
1104 if (code->type() != Code::NORMAL && 1056 bool is_normal = receiver_is_holder &&
1105 Code::ExtractCacheHolderFromFlags(code->flags()) == flag) { 1057 !lookup->GetHolder<JSReceiver>()->HasFastProperties();
1058 if (!is_normal && Code::ExtractCacheHolderFromFlags(code->flags()) == flag) {
1106 Map::UpdateCodeCache(stub_holder_map, lookup->name(), code); 1059 Map::UpdateCodeCache(stub_holder_map, lookup->name(), code);
1107 } 1060 }
1108 1061
1109 return code; 1062 return code;
1110 } 1063 }
1111 1064
1112 1065
1113 Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup, 1066 Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
1114 Handle<Object> unused, 1067 Handle<Object> unused,
1115 CacheHolderFlag cache_holder) { 1068 CacheHolderFlag cache_holder) {
(...skipping 518 matching lines...) Expand 10 before | Expand all | Expand 10 after
1634 Handle<Code> StoreIC::slow_stub() const { 1587 Handle<Code> StoreIC::slow_stub() const {
1635 if (kind() == Code::STORE_IC) { 1588 if (kind() == Code::STORE_IC) {
1636 return isolate()->builtins()->StoreIC_Slow(); 1589 return isolate()->builtins()->StoreIC_Slow();
1637 } else { 1590 } else {
1638 DCHECK(kind() == Code::KEYED_STORE_IC); 1591 DCHECK(kind() == Code::KEYED_STORE_IC);
1639 return isolate()->builtins()->KeyedStoreIC_Slow(); 1592 return isolate()->builtins()->KeyedStoreIC_Slow();
1640 } 1593 }
1641 } 1594 }
1642 1595
1643 1596
1644 Handle<Code> StoreIC::pre_monomorphic_stub(Isolate* isolate,
1645 LanguageMode language_mode) {
1646 ExtraICState state = ComputeExtraICState(language_mode);
1647 return PropertyICCompiler::ComputeStore(isolate, PREMONOMORPHIC, state);
1648 }
1649
1650
1651 void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value, 1597 void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value,
1652 JSReceiver::StoreFromKeyed store_mode) { 1598 JSReceiver::StoreFromKeyed store_mode) {
1653 if (state() == UNINITIALIZED) { 1599 if (state() == UNINITIALIZED) {
1654 // This is the first time we execute this inline cache. Set the target to 1600 // This is the first time we execute this inline cache. Set the target to
1655 // the pre monomorphic stub to delay setting the monomorphic state. 1601 // the pre monomorphic stub to delay setting the monomorphic state.
1656 ConfigureVectorState(PREMONOMORPHIC); 1602 ConfigureVectorState(PREMONOMORPHIC);
1657 TRACE_IC("StoreIC", lookup->name()); 1603 TRACE_IC("StoreIC", lookup->name());
1658 return; 1604 return;
1659 } 1605 }
1660 1606
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
1821 case LookupIterator::JSPROXY: 1767 case LookupIterator::JSPROXY:
1822 case LookupIterator::NOT_FOUND: 1768 case LookupIterator::NOT_FOUND:
1823 UNREACHABLE(); 1769 UNREACHABLE();
1824 } 1770 }
1825 return slow_stub(); 1771 return slow_stub();
1826 } 1772 }
1827 1773
1828 1774
1829 Handle<Code> KeyedStoreIC::StoreElementStub(Handle<Map> receiver_map, 1775 Handle<Code> KeyedStoreIC::StoreElementStub(Handle<Map> receiver_map,
1830 KeyedAccessStoreMode store_mode) { 1776 KeyedAccessStoreMode store_mode) {
1831 Handle<Code> null_handle;
1832 // Don't handle megamorphic property accesses for INTERCEPTORS or
1833 // ACCESSOR_CONSTANT
1834 // via megamorphic stubs, since they don't have a map in their relocation info
1835 // and so the stubs can't be harvested for the object needed for a map check.
1836 if (target()->type() != Code::NORMAL) {
1837 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-NORMAL target type");
1838 return megamorphic_stub();
1839 }
1840
1841 MapHandleList target_receiver_maps; 1777 MapHandleList target_receiver_maps;
1842 TargetMaps(&target_receiver_maps); 1778 TargetMaps(&target_receiver_maps);
1843 if (target_receiver_maps.length() == 0) { 1779 if (target_receiver_maps.length() == 0) {
1844 Handle<Map> monomorphic_map = 1780 Handle<Map> monomorphic_map =
1845 ComputeTransitionedMap(receiver_map, store_mode); 1781 ComputeTransitionedMap(receiver_map, store_mode);
1846 store_mode = GetNonTransitioningStoreMode(store_mode); 1782 store_mode = GetNonTransitioningStoreMode(store_mode);
1847 Handle<Code> handler = 1783 Handle<Code> handler =
1848 PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler( 1784 PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler(
1849 monomorphic_map, language_mode(), store_mode); 1785 monomorphic_map, language_mode(), store_mode);
1850 ConfigureVectorState(Handle<Name>::null(), monomorphic_map, handler); 1786 ConfigureVectorState(Handle<Name>::null(), monomorphic_map, handler);
1851 return null_handle; 1787 return Handle<Code>();
1852 } 1788 }
1853 1789
1854 // There are several special cases where an IC that is MONOMORPHIC can still 1790 // There are several special cases where an IC that is MONOMORPHIC can still
1855 // transition to a different GetNonTransitioningStoreMode IC that handles a 1791 // transition to a different GetNonTransitioningStoreMode IC that handles a
1856 // superset of the original IC. Handle those here if the receiver map hasn't 1792 // superset of the original IC. Handle those here if the receiver map hasn't
1857 // changed or it has transitioned to a more general kind. 1793 // changed or it has transitioned to a more general kind.
1858 KeyedAccessStoreMode old_store_mode = GetKeyedAccessStoreMode(); 1794 KeyedAccessStoreMode old_store_mode = GetKeyedAccessStoreMode();
1859 Handle<Map> previous_receiver_map = target_receiver_maps.at(0); 1795 Handle<Map> previous_receiver_map = target_receiver_maps.at(0);
1860 if (state() == MONOMORPHIC) { 1796 if (state() == MONOMORPHIC) {
1861 Handle<Map> transitioned_receiver_map = receiver_map; 1797 Handle<Map> transitioned_receiver_map = receiver_map;
1862 if (IsTransitionStoreMode(store_mode)) { 1798 if (IsTransitionStoreMode(store_mode)) {
1863 transitioned_receiver_map = 1799 transitioned_receiver_map =
1864 ComputeTransitionedMap(receiver_map, store_mode); 1800 ComputeTransitionedMap(receiver_map, store_mode);
1865 } 1801 }
1866 if ((receiver_map.is_identical_to(previous_receiver_map) && 1802 if ((receiver_map.is_identical_to(previous_receiver_map) &&
1867 IsTransitionStoreMode(store_mode)) || 1803 IsTransitionStoreMode(store_mode)) ||
1868 IsTransitionOfMonomorphicTarget(*previous_receiver_map, 1804 IsTransitionOfMonomorphicTarget(*previous_receiver_map,
1869 *transitioned_receiver_map)) { 1805 *transitioned_receiver_map)) {
1870 // If the "old" and "new" maps are in the same elements map family, or 1806 // If the "old" and "new" maps are in the same elements map family, or
1871 // if they at least come from the same origin for a transitioning store, 1807 // if they at least come from the same origin for a transitioning store,
1872 // stay MONOMORPHIC and use the map for the most generic ElementsKind. 1808 // stay MONOMORPHIC and use the map for the most generic ElementsKind.
1873 store_mode = GetNonTransitioningStoreMode(store_mode); 1809 store_mode = GetNonTransitioningStoreMode(store_mode);
1874 Handle<Code> handler = 1810 Handle<Code> handler =
1875 PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler( 1811 PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler(
1876 transitioned_receiver_map, language_mode(), store_mode); 1812 transitioned_receiver_map, language_mode(), store_mode);
1877 ConfigureVectorState(Handle<Name>::null(), transitioned_receiver_map, 1813 ConfigureVectorState(Handle<Name>::null(), transitioned_receiver_map,
1878 handler); 1814 handler);
1879 return null_handle; 1815 return Handle<Code>();
1880 } else if (receiver_map.is_identical_to(previous_receiver_map) && 1816 } else if (receiver_map.is_identical_to(previous_receiver_map) &&
1881 old_store_mode == STANDARD_STORE && 1817 old_store_mode == STANDARD_STORE &&
1882 (store_mode == STORE_AND_GROW_NO_TRANSITION || 1818 (store_mode == STORE_AND_GROW_NO_TRANSITION ||
1883 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || 1819 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
1884 store_mode == STORE_NO_TRANSITION_HANDLE_COW)) { 1820 store_mode == STORE_NO_TRANSITION_HANDLE_COW)) {
1885 // A "normal" IC that handles stores can switch to a version that can 1821 // A "normal" IC that handles stores can switch to a version that can
1886 // grow at the end of the array, handle OOB accesses or copy COW arrays 1822 // grow at the end of the array, handle OOB accesses or copy COW arrays
1887 // and still stay MONOMORPHIC. 1823 // and still stay MONOMORPHIC.
1888 Handle<Code> handler = 1824 Handle<Code> handler =
1889 PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler( 1825 PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler(
1890 receiver_map, language_mode(), store_mode); 1826 receiver_map, language_mode(), store_mode);
1891 ConfigureVectorState(Handle<Name>::null(), receiver_map, handler); 1827 ConfigureVectorState(Handle<Name>::null(), receiver_map, handler);
1892 return null_handle; 1828 return Handle<Code>();
1893 } 1829 }
1894 } 1830 }
1895 1831
1896 DCHECK(state() != GENERIC); 1832 DCHECK(state() != GENERIC);
1897 1833
1898 bool map_added = 1834 bool map_added =
1899 AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map); 1835 AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map);
1900 1836
1901 if (IsTransitionStoreMode(store_mode)) { 1837 if (IsTransitionStoreMode(store_mode)) {
1902 Handle<Map> transitioned_receiver_map = 1838 Handle<Map> transitioned_receiver_map =
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1947 return megamorphic_stub(); 1883 return megamorphic_stub();
1948 } 1884 }
1949 } 1885 }
1950 1886
1951 MapHandleList transitioned_maps(target_receiver_maps.length()); 1887 MapHandleList transitioned_maps(target_receiver_maps.length());
1952 CodeHandleList handlers(target_receiver_maps.length()); 1888 CodeHandleList handlers(target_receiver_maps.length());
1953 PropertyICCompiler::ComputeKeyedStorePolymorphicHandlers( 1889 PropertyICCompiler::ComputeKeyedStorePolymorphicHandlers(
1954 &target_receiver_maps, &transitioned_maps, &handlers, store_mode, 1890 &target_receiver_maps, &transitioned_maps, &handlers, store_mode,
1955 language_mode()); 1891 language_mode());
1956 ConfigureVectorState(&target_receiver_maps, &transitioned_maps, &handlers); 1892 ConfigureVectorState(&target_receiver_maps, &transitioned_maps, &handlers);
1957 return null_handle; 1893 return Handle<Code>();
1958 } 1894 }
1959 1895
1960 1896
1961 Handle<Map> KeyedStoreIC::ComputeTransitionedMap( 1897 Handle<Map> KeyedStoreIC::ComputeTransitionedMap(
1962 Handle<Map> map, KeyedAccessStoreMode store_mode) { 1898 Handle<Map> map, KeyedAccessStoreMode store_mode) {
1963 switch (store_mode) { 1899 switch (store_mode) {
1964 case STORE_TRANSITION_TO_OBJECT: 1900 case STORE_TRANSITION_TO_OBJECT:
1965 case STORE_AND_GROW_TRANSITION_TO_OBJECT: { 1901 case STORE_AND_GROW_TRANSITION_TO_OBJECT: {
1966 ElementsKind kind = IsFastHoleyElementsKind(map->elements_kind()) 1902 ElementsKind kind = IsFastHoleyElementsKind(map->elements_kind())
1967 ? FAST_HOLEY_ELEMENTS 1903 ? FAST_HOLEY_ELEMENTS
(...skipping 990 matching lines...) Expand 10 before | Expand all | Expand 10 after
2958 KeyedLoadICNexus nexus(vector, vector_slot); 2894 KeyedLoadICNexus nexus(vector, vector_slot);
2959 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); 2895 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
2960 ic.UpdateState(receiver, key); 2896 ic.UpdateState(receiver, key);
2961 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); 2897 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key));
2962 } 2898 }
2963 2899
2964 return *result; 2900 return *result;
2965 } 2901 }
2966 } // namespace internal 2902 } // namespace internal
2967 } // namespace v8 2903 } // namespace v8
OLDNEW
« no previous file with comments | « src/ic/ic.h ('k') | src/ic/ic-compiler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698