Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 142 StackFrameIterator it(isolate); | 142 StackFrameIterator it(isolate); |
| 143 for (int i = 0; i < depth + 1; i++) it.Advance(); | 143 for (int i = 0; i < depth + 1; i++) it.Advance(); |
| 144 StackFrame* frame = it.frame(); | 144 StackFrame* frame = it.frame(); |
| 145 ASSERT(fp == frame->fp() && pc_address == frame->pc_address()); | 145 ASSERT(fp == frame->fp() && pc_address == frame->pc_address()); |
| 146 #endif | 146 #endif |
| 147 fp_ = fp; | 147 fp_ = fp; |
| 148 pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address); | 148 pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address); |
| 149 target_ = handle(raw_target(), isolate); | 149 target_ = handle(raw_target(), isolate); |
| 150 state_ = target_->ic_state(); | 150 state_ = target_->ic_state(); |
| 151 extra_ic_state_ = target_->extra_ic_state(); | 151 extra_ic_state_ = target_->extra_ic_state(); |
| 152 target()->FindAllTypes(&types_); | |
| 153 target()->FindHandlers(&handlers_); | |
| 152 } | 154 } |
| 153 | 155 |
| 154 | 156 |
| 155 #ifdef ENABLE_DEBUGGER_SUPPORT | 157 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 156 Address IC::OriginalCodeAddress() const { | 158 Address IC::OriginalCodeAddress() const { |
| 157 HandleScope scope(isolate()); | 159 HandleScope scope(isolate()); |
| 158 // Compute the JavaScript frame for the frame pointer of this IC | 160 // Compute the JavaScript frame for the frame pointer of this IC |
| 159 // structure. We need this to be able to find the function | 161 // structure. We need this to be able to find the function |
| 160 // corresponding to the frame. | 162 // corresponding to the frame. |
| 161 StackFrameIterator it(isolate()); | 163 StackFrameIterator it(isolate()); |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 274 | 276 |
| 275 // The stub is not in the cache. We've ruled out all other kinds of failure | 277 // The stub is not in the cache. We've ruled out all other kinds of failure |
| 276 // except for proptotype chain changes, a deprecated map, a map that's | 278 // except for proptotype chain changes, a deprecated map, a map that's |
| 277 // different from the one that the stub expects, elements kind changes, or a | 279 // different from the one that the stub expects, elements kind changes, or a |
| 278 // constant global property that will become mutable. Threat all those | 280 // constant global property that will become mutable. Threat all those |
| 279 // situations as prototype failures (stay monomorphic if possible). | 281 // situations as prototype failures (stay monomorphic if possible). |
| 280 | 282 |
| 281 // If the IC is shared between multiple receivers (slow dictionary mode), then | 283 // If the IC is shared between multiple receivers (slow dictionary mode), then |
| 282 // the map cannot be deprecated and the stub invalidated. | 284 // the map cannot be deprecated and the stub invalidated. |
| 283 if (cache_holder == OWN_MAP) { | 285 if (cache_holder == OWN_MAP) { |
| 284 Map* old_map = target()->FindFirstMap(); | 286 Map* old_map = first_map(); |
| 285 if (old_map == *map) return true; | 287 if (old_map == *map) return true; |
| 286 if (old_map != NULL) { | 288 if (old_map != NULL) { |
| 287 if (old_map->is_deprecated()) return true; | 289 if (old_map->is_deprecated()) return true; |
| 288 if (IsMoreGeneralElementsKindTransition(old_map->elements_kind(), | 290 if (IsMoreGeneralElementsKindTransition(old_map->elements_kind(), |
| 289 map->elements_kind())) { | 291 map->elements_kind())) { |
| 290 return true; | 292 return true; |
| 291 } | 293 } |
| 292 } | 294 } |
| 293 } | 295 } |
| 294 | 296 |
| 295 if (receiver->IsGlobalObject()) { | 297 if (receiver->IsGlobalObject()) { |
| 296 LookupResult lookup(isolate()); | 298 LookupResult lookup(isolate()); |
| 297 GlobalObject* global = GlobalObject::cast(*receiver); | 299 GlobalObject* global = GlobalObject::cast(*receiver); |
| 298 global->LocalLookupRealNamedProperty(*name, &lookup); | 300 global->LocalLookupRealNamedProperty(*name, &lookup); |
| 299 if (!lookup.IsFound()) return false; | 301 if (!lookup.IsFound()) return false; |
| 300 PropertyCell* cell = global->GetPropertyCell(&lookup); | 302 PropertyCell* cell = global->GetPropertyCell(&lookup); |
| 301 return cell->type()->IsConstant(); | 303 return cell->type()->IsConstant(); |
| 302 } | 304 } |
| 303 | 305 |
| 304 return false; | 306 return false; |
| 305 } | 307 } |
| 306 | 308 |
| 307 | 309 |
| 308 void IC::TryRemoveInvalidHandlers(Handle<Map> map, Handle<String> name) { | 310 void IC::TryRemoveInvalidHandlers(Handle<Map> map, Handle<String> name) { |
| 309 CodeHandleList handlers; | 311 for (int i = 0; i < handlers()->length(); i++) { |
| 310 target()->FindHandlers(&handlers); | 312 Handle<Code> handler = handlers()->at(i); |
| 311 for (int i = 0; i < handlers.length(); i++) { | |
| 312 Handle<Code> handler = handlers.at(i); | |
| 313 int index = map->IndexInCodeCache(*name, *handler); | 313 int index = map->IndexInCodeCache(*name, *handler); |
| 314 if (index >= 0) { | 314 if (index >= 0) { |
| 315 map->RemoveFromCodeCache(*name, *handler, index); | 315 map->RemoveFromCodeCache(*name, *handler, index); |
| 316 return; | 316 return; |
| 317 } | 317 } |
| 318 } | 318 } |
| 319 } | 319 } |
| 320 | 320 |
| 321 | 321 |
| 322 void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) { | 322 void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) { |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 598 } | 598 } |
| 599 receiver_maps->Add(new_receiver_map); | 599 receiver_maps->Add(new_receiver_map); |
| 600 return true; | 600 return true; |
| 601 } | 601 } |
| 602 | 602 |
| 603 | 603 |
| 604 bool IC::UpdatePolymorphicIC(Handle<HeapType> type, | 604 bool IC::UpdatePolymorphicIC(Handle<HeapType> type, |
| 605 Handle<String> name, | 605 Handle<String> name, |
| 606 Handle<Code> code) { | 606 Handle<Code> code) { |
| 607 if (!code->is_handler()) return false; | 607 if (!code->is_handler()) return false; |
| 608 TypeHandleList types; | |
| 609 CodeHandleList handlers; | |
| 610 | |
| 611 int number_of_valid_types; | 608 int number_of_valid_types; |
| 612 int handler_to_overwrite = -1; | 609 int handler_to_overwrite = -1; |
| 613 | 610 |
| 614 target()->FindAllTypes(&types); | 611 int number_of_types = types()->length(); |
| 615 int number_of_types = types.length(); | |
| 616 number_of_valid_types = number_of_types; | 612 number_of_valid_types = number_of_types; |
| 617 | 613 |
| 618 for (int i = 0; i < number_of_types; i++) { | 614 for (int i = 0; i < number_of_types; i++) { |
| 619 Handle<HeapType> current_type = types.at(i); | 615 Handle<HeapType> current_type = types()->at(i); |
| 620 // Filter out deprecated maps to ensure their instances get migrated. | 616 // Filter out deprecated maps to ensure their instances get migrated. |
| 621 if (current_type->IsClass() && current_type->AsClass()->is_deprecated()) { | 617 if (current_type->IsClass() && current_type->AsClass()->is_deprecated()) { |
| 622 number_of_valid_types--; | 618 number_of_valid_types--; |
| 623 // If the receiver type is already in the polymorphic IC, this indicates | 619 // If the receiver type is already in the polymorphic IC, this indicates |
| 624 // there was a prototoype chain failure. In that case, just overwrite the | 620 // there was a prototoype chain failure. In that case, just overwrite the |
| 625 // handler. | 621 // handler. |
| 626 } else if (type->IsCurrently(current_type)) { | 622 } else if (type->IsCurrently(current_type)) { |
| 627 ASSERT(handler_to_overwrite == -1); | 623 ASSERT(handler_to_overwrite == -1); |
| 628 number_of_valid_types--; | 624 number_of_valid_types--; |
| 629 handler_to_overwrite = i; | 625 handler_to_overwrite = i; |
| 630 } | 626 } |
| 631 } | 627 } |
| 632 | 628 |
| 633 if (number_of_valid_types >= 4) return false; | 629 if (number_of_valid_types >= 4) return false; |
| 634 if (number_of_types == 0) return false; | 630 if (number_of_types == 0) return false; |
| 635 if (!target()->FindHandlers(&handlers, types.length())) return false; | 631 if (handlers()->length() < types()->length()) return false; |
| 636 | 632 |
| 637 number_of_valid_types++; | 633 number_of_valid_types++; |
| 638 if (handler_to_overwrite >= 0) { | 634 if (handler_to_overwrite >= 0) { |
| 639 handlers.Set(handler_to_overwrite, code); | 635 handlers()->Set(handler_to_overwrite, code); |
|
ulan
2014/02/18 14:50:26
This function modifies handlers and types. Do you
Toon Verwaest
2014/02/18 15:06:36
This is done at the end of IC computation. It shou
| |
| 640 } else { | 636 } else { |
| 641 types.Add(type); | 637 types()->Add(type); |
| 642 handlers.Add(code); | 638 handlers()->Add(code); |
| 643 } | 639 } |
| 644 | 640 |
| 645 Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC( | 641 Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC( |
| 646 kind(), &types, &handlers, number_of_valid_types, name, extra_ic_state()); | 642 kind(), types(), handlers(), number_of_valid_types, |
| 643 name, extra_ic_state()); | |
| 647 set_target(*ic); | 644 set_target(*ic); |
| 648 return true; | 645 return true; |
| 649 } | 646 } |
| 650 | 647 |
| 651 | 648 |
| 652 Handle<HeapType> IC::CurrentTypeOf(Handle<Object> object, Isolate* isolate) { | 649 Handle<HeapType> IC::CurrentTypeOf(Handle<Object> object, Isolate* isolate) { |
| 653 return object->IsJSGlobalObject() | 650 return object->IsJSGlobalObject() |
| 654 ? HeapType::Constant(Handle<JSGlobalObject>::cast(object), isolate) | 651 ? HeapType::Constant(Handle<JSGlobalObject>::cast(object), isolate) |
| 655 : HeapType::OfCurrently(object, isolate); | 652 : HeapType::OfCurrently(object, isolate); |
| 656 } | 653 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 694 Handle<Code> handler, | 691 Handle<Code> handler, |
| 695 Handle<String> name) { | 692 Handle<String> name) { |
| 696 if (!handler->is_handler()) return set_target(*handler); | 693 if (!handler->is_handler()) return set_target(*handler); |
| 697 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC( | 694 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC( |
| 698 kind(), name, type, handler, extra_ic_state()); | 695 kind(), name, type, handler, extra_ic_state()); |
| 699 set_target(*ic); | 696 set_target(*ic); |
| 700 } | 697 } |
| 701 | 698 |
| 702 | 699 |
| 703 void IC::CopyICToMegamorphicCache(Handle<String> name) { | 700 void IC::CopyICToMegamorphicCache(Handle<String> name) { |
| 704 TypeHandleList types; | 701 if (handlers()->length() < types()->length()) return; |
| 705 CodeHandleList handlers; | 702 for (int i = 0; i < types()->length(); i++) { |
| 706 target()->FindAllTypes(&types); | 703 UpdateMegamorphicCache(*types()->at(i), *name, *handlers()->at(i)); |
| 707 if (!target()->FindHandlers(&handlers, types.length())) return; | |
| 708 for (int i = 0; i < types.length(); i++) { | |
| 709 UpdateMegamorphicCache(*types.at(i), *name, *handlers.at(i)); | |
| 710 } | 704 } |
| 711 } | 705 } |
| 712 | 706 |
| 713 | 707 |
| 714 bool IC::IsTransitionOfMonomorphicTarget(Handle<HeapType> type) { | 708 bool IC::IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map) { |
| 715 if (!type->IsClass()) return false; | 709 if (source_map == NULL) return true; |
| 716 Map* receiver_map = *type->AsClass(); | 710 if (target_map == NULL) return false; |
| 717 Map* current_map = target()->FindFirstMap(); | 711 ElementsKind target_elements_kind = target_map->elements_kind(); |
| 718 ElementsKind receiver_elements_kind = receiver_map->elements_kind(); | 712 bool more_general_transition = IsMoreGeneralElementsKindTransition( |
| 719 bool more_general_transition = | 713 source_map->elements_kind(), target_elements_kind); |
| 720 IsMoreGeneralElementsKindTransition( | |
| 721 current_map->elements_kind(), receiver_elements_kind); | |
| 722 Map* transitioned_map = more_general_transition | 714 Map* transitioned_map = more_general_transition |
| 723 ? current_map->LookupElementsTransitionMap(receiver_elements_kind) | 715 ? source_map->LookupElementsTransitionMap(target_elements_kind) |
| 724 : NULL; | 716 : NULL; |
| 725 | 717 return transitioned_map == target_map; |
| 726 return transitioned_map == receiver_map; | |
| 727 } | 718 } |
| 728 | 719 |
| 729 | 720 |
| 730 void IC::PatchCache(Handle<HeapType> type, | 721 void IC::PatchCache(Handle<HeapType> type, |
| 731 Handle<String> name, | 722 Handle<String> name, |
| 732 Handle<Code> code) { | 723 Handle<Code> code) { |
| 733 switch (state()) { | 724 switch (state()) { |
| 734 case UNINITIALIZED: | 725 case UNINITIALIZED: |
| 735 case PREMONOMORPHIC: | 726 case PREMONOMORPHIC: |
| 736 case MONOMORPHIC_PROTOTYPE_FAILURE: | 727 case MONOMORPHIC_PROTOTYPE_FAILURE: |
| 737 UpdateMonomorphicIC(type, code, name); | 728 UpdateMonomorphicIC(type, code, name); |
| 738 break; | 729 break; |
| 739 case MONOMORPHIC: { | 730 case MONOMORPHIC: { |
| 740 // For now, call stubs are allowed to rewrite to the same stub. This | 731 // For now, call stubs are allowed to rewrite to the same stub. This |
| 741 // happens e.g., when the field does not contain a function. | 732 // happens e.g., when the field does not contain a function. |
| 742 ASSERT(!target().is_identical_to(code)); | 733 ASSERT(!target().is_identical_to(code)); |
| 743 Code* old_handler = target()->FindFirstHandler(); | 734 Map* old_map = first_map(); |
| 744 if (old_handler == *code && IsTransitionOfMonomorphicTarget(type)) { | 735 Code* old_handler = first_handler(); |
| 736 Map* map = type->IsClass() ? *type->AsClass() : NULL; | |
| 737 if (old_handler == *code && | |
| 738 IsTransitionOfMonomorphicTarget(old_map, map)) { | |
| 745 UpdateMonomorphicIC(type, code, name); | 739 UpdateMonomorphicIC(type, code, name); |
| 746 break; | 740 break; |
| 747 } | 741 } |
| 748 // Fall through. | 742 // Fall through. |
| 749 } | 743 } |
| 750 case POLYMORPHIC: | 744 case POLYMORPHIC: |
| 751 if (!target()->is_keyed_stub()) { | 745 if (!target()->is_keyed_stub()) { |
| 752 if (UpdatePolymorphicIC(type, name, code)) break; | 746 if (UpdatePolymorphicIC(type, name, code)) break; |
| 753 CopyICToMegamorphicCache(name); | 747 CopyICToMegamorphicCache(name); |
| 754 } | 748 } |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1003 MapHandleList target_receiver_maps; | 997 MapHandleList target_receiver_maps; |
| 1004 if (state() == UNINITIALIZED || state() == PREMONOMORPHIC) { | 998 if (state() == UNINITIALIZED || state() == PREMONOMORPHIC) { |
| 1005 // Optimistically assume that ICs that haven't reached the MONOMORPHIC state | 999 // Optimistically assume that ICs that haven't reached the MONOMORPHIC state |
| 1006 // yet will do so and stay there. | 1000 // yet will do so and stay there. |
| 1007 return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map); | 1001 return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map); |
| 1008 } | 1002 } |
| 1009 | 1003 |
| 1010 if (target().is_identical_to(string_stub())) { | 1004 if (target().is_identical_to(string_stub())) { |
| 1011 target_receiver_maps.Add(isolate()->factory()->string_map()); | 1005 target_receiver_maps.Add(isolate()->factory()->string_map()); |
| 1012 } else { | 1006 } else { |
| 1013 target()->FindAllMaps(&target_receiver_maps); | 1007 GetMapsFromTypes(&target_receiver_maps); |
| 1014 if (target_receiver_maps.length() == 0) { | 1008 if (target_receiver_maps.length() == 0) { |
| 1015 return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map); | 1009 return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map); |
| 1016 } | 1010 } |
| 1017 } | 1011 } |
| 1018 | 1012 |
| 1019 // The first time a receiver is seen that is a transitioned version of the | 1013 // The first time a receiver is seen that is a transitioned version of the |
| 1020 // previous monomorphic receiver type, assume the new ElementsKind is the | 1014 // previous monomorphic receiver type, assume the new ElementsKind is the |
| 1021 // monomorphic type. This benefits global arrays that only transition | 1015 // monomorphic type. This benefits global arrays that only transition |
| 1022 // once, and all call sites accessing them are faster if they remain | 1016 // once, and all call sites accessing them are faster if they remain |
| 1023 // monomorphic. If this optimistic assumption is not true, the IC will | 1017 // monomorphic. If this optimistic assumption is not true, the IC will |
| (...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1407 Handle<Map> receiver_map(receiver->map(), isolate()); | 1401 Handle<Map> receiver_map(receiver->map(), isolate()); |
| 1408 if (state() == UNINITIALIZED || state() == PREMONOMORPHIC) { | 1402 if (state() == UNINITIALIZED || state() == PREMONOMORPHIC) { |
| 1409 // Optimistically assume that ICs that haven't reached the MONOMORPHIC state | 1403 // Optimistically assume that ICs that haven't reached the MONOMORPHIC state |
| 1410 // yet will do so and stay there. | 1404 // yet will do so and stay there. |
| 1411 Handle<Map> monomorphic_map = ComputeTransitionedMap(receiver, store_mode); | 1405 Handle<Map> monomorphic_map = ComputeTransitionedMap(receiver, store_mode); |
| 1412 store_mode = GetNonTransitioningStoreMode(store_mode); | 1406 store_mode = GetNonTransitioningStoreMode(store_mode); |
| 1413 return isolate()->stub_cache()->ComputeKeyedStoreElement( | 1407 return isolate()->stub_cache()->ComputeKeyedStoreElement( |
| 1414 monomorphic_map, strict_mode(), store_mode); | 1408 monomorphic_map, strict_mode(), store_mode); |
| 1415 } | 1409 } |
| 1416 | 1410 |
| 1417 MapHandleList target_receiver_maps; | |
| 1418 target()->FindAllMaps(&target_receiver_maps); | |
| 1419 if (target_receiver_maps.length() == 0) { | |
| 1420 // In the case that there is a non-map-specific IC is installed (e.g. keyed | |
| 1421 // stores into properties in dictionary mode), then there will be not | |
| 1422 // receiver maps in the target. | |
| 1423 return generic_stub(); | |
| 1424 } | |
| 1425 | |
| 1426 // There are several special cases where an IC that is MONOMORPHIC can still | 1411 // There are several special cases where an IC that is MONOMORPHIC can still |
| 1427 // transition to a different GetNonTransitioningStoreMode IC that handles a | 1412 // transition to a different GetNonTransitioningStoreMode IC that handles a |
| 1428 // superset of the original IC. Handle those here if the receiver map hasn't | 1413 // superset of the original IC. Handle those here if the receiver map hasn't |
| 1429 // changed or it has transitioned to a more general kind. | 1414 // changed or it has transitioned to a more general kind. |
| 1430 KeyedAccessStoreMode old_store_mode = | 1415 KeyedAccessStoreMode old_store_mode = |
| 1431 KeyedStoreIC::GetKeyedAccessStoreMode(target()->extra_ic_state()); | 1416 KeyedStoreIC::GetKeyedAccessStoreMode(target()->extra_ic_state()); |
| 1432 Handle<Map> previous_receiver_map = target_receiver_maps.at(0); | |
| 1433 if (state() == MONOMORPHIC) { | 1417 if (state() == MONOMORPHIC) { |
| 1434 // If the "old" and "new" maps are in the same elements map family, stay | 1418 // If the "old" and "new" maps are in the same elements map family, stay |
| 1435 // MONOMORPHIC and use the map for the most generic ElementsKind. | 1419 // MONOMORPHIC and use the map for the most generic ElementsKind. |
| 1436 Handle<Map> transitioned_receiver_map = receiver_map; | 1420 Handle<Map> transitioned_map = receiver_map; |
| 1437 if (IsTransitionStoreMode(store_mode)) { | 1421 if (IsTransitionStoreMode(store_mode)) { |
| 1438 transitioned_receiver_map = | 1422 transitioned_map = ComputeTransitionedMap(receiver, store_mode); |
| 1439 ComputeTransitionedMap(receiver, store_mode); | |
| 1440 } | 1423 } |
| 1441 if (IsTransitionOfMonomorphicTarget( | 1424 if (IsTransitionOfMonomorphicTarget(first_map(), *transitioned_map)) { |
| 1442 MapToType<HeapType>(transitioned_receiver_map, isolate()))) { | |
| 1443 // Element family is the same, use the "worst" case map. | 1425 // Element family is the same, use the "worst" case map. |
| 1444 store_mode = GetNonTransitioningStoreMode(store_mode); | 1426 store_mode = GetNonTransitioningStoreMode(store_mode); |
| 1445 return isolate()->stub_cache()->ComputeKeyedStoreElement( | 1427 return isolate()->stub_cache()->ComputeKeyedStoreElement( |
| 1446 transitioned_receiver_map, strict_mode(), store_mode); | 1428 transitioned_map, strict_mode(), store_mode); |
| 1447 } else if (*previous_receiver_map == receiver->map() && | 1429 } else if (first_map() == receiver->map() && |
| 1448 old_store_mode == STANDARD_STORE && | 1430 old_store_mode == STANDARD_STORE && |
| 1449 (IsGrowStoreMode(store_mode) || | 1431 (IsGrowStoreMode(store_mode) || |
| 1450 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || | 1432 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || |
| 1451 store_mode == STORE_NO_TRANSITION_HANDLE_COW)) { | 1433 store_mode == STORE_NO_TRANSITION_HANDLE_COW)) { |
| 1452 // A "normal" IC that handles stores can switch to a version that can | 1434 // A "normal" IC that handles stores can switch to a version that can |
| 1453 // grow at the end of the array, handle OOB accesses or copy COW arrays | 1435 // grow at the end of the array, handle OOB accesses or copy COW arrays |
| 1454 // and still stay MONOMORPHIC. | 1436 // and still stay MONOMORPHIC. |
| 1455 return isolate()->stub_cache()->ComputeKeyedStoreElement( | 1437 return isolate()->stub_cache()->ComputeKeyedStoreElement( |
| 1456 receiver_map, strict_mode(), store_mode); | 1438 receiver_map, strict_mode(), store_mode); |
| 1457 } | 1439 } |
| 1458 } | 1440 } |
| 1459 | 1441 |
| 1460 ASSERT(state() != GENERIC); | 1442 ASSERT(state() != GENERIC); |
| 1461 | 1443 |
| 1444 MapHandleList target_receiver_maps; | |
| 1445 GetMapsFromTypes(&target_receiver_maps); | |
| 1446 | |
| 1462 bool map_added = | 1447 bool map_added = |
| 1463 AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map); | 1448 AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map); |
| 1464 | 1449 |
| 1465 if (IsTransitionStoreMode(store_mode)) { | 1450 if (IsTransitionStoreMode(store_mode)) { |
| 1466 Handle<Map> transitioned_receiver_map = | 1451 Handle<Map> transitioned_receiver_map = |
| 1467 ComputeTransitionedMap(receiver, store_mode); | 1452 ComputeTransitionedMap(receiver, store_mode); |
| 1468 map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps, | 1453 map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps, |
| 1469 transitioned_receiver_map); | 1454 transitioned_receiver_map); |
| 1470 } | 1455 } |
| 1471 | 1456 |
| (...skipping 1236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2708 // types must be supported as a result of the miss. | 2693 // types must be supported as a result of the miss. |
| 2709 bool already_monomorphic = stub.IsMonomorphic(); | 2694 bool already_monomorphic = stub.IsMonomorphic(); |
| 2710 | 2695 |
| 2711 stub.UpdateStatus(object); | 2696 stub.UpdateStatus(object); |
| 2712 | 2697 |
| 2713 NilValue nil = stub.GetNilValue(); | 2698 NilValue nil = stub.GetNilValue(); |
| 2714 | 2699 |
| 2715 // Find or create the specialized stub to support the new set of types. | 2700 // Find or create the specialized stub to support the new set of types. |
| 2716 Handle<Code> code; | 2701 Handle<Code> code; |
| 2717 if (stub.IsMonomorphic()) { | 2702 if (stub.IsMonomorphic()) { |
| 2718 Handle<Map> monomorphic_map(already_monomorphic | 2703 Handle<Map> monomorphic_map(already_monomorphic && (first_map() != NULL) |
| 2719 ? target()->FindFirstMap() | 2704 ? first_map() |
| 2720 : HeapObject::cast(*object)->map()); | 2705 : HeapObject::cast(*object)->map()); |
| 2721 code = isolate()->stub_cache()->ComputeCompareNil(monomorphic_map, stub); | 2706 code = isolate()->stub_cache()->ComputeCompareNil(monomorphic_map, stub); |
| 2722 } else { | 2707 } else { |
| 2723 code = stub.GetCode(isolate()); | 2708 code = stub.GetCode(isolate()); |
| 2724 } | 2709 } |
| 2725 set_target(*code); | 2710 set_target(*code); |
| 2726 return DoCompareNilSlow(nil, object); | 2711 return DoCompareNilSlow(nil, object); |
| 2727 } | 2712 } |
| 2728 | 2713 |
| 2729 | 2714 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2808 #undef ADDR | 2793 #undef ADDR |
| 2809 }; | 2794 }; |
| 2810 | 2795 |
| 2811 | 2796 |
| 2812 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2797 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 2813 return IC_utilities[id]; | 2798 return IC_utilities[id]; |
| 2814 } | 2799 } |
| 2815 | 2800 |
| 2816 | 2801 |
| 2817 } } // namespace v8::internal | 2802 } } // namespace v8::internal |
| OLD | NEW |