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 |