Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(252)

Side by Side Diff: src/compiler/access-info.cc

Issue 2290233002: [turbofan] Introduce MachineRepresentation to PropertyAccessInfo. (Closed)
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698