| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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 <ostream> | 5 #include <ostream> |
| 6 | 6 |
| 7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
| 8 #include "src/compilation-dependencies.h" | 8 #include "src/compilation-dependencies.h" |
| 9 #include "src/compiler/access-info.h" | 9 #include "src/compiler/access-info.h" |
| 10 #include "src/compiler/type-cache.h" | 10 #include "src/compiler/type-cache.h" |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 // Check if it is safe to inline element access for the {map}. | 199 // Check if it is safe to inline element access for the {map}. |
| 200 if (!CanInlineElementAccess(map)) return false; | 200 if (!CanInlineElementAccess(map)) return false; |
| 201 ElementsKind const elements_kind = map->elements_kind(); | 201 ElementsKind const elements_kind = map->elements_kind(); |
| 202 *access_info = ElementAccessInfo(MapList{map}, elements_kind); | 202 *access_info = ElementAccessInfo(MapList{map}, elements_kind); |
| 203 return true; | 203 return true; |
| 204 } | 204 } |
| 205 | 205 |
| 206 bool AccessInfoFactory::ComputeElementAccessInfos( | 206 bool AccessInfoFactory::ComputeElementAccessInfos( |
| 207 MapHandleList const& maps, AccessMode access_mode, | 207 MapHandleList const& maps, AccessMode access_mode, |
| 208 ZoneVector<ElementAccessInfo>* access_infos) { | 208 ZoneVector<ElementAccessInfo>* access_infos) { |
| 209 if (access_mode == AccessMode::kLoad) { | 209 // For polymorphic loads of similar elements kinds (i.e. all tagged or all |
| 210 // For polymorphic loads of similar elements kinds (i.e. all tagged or all | 210 // double), always use the "worst case" code without a transition. This is |
| 211 // double), always use the "worst case" code without a transition. This is | 211 // much faster than transitioning the elements to the worst case, trading a |
| 212 // much faster than transitioning the elements to the worst case, trading a | 212 // TransitionElementsKind for a CheckMaps, avoiding mutation of the array. |
| 213 // TransitionElementsKind for a CheckMaps, avoiding mutation of the array. | 213 // |
| 214 ElementAccessInfo access_info; | 214 // Similarly, for polymorphic stores of compatible elements kind that |
| 215 if (ConsolidateElementLoad(maps, &access_info)) { | 215 // differ only in holeyness, always use the "holey case" code without a |
| 216 access_infos->push_back(access_info); | 216 // transition. This is beneficial, because CheckMaps can often be optimized |
| 217 return true; | 217 // whereas TransitionElementsKind can block optimizations. And as above, we |
| 218 } | 218 // avoid mutation of the array (we still mutate the array contents). |
| 219 ElementAccessInfo access_info; |
| 220 if (ConsolidateElementAccess(maps, access_mode, &access_info)) { |
| 221 access_infos->push_back(access_info); |
| 222 return true; |
| 219 } | 223 } |
| 220 | 224 |
| 221 // Collect possible transition targets. | 225 // Collect possible transition targets. |
| 222 MapHandleList possible_transition_targets(maps.length()); | 226 MapHandleList possible_transition_targets(maps.length()); |
| 223 for (Handle<Map> map : maps) { | 227 for (Handle<Map> map : maps) { |
| 224 if (Map::TryUpdate(map).ToHandle(&map)) { | 228 if (Map::TryUpdate(map).ToHandle(&map)) { |
| 225 if (CanInlineElementAccess(map) && | 229 if (CanInlineElementAccess(map) && |
| 226 IsFastElementsKind(map->elements_kind()) && | 230 IsFastElementsKind(map->elements_kind()) && |
| 227 GetInitialFastElementsKind() != map->elements_kind()) { | 231 GetInitialFastElementsKind() != map->elements_kind()) { |
| 228 possible_transition_targets.Add(map); | 232 possible_transition_targets.Add(map); |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 468 merged = true; | 472 merged = true; |
| 469 break; | 473 break; |
| 470 } | 474 } |
| 471 } | 475 } |
| 472 if (!merged) access_infos->push_back(access_info); | 476 if (!merged) access_infos->push_back(access_info); |
| 473 } | 477 } |
| 474 } | 478 } |
| 475 return true; | 479 return true; |
| 476 } | 480 } |
| 477 | 481 |
| 478 namespace { | 482 bool AccessInfoFactory::ConsolidateElementAccess( |
| 479 | 483 MapHandleList const& maps, AccessMode access_mode, |
| 480 Maybe<ElementsKind> GeneralizeElementsKind(ElementsKind this_kind, | 484 ElementAccessInfo* access_info) { |
| 481 ElementsKind that_kind) { | |
| 482 if (IsHoleyElementsKind(this_kind)) { | |
| 483 that_kind = GetHoleyElementsKind(that_kind); | |
| 484 } else if (IsHoleyElementsKind(that_kind)) { | |
| 485 this_kind = GetHoleyElementsKind(this_kind); | |
| 486 } | |
| 487 if (this_kind == that_kind) return Just(this_kind); | |
| 488 if (IsFastDoubleElementsKind(that_kind) == | |
| 489 IsFastDoubleElementsKind(this_kind)) { | |
| 490 if (IsMoreGeneralElementsKindTransition(that_kind, this_kind)) { | |
| 491 return Just(this_kind); | |
| 492 } | |
| 493 if (IsMoreGeneralElementsKindTransition(this_kind, that_kind)) { | |
| 494 return Just(that_kind); | |
| 495 } | |
| 496 } | |
| 497 return Nothing<ElementsKind>(); | |
| 498 } | |
| 499 | |
| 500 } // namespace | |
| 501 | |
| 502 bool AccessInfoFactory::ConsolidateElementLoad(MapHandleList const& maps, | |
| 503 ElementAccessInfo* access_info) { | |
| 504 if (maps.is_empty()) return false; | 485 if (maps.is_empty()) return false; |
| 505 InstanceType instance_type = maps.first()->instance_type(); | 486 InstanceType instance_type = maps.first()->instance_type(); |
| 506 ElementsKind elements_kind = maps.first()->elements_kind(); | 487 ElementsKind elements_kind = maps.first()->elements_kind(); |
| 507 MapList receiver_maps(maps.length()); | 488 MapList receiver_maps(maps.length()); |
| 508 for (int i = 0; i < maps.length(); ++i) { | 489 for (int i = 0; i < maps.length(); ++i) { |
| 509 Handle<Map> map = maps[i]; | 490 Handle<Map> map = maps[i]; |
| 510 if (!CanInlineElementAccess(map) || map->instance_type() != instance_type) { | 491 if (!CanInlineElementAccess(map) || map->instance_type() != instance_type) { |
| 511 return false; | 492 return false; |
| 512 } | 493 } |
| 513 if (!GeneralizeElementsKind(elements_kind, map->elements_kind()) | 494 ElementsKind other_kind = map->elements_kind(); |
| 514 .To(&elements_kind)) { | 495 if (IsHoleyElementsKind(elements_kind)) { |
| 515 return false; | 496 other_kind = GetHoleyElementsKind(other_kind); |
| 497 } else if (IsHoleyElementsKind(other_kind)) { |
| 498 elements_kind = GetHoleyElementsKind(elements_kind); |
| 499 } |
| 500 if (elements_kind != other_kind) { |
| 501 if (access_mode != AccessMode::kLoad) return false; |
| 502 if (IsFastDoubleElementsKind(elements_kind) != |
| 503 IsFastDoubleElementsKind(other_kind)) { |
| 504 return false; |
| 505 } |
| 506 if (IsMoreGeneralElementsKindTransition(elements_kind, other_kind)) { |
| 507 elements_kind = other_kind; |
| 508 } else if (!IsMoreGeneralElementsKindTransition(other_kind, |
| 509 elements_kind)) { |
| 510 return false; |
| 511 } |
| 516 } | 512 } |
| 517 receiver_maps[i] = map; | 513 receiver_maps[i] = map; |
| 518 } | 514 } |
| 519 *access_info = ElementAccessInfo(receiver_maps, elements_kind); | 515 *access_info = ElementAccessInfo(receiver_maps, elements_kind); |
| 520 return true; | 516 return true; |
| 521 } | 517 } |
| 522 | 518 |
| 523 bool AccessInfoFactory::LookupSpecialFieldAccessor( | 519 bool AccessInfoFactory::LookupSpecialFieldAccessor( |
| 524 Handle<Map> map, Handle<Name> name, PropertyAccessInfo* access_info) { | 520 Handle<Map> map, Handle<Name> name, PropertyAccessInfo* access_info) { |
| 525 // Check for special JSObject field accessors. | 521 // Check for special JSObject field accessors. |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 617 } | 613 } |
| 618 return false; | 614 return false; |
| 619 } | 615 } |
| 620 | 616 |
| 621 | 617 |
| 622 Factory* AccessInfoFactory::factory() const { return isolate()->factory(); } | 618 Factory* AccessInfoFactory::factory() const { return isolate()->factory(); } |
| 623 | 619 |
| 624 } // namespace compiler | 620 } // namespace compiler |
| 625 } // namespace internal | 621 } // namespace internal |
| 626 } // namespace v8 | 622 } // namespace v8 |
| OLD | NEW |