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