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 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
72 | 72 |
73 // static | 73 // static |
74 PropertyAccessInfo PropertyAccessInfo::DataConstant( | 74 PropertyAccessInfo PropertyAccessInfo::DataConstant( |
75 MapList const& receiver_maps, Handle<Object> constant, | 75 MapList const& receiver_maps, Handle<Object> constant, |
76 MaybeHandle<JSObject> holder) { | 76 MaybeHandle<JSObject> holder) { |
77 return PropertyAccessInfo(kDataConstant, holder, constant, receiver_maps); | 77 return PropertyAccessInfo(kDataConstant, holder, constant, receiver_maps); |
78 } | 78 } |
79 | 79 |
80 // static | 80 // static |
81 PropertyAccessInfo PropertyAccessInfo::DataField( | 81 PropertyAccessInfo PropertyAccessInfo::DataField( |
82 MapList const& receiver_maps, FieldIndex field_index, Type* field_type, | 82 MapList const& receiver_maps, FieldIndex field_index, |
| 83 MachineRepresentation field_representation, Type* field_type, |
83 MaybeHandle<JSObject> holder, MaybeHandle<Map> transition_map) { | 84 MaybeHandle<JSObject> holder, MaybeHandle<Map> transition_map) { |
84 return PropertyAccessInfo(holder, transition_map, field_index, field_type, | 85 return PropertyAccessInfo(holder, transition_map, field_index, |
85 receiver_maps); | 86 field_representation, field_type, receiver_maps); |
86 } | 87 } |
87 | 88 |
88 // static | 89 // static |
89 PropertyAccessInfo PropertyAccessInfo::AccessorConstant( | 90 PropertyAccessInfo PropertyAccessInfo::AccessorConstant( |
90 MapList const& receiver_maps, Handle<Object> constant, | 91 MapList const& receiver_maps, Handle<Object> constant, |
91 MaybeHandle<JSObject> holder) { | 92 MaybeHandle<JSObject> holder) { |
92 return PropertyAccessInfo(kAccessorConstant, holder, constant, receiver_maps); | 93 return PropertyAccessInfo(kAccessorConstant, holder, constant, receiver_maps); |
93 } | 94 } |
94 | 95 |
95 PropertyAccessInfo::PropertyAccessInfo() | 96 PropertyAccessInfo::PropertyAccessInfo() |
96 : kind_(kInvalid), field_type_(Type::None()) {} | 97 : kind_(kInvalid), |
| 98 field_representation_(MachineRepresentation::kNone), |
| 99 field_type_(Type::None()) {} |
97 | 100 |
98 PropertyAccessInfo::PropertyAccessInfo(MaybeHandle<JSObject> holder, | 101 PropertyAccessInfo::PropertyAccessInfo(MaybeHandle<JSObject> holder, |
99 MapList const& receiver_maps) | 102 MapList const& receiver_maps) |
100 : kind_(kNotFound), | 103 : kind_(kNotFound), |
101 receiver_maps_(receiver_maps), | 104 receiver_maps_(receiver_maps), |
102 holder_(holder), | 105 holder_(holder), |
| 106 field_representation_(MachineRepresentation::kNone), |
103 field_type_(Type::None()) {} | 107 field_type_(Type::None()) {} |
104 | 108 |
105 PropertyAccessInfo::PropertyAccessInfo(Kind kind, MaybeHandle<JSObject> holder, | 109 PropertyAccessInfo::PropertyAccessInfo(Kind kind, MaybeHandle<JSObject> holder, |
106 Handle<Object> constant, | 110 Handle<Object> constant, |
107 MapList const& receiver_maps) | 111 MapList const& receiver_maps) |
108 : kind_(kind), | 112 : kind_(kind), |
109 receiver_maps_(receiver_maps), | 113 receiver_maps_(receiver_maps), |
110 constant_(constant), | 114 constant_(constant), |
111 holder_(holder), | 115 holder_(holder), |
| 116 field_representation_(MachineRepresentation::kNone), |
112 field_type_(Type::Any()) {} | 117 field_type_(Type::Any()) {} |
113 | 118 |
114 PropertyAccessInfo::PropertyAccessInfo(MaybeHandle<JSObject> holder, | 119 PropertyAccessInfo::PropertyAccessInfo( |
115 MaybeHandle<Map> transition_map, | 120 MaybeHandle<JSObject> holder, MaybeHandle<Map> transition_map, |
116 FieldIndex field_index, Type* field_type, | 121 FieldIndex field_index, MachineRepresentation field_representation, |
117 MapList const& receiver_maps) | 122 Type* field_type, MapList const& receiver_maps) |
118 : kind_(kDataField), | 123 : kind_(kDataField), |
119 receiver_maps_(receiver_maps), | 124 receiver_maps_(receiver_maps), |
120 transition_map_(transition_map), | 125 transition_map_(transition_map), |
121 holder_(holder), | 126 holder_(holder), |
122 field_index_(field_index), | 127 field_index_(field_index), |
| 128 field_representation_(field_representation), |
123 field_type_(field_type) {} | 129 field_type_(field_type) {} |
124 | 130 |
125 bool PropertyAccessInfo::Merge(PropertyAccessInfo const* that) { | 131 bool PropertyAccessInfo::Merge(PropertyAccessInfo const* that) { |
126 if (this->kind_ != that->kind_) return false; | 132 if (this->kind_ != that->kind_) return false; |
127 if (this->holder_.address() != that->holder_.address()) return false; | 133 if (this->holder_.address() != that->holder_.address()) return false; |
128 | 134 |
129 switch (this->kind_) { | 135 switch (this->kind_) { |
130 case kInvalid: | 136 case kInvalid: |
131 break; | 137 break; |
132 | 138 |
133 case kNotFound: | 139 case kNotFound: |
134 return true; | 140 return true; |
135 | 141 |
136 case kDataField: { | 142 case kDataField: { |
137 // Check if we actually access the same field. | 143 // Check if we actually access the same field. |
138 if (this->transition_map_.address() == that->transition_map_.address() && | 144 if (this->transition_map_.address() == that->transition_map_.address() && |
139 this->field_index_ == that->field_index_ && | 145 this->field_index_ == that->field_index_ && |
140 this->field_type_->Is(that->field_type_) && | 146 this->field_type_->Is(that->field_type_) && |
141 that->field_type_->Is(this->field_type_)) { | 147 that->field_type_->Is(this->field_type_) && |
| 148 this->field_representation_ == that->field_representation_) { |
142 this->receiver_maps_.insert(this->receiver_maps_.end(), | 149 this->receiver_maps_.insert(this->receiver_maps_.end(), |
143 that->receiver_maps_.begin(), | 150 that->receiver_maps_.begin(), |
144 that->receiver_maps_.end()); | 151 that->receiver_maps_.end()); |
145 return true; | 152 return true; |
146 } | 153 } |
147 return false; | 154 return false; |
148 } | 155 } |
149 | 156 |
150 case kDataConstant: | 157 case kDataConstant: |
151 case kAccessorConstant: { | 158 case kAccessorConstant: { |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
276 } | 283 } |
277 switch (details.type()) { | 284 switch (details.type()) { |
278 case DATA_CONSTANT: { | 285 case DATA_CONSTANT: { |
279 *access_info = PropertyAccessInfo::DataConstant( | 286 *access_info = PropertyAccessInfo::DataConstant( |
280 MapList{receiver_map}, | 287 MapList{receiver_map}, |
281 handle(descriptors->GetValue(number), isolate()), holder); | 288 handle(descriptors->GetValue(number), isolate()), holder); |
282 return true; | 289 return true; |
283 } | 290 } |
284 case DATA: { | 291 case DATA: { |
285 int index = descriptors->GetFieldIndex(number); | 292 int index = descriptors->GetFieldIndex(number); |
286 Representation field_representation = details.representation(); | 293 Representation details_representation = details.representation(); |
287 FieldIndex field_index = FieldIndex::ForPropertyIndex( | 294 FieldIndex field_index = FieldIndex::ForPropertyIndex( |
288 *map, index, field_representation.IsDouble()); | 295 *map, index, details_representation.IsDouble()); |
289 Type* field_type = Type::Tagged(); | 296 Type* field_type = Type::Tagged(); |
290 if (field_representation.IsSmi()) { | 297 MachineRepresentation field_representation = |
| 298 MachineRepresentation::kTagged; |
| 299 if (details_representation.IsSmi()) { |
291 field_type = type_cache_.kSmi; | 300 field_type = type_cache_.kSmi; |
292 } else if (field_representation.IsDouble()) { | 301 field_representation = MachineRepresentation::kTaggedSigned; |
| 302 } else if (details_representation.IsDouble()) { |
293 field_type = type_cache_.kFloat64; | 303 field_type = type_cache_.kFloat64; |
294 } else if (field_representation.IsHeapObject()) { | 304 field_representation = MachineRepresentation::kFloat64; |
| 305 } else if (details_representation.IsHeapObject()) { |
295 // Extract the field type from the property details (make sure its | 306 // Extract the field type from the property details (make sure its |
296 // representation is TaggedPointer to reflect the heap object case). | 307 // representation is TaggedPointer to reflect the heap object case). |
297 field_type = Type::Intersect( | 308 field_representation = MachineRepresentation::kTaggedPointer; |
298 descriptors->GetFieldType(number)->Convert(zone()), | 309 field_type = descriptors->GetFieldType(number)->Convert(zone()); |
299 Type::TaggedPointer(), zone()); | |
300 if (field_type->Is(Type::None())) { | 310 if (field_type->Is(Type::None())) { |
301 // Store is not safe if the field type was cleared. | 311 // Store is not safe if the field type was cleared. |
302 if (access_mode == AccessMode::kStore) return false; | 312 if (access_mode == AccessMode::kStore) return false; |
303 | 313 |
304 // The field type was cleared by the GC, so we don't know anything | 314 // The field type was cleared by the GC, so we don't know anything |
305 // about the contents now. | 315 // about the contents now. |
306 // TODO(bmeurer): It would be awesome to make this saner in the | 316 // TODO(bmeurer): It would be awesome to make this saner in the |
307 // runtime/GC interaction. | 317 // runtime/GC interaction. |
308 field_type = Type::TaggedPointer(); | 318 field_type = Type::Any(); |
309 } else if (!Type::Any()->Is(field_type)) { | 319 } else if (!Type::Any()->Is(field_type)) { |
310 // Add proper code dependencies in case of stable field map(s). | 320 // Add proper code dependencies in case of stable field map(s). |
| 321 field_representation = MachineRepresentation::kTaggedPointer; |
311 Handle<Map> field_owner_map(map->FindFieldOwner(number), | 322 Handle<Map> field_owner_map(map->FindFieldOwner(number), |
312 isolate()); | 323 isolate()); |
313 dependencies()->AssumeFieldType(field_owner_map); | 324 dependencies()->AssumeFieldType(field_owner_map); |
314 } | 325 } |
315 DCHECK(field_type->Is(Type::TaggedPointer())); | |
316 } | 326 } |
317 *access_info = PropertyAccessInfo::DataField( | 327 *access_info = PropertyAccessInfo::DataField( |
318 MapList{receiver_map}, field_index, field_type, holder); | 328 MapList{receiver_map}, field_index, field_representation, |
| 329 field_type, holder); |
319 return true; | 330 return true; |
320 } | 331 } |
321 case ACCESSOR_CONSTANT: { | 332 case ACCESSOR_CONSTANT: { |
322 Handle<Object> accessors(descriptors->GetValue(number), isolate()); | 333 Handle<Object> accessors(descriptors->GetValue(number), isolate()); |
323 if (!accessors->IsAccessorPair()) return false; | 334 if (!accessors->IsAccessorPair()) return false; |
324 Handle<Object> accessor( | 335 Handle<Object> accessor( |
325 access_mode == AccessMode::kLoad | 336 access_mode == AccessMode::kLoad |
326 ? Handle<AccessorPair>::cast(accessors)->getter() | 337 ? Handle<AccessorPair>::cast(accessors)->getter() |
327 : Handle<AccessorPair>::cast(accessors)->setter(), | 338 : Handle<AccessorPair>::cast(accessors)->setter(), |
328 isolate()); | 339 isolate()); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
415 } | 426 } |
416 | 427 |
417 | 428 |
418 bool AccessInfoFactory::LookupSpecialFieldAccessor( | 429 bool AccessInfoFactory::LookupSpecialFieldAccessor( |
419 Handle<Map> map, Handle<Name> name, PropertyAccessInfo* access_info) { | 430 Handle<Map> map, Handle<Name> name, PropertyAccessInfo* access_info) { |
420 // Check for special JSObject field accessors. | 431 // Check for special JSObject field accessors. |
421 int offset; | 432 int offset; |
422 if (Accessors::IsJSObjectFieldAccessor(map, name, &offset)) { | 433 if (Accessors::IsJSObjectFieldAccessor(map, name, &offset)) { |
423 FieldIndex field_index = FieldIndex::ForInObjectOffset(offset); | 434 FieldIndex field_index = FieldIndex::ForInObjectOffset(offset); |
424 Type* field_type = Type::Tagged(); | 435 Type* field_type = Type::Tagged(); |
| 436 MachineRepresentation field_representation = MachineRepresentation::kTagged; |
425 if (map->IsStringMap()) { | 437 if (map->IsStringMap()) { |
426 DCHECK(Name::Equals(factory()->length_string(), name)); | 438 DCHECK(Name::Equals(factory()->length_string(), name)); |
427 // The String::length property is always a smi in the range | 439 // The String::length property is always a smi in the range |
428 // [0, String::kMaxLength]. | 440 // [0, String::kMaxLength]. |
429 field_type = type_cache_.kStringLengthType; | 441 field_type = type_cache_.kStringLengthType; |
| 442 field_representation = MachineRepresentation::kTaggedSigned; |
430 } else if (map->IsJSArrayMap()) { | 443 } else if (map->IsJSArrayMap()) { |
431 DCHECK(Name::Equals(factory()->length_string(), name)); | 444 DCHECK(Name::Equals(factory()->length_string(), name)); |
432 // The JSArray::length property is a smi in the range | 445 // The JSArray::length property is a smi in the range |
433 // [0, FixedDoubleArray::kMaxLength] in case of fast double | 446 // [0, FixedDoubleArray::kMaxLength] in case of fast double |
434 // elements, a smi in the range [0, FixedArray::kMaxLength] | 447 // elements, a smi in the range [0, FixedArray::kMaxLength] |
435 // in case of other fast elements, and [0, kMaxUInt32] in | 448 // in case of other fast elements, and [0, kMaxUInt32] in |
436 // case of other arrays. | 449 // case of other arrays. |
437 if (IsFastDoubleElementsKind(map->elements_kind())) { | 450 if (IsFastDoubleElementsKind(map->elements_kind())) { |
438 field_type = type_cache_.kFixedDoubleArrayLengthType; | 451 field_type = type_cache_.kFixedDoubleArrayLengthType; |
| 452 field_representation = MachineRepresentation::kTaggedSigned; |
439 } else if (IsFastElementsKind(map->elements_kind())) { | 453 } else if (IsFastElementsKind(map->elements_kind())) { |
440 field_type = type_cache_.kFixedArrayLengthType; | 454 field_type = type_cache_.kFixedArrayLengthType; |
| 455 field_representation = MachineRepresentation::kTaggedSigned; |
441 } else { | 456 } else { |
442 field_type = type_cache_.kJSArrayLengthType; | 457 field_type = type_cache_.kJSArrayLengthType; |
443 } | 458 } |
444 } | 459 } |
445 *access_info = | 460 *access_info = PropertyAccessInfo::DataField( |
446 PropertyAccessInfo::DataField(MapList{map}, field_index, field_type); | 461 MapList{map}, field_index, field_representation, field_type); |
447 return true; | 462 return true; |
448 } | 463 } |
449 return false; | 464 return false; |
450 } | 465 } |
451 | 466 |
452 | 467 |
453 bool AccessInfoFactory::LookupTransition(Handle<Map> map, Handle<Name> name, | 468 bool AccessInfoFactory::LookupTransition(Handle<Map> map, Handle<Name> name, |
454 MaybeHandle<JSObject> holder, | 469 MaybeHandle<JSObject> holder, |
455 PropertyAccessInfo* access_info) { | 470 PropertyAccessInfo* access_info) { |
456 // Check if the {map} has a data transition with the given {name}. | 471 // Check if the {map} has a data transition with the given {name}. |
457 if (map->unused_property_fields() == 0) return false; | 472 if (map->unused_property_fields() == 0) return false; |
458 Handle<Map> transition_map; | 473 Handle<Map> transition_map; |
459 if (TransitionArray::SearchTransition(map, kData, name, NONE) | 474 if (TransitionArray::SearchTransition(map, kData, name, NONE) |
460 .ToHandle(&transition_map)) { | 475 .ToHandle(&transition_map)) { |
461 int const number = transition_map->LastAdded(); | 476 int const number = transition_map->LastAdded(); |
462 PropertyDetails const details = | 477 PropertyDetails const details = |
463 transition_map->instance_descriptors()->GetDetails(number); | 478 transition_map->instance_descriptors()->GetDetails(number); |
464 // Don't bother optimizing stores to read-only properties. | 479 // Don't bother optimizing stores to read-only properties. |
465 if (details.IsReadOnly()) return false; | 480 if (details.IsReadOnly()) return false; |
466 // TODO(bmeurer): Handle transition to data constant? | 481 // TODO(bmeurer): Handle transition to data constant? |
467 if (details.type() != DATA) return false; | 482 if (details.type() != DATA) return false; |
468 int const index = details.field_index(); | 483 int const index = details.field_index(); |
469 Representation field_representation = details.representation(); | 484 Representation details_representation = details.representation(); |
470 FieldIndex field_index = FieldIndex::ForPropertyIndex( | 485 FieldIndex field_index = FieldIndex::ForPropertyIndex( |
471 *transition_map, index, field_representation.IsDouble()); | 486 *transition_map, index, details_representation.IsDouble()); |
472 Type* field_type = Type::Tagged(); | 487 Type* field_type = Type::Tagged(); |
473 if (field_representation.IsSmi()) { | 488 MachineRepresentation field_representation = MachineRepresentation::kTagged; |
| 489 if (details_representation.IsSmi()) { |
474 field_type = type_cache_.kSmi; | 490 field_type = type_cache_.kSmi; |
475 } else if (field_representation.IsDouble()) { | 491 field_representation = MachineRepresentation::kTaggedSigned; |
| 492 } else if (details_representation.IsDouble()) { |
476 field_type = type_cache_.kFloat64; | 493 field_type = type_cache_.kFloat64; |
477 } else if (field_representation.IsHeapObject()) { | 494 field_representation = MachineRepresentation::kFloat64; |
| 495 } else if (details_representation.IsHeapObject()) { |
478 // Extract the field type from the property details (make sure its | 496 // Extract the field type from the property details (make sure its |
479 // representation is TaggedPointer to reflect the heap object case). | 497 // representation is TaggedPointer to reflect the heap object case). |
480 field_type = Type::Intersect( | 498 field_representation = MachineRepresentation::kTaggedPointer; |
| 499 field_type = |
481 transition_map->instance_descriptors()->GetFieldType(number)->Convert( | 500 transition_map->instance_descriptors()->GetFieldType(number)->Convert( |
482 zone()), | 501 zone()); |
483 Type::TaggedPointer(), zone()); | |
484 if (field_type->Is(Type::None())) { | 502 if (field_type->Is(Type::None())) { |
485 // Store is not safe if the field type was cleared. | 503 // Store is not safe if the field type was cleared. |
486 return false; | 504 return false; |
487 } else if (!Type::Any()->Is(field_type)) { | 505 } else if (!Type::Any()->Is(field_type)) { |
488 // Add proper code dependencies in case of stable field map(s). | 506 // Add proper code dependencies in case of stable field map(s). |
489 Handle<Map> field_owner_map(transition_map->FindFieldOwner(number), | 507 Handle<Map> field_owner_map(transition_map->FindFieldOwner(number), |
490 isolate()); | 508 isolate()); |
491 dependencies()->AssumeFieldType(field_owner_map); | 509 dependencies()->AssumeFieldType(field_owner_map); |
492 } | 510 } |
493 DCHECK(field_type->Is(Type::TaggedPointer())); | |
494 } | 511 } |
495 dependencies()->AssumeMapNotDeprecated(transition_map); | 512 dependencies()->AssumeMapNotDeprecated(transition_map); |
496 *access_info = PropertyAccessInfo::DataField( | 513 *access_info = PropertyAccessInfo::DataField( |
497 MapList{map}, field_index, field_type, holder, transition_map); | 514 MapList{map}, field_index, field_representation, field_type, holder, |
| 515 transition_map); |
498 return true; | 516 return true; |
499 } | 517 } |
500 return false; | 518 return false; |
501 } | 519 } |
502 | 520 |
503 | 521 |
504 Factory* AccessInfoFactory::factory() const { return isolate()->factory(); } | 522 Factory* AccessInfoFactory::factory() const { return isolate()->factory(); } |
505 | 523 |
506 } // namespace compiler | 524 } // namespace compiler |
507 } // namespace internal | 525 } // namespace internal |
508 } // namespace v8 | 526 } // namespace v8 |
OLD | NEW |