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