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 |