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/field-index-inl.h" | 10 #include "src/field-index-inl.h" |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 // static | 68 // static |
69 PropertyAccessInfo PropertyAccessInfo::NotFound(MapList const& receiver_maps, | 69 PropertyAccessInfo PropertyAccessInfo::NotFound(MapList const& receiver_maps, |
70 MaybeHandle<JSObject> holder) { | 70 MaybeHandle<JSObject> holder) { |
71 return PropertyAccessInfo(holder, receiver_maps); | 71 return PropertyAccessInfo(holder, receiver_maps); |
72 } | 72 } |
73 | 73 |
74 // static | 74 // static |
75 PropertyAccessInfo PropertyAccessInfo::DataConstant( | 75 PropertyAccessInfo PropertyAccessInfo::DataConstant( |
76 MapList const& receiver_maps, Handle<Object> constant, | 76 MapList const& receiver_maps, Handle<Object> constant, |
77 MaybeHandle<JSObject> holder) { | 77 MaybeHandle<JSObject> holder) { |
78 return PropertyAccessInfo(holder, constant, receiver_maps); | 78 return PropertyAccessInfo(kDataConstant, holder, constant, receiver_maps); |
79 } | 79 } |
80 | 80 |
81 // static | 81 // static |
82 PropertyAccessInfo PropertyAccessInfo::DataField( | 82 PropertyAccessInfo PropertyAccessInfo::DataField( |
83 MapList const& receiver_maps, FieldIndex field_index, Type* field_type, | 83 MapList const& receiver_maps, FieldIndex field_index, Type* field_type, |
84 MaybeHandle<JSObject> holder, MaybeHandle<Map> transition_map) { | 84 MaybeHandle<JSObject> holder, MaybeHandle<Map> transition_map) { |
85 return PropertyAccessInfo(holder, transition_map, field_index, field_type, | 85 return PropertyAccessInfo(holder, transition_map, field_index, field_type, |
86 receiver_maps); | 86 receiver_maps); |
87 } | 87 } |
88 | 88 |
| 89 // static |
| 90 PropertyAccessInfo PropertyAccessInfo::AccessorConstant( |
| 91 MapList const& receiver_maps, Handle<Object> constant, |
| 92 MaybeHandle<JSObject> holder) { |
| 93 return PropertyAccessInfo(kAccessorConstant, holder, constant, receiver_maps); |
| 94 } |
| 95 |
89 PropertyAccessInfo::PropertyAccessInfo() | 96 PropertyAccessInfo::PropertyAccessInfo() |
90 : kind_(kInvalid), field_type_(Type::Any()) {} | 97 : kind_(kInvalid), field_type_(Type::Any()) {} |
91 | 98 |
92 PropertyAccessInfo::PropertyAccessInfo(MaybeHandle<JSObject> holder, | 99 PropertyAccessInfo::PropertyAccessInfo(MaybeHandle<JSObject> holder, |
93 MapList const& receiver_maps) | 100 MapList const& receiver_maps) |
94 : kind_(kNotFound), | 101 : kind_(kNotFound), |
95 receiver_maps_(receiver_maps), | 102 receiver_maps_(receiver_maps), |
96 holder_(holder), | 103 holder_(holder), |
97 field_type_(Type::Any()) {} | 104 field_type_(Type::Any()) {} |
98 | 105 |
99 PropertyAccessInfo::PropertyAccessInfo(MaybeHandle<JSObject> holder, | 106 PropertyAccessInfo::PropertyAccessInfo(Kind kind, MaybeHandle<JSObject> holder, |
100 Handle<Object> constant, | 107 Handle<Object> constant, |
101 MapList const& receiver_maps) | 108 MapList const& receiver_maps) |
102 : kind_(kDataConstant), | 109 : kind_(kind), |
103 receiver_maps_(receiver_maps), | 110 receiver_maps_(receiver_maps), |
104 constant_(constant), | 111 constant_(constant), |
105 holder_(holder), | 112 holder_(holder), |
106 field_type_(Type::Any()) {} | 113 field_type_(Type::Any()) {} |
107 | 114 |
108 PropertyAccessInfo::PropertyAccessInfo(MaybeHandle<JSObject> holder, | 115 PropertyAccessInfo::PropertyAccessInfo(MaybeHandle<JSObject> holder, |
109 MaybeHandle<Map> transition_map, | 116 MaybeHandle<Map> transition_map, |
110 FieldIndex field_index, Type* field_type, | 117 FieldIndex field_index, Type* field_type, |
111 MapList const& receiver_maps) | 118 MapList const& receiver_maps) |
112 : kind_(kDataField), | 119 : kind_(kDataField), |
(...skipping 21 matching lines...) Expand all Loading... |
134 this->field_type_->Is(that->field_type_) && | 141 this->field_type_->Is(that->field_type_) && |
135 that->field_type_->Is(this->field_type_)) { | 142 that->field_type_->Is(this->field_type_)) { |
136 this->receiver_maps_.insert(this->receiver_maps_.end(), | 143 this->receiver_maps_.insert(this->receiver_maps_.end(), |
137 that->receiver_maps_.begin(), | 144 that->receiver_maps_.begin(), |
138 that->receiver_maps_.end()); | 145 that->receiver_maps_.end()); |
139 return true; | 146 return true; |
140 } | 147 } |
141 return false; | 148 return false; |
142 } | 149 } |
143 | 150 |
144 case kDataConstant: { | 151 case kDataConstant: |
| 152 case kAccessorConstant: { |
145 // Check if we actually access the same constant. | 153 // Check if we actually access the same constant. |
146 if (this->constant_.address() == that->constant_.address()) { | 154 if (this->constant_.address() == that->constant_.address()) { |
147 this->receiver_maps_.insert(this->receiver_maps_.end(), | 155 this->receiver_maps_.insert(this->receiver_maps_.end(), |
148 that->receiver_maps_.begin(), | 156 that->receiver_maps_.begin(), |
149 that->receiver_maps_.end()); | 157 that->receiver_maps_.end()); |
150 return true; | 158 return true; |
151 } | 159 } |
152 return false; | 160 return false; |
153 } | 161 } |
154 } | 162 } |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
281 return false; | 289 return false; |
282 } | 290 } |
283 // Check for store to data property on a prototype. | 291 // Check for store to data property on a prototype. |
284 if (details.kind() == kData && !holder.is_null()) { | 292 if (details.kind() == kData && !holder.is_null()) { |
285 // Store to property not found on the receiver but on a prototype, we | 293 // Store to property not found on the receiver but on a prototype, we |
286 // need to transition to a new data property. | 294 // need to transition to a new data property. |
287 // Implemented according to ES6 section 9.1.9 [[Set]] (P, V, Receiver) | 295 // Implemented according to ES6 section 9.1.9 [[Set]] (P, V, Receiver) |
288 return LookupTransition(receiver_map, name, holder, access_info); | 296 return LookupTransition(receiver_map, name, holder, access_info); |
289 } | 297 } |
290 } | 298 } |
291 if (details.type() == DATA_CONSTANT) { | 299 switch (details.type()) { |
292 *access_info = PropertyAccessInfo::DataConstant( | 300 case DATA_CONSTANT: { |
293 MapList{receiver_map}, | 301 *access_info = PropertyAccessInfo::DataConstant( |
294 handle(descriptors->GetValue(number), isolate()), holder); | 302 MapList{receiver_map}, |
295 return true; | 303 handle(descriptors->GetValue(number), isolate()), holder); |
296 } else if (details.type() == DATA) { | 304 return true; |
297 int index = descriptors->GetFieldIndex(number); | 305 } |
298 Representation field_representation = details.representation(); | 306 case DATA: { |
299 FieldIndex field_index = FieldIndex::ForPropertyIndex( | 307 int index = descriptors->GetFieldIndex(number); |
300 *map, index, field_representation.IsDouble()); | 308 Representation field_representation = details.representation(); |
301 Type* field_type = Type::Tagged(); | 309 FieldIndex field_index = FieldIndex::ForPropertyIndex( |
302 if (field_representation.IsSmi()) { | 310 *map, index, field_representation.IsDouble()); |
303 field_type = type_cache_.kSmi; | 311 Type* field_type = Type::Tagged(); |
304 } else if (field_representation.IsDouble()) { | 312 if (field_representation.IsSmi()) { |
305 field_type = type_cache_.kFloat64; | 313 field_type = type_cache_.kSmi; |
306 } else if (field_representation.IsHeapObject()) { | 314 } else if (field_representation.IsDouble()) { |
307 // Extract the field type from the property details (make sure its | 315 field_type = type_cache_.kFloat64; |
308 // representation is TaggedPointer to reflect the heap object case). | 316 } else if (field_representation.IsHeapObject()) { |
309 field_type = Type::Intersect( | 317 // Extract the field type from the property details (make sure its |
310 descriptors->GetFieldType(number)->Convert(zone()), | 318 // representation is TaggedPointer to reflect the heap object case). |
311 Type::TaggedPointer(), zone()); | 319 field_type = Type::Intersect( |
312 if (field_type->Is(Type::None())) { | 320 descriptors->GetFieldType(number)->Convert(zone()), |
313 // Store is not safe if the field type was cleared. | 321 Type::TaggedPointer(), zone()); |
314 if (access_mode == AccessMode::kStore) return false; | 322 if (field_type->Is(Type::None())) { |
| 323 // Store is not safe if the field type was cleared. |
| 324 if (access_mode == AccessMode::kStore) return false; |
315 | 325 |
316 // The field type was cleared by the GC, so we don't know anything | 326 // The field type was cleared by the GC, so we don't know anything |
317 // about the contents now. | 327 // about the contents now. |
318 // TODO(bmeurer): It would be awesome to make this saner in the | 328 // TODO(bmeurer): It would be awesome to make this saner in the |
319 // runtime/GC interaction. | 329 // runtime/GC interaction. |
320 field_type = Type::TaggedPointer(); | 330 field_type = Type::TaggedPointer(); |
321 } else if (!Type::Any()->Is(field_type)) { | 331 } else if (!Type::Any()->Is(field_type)) { |
322 // Add proper code dependencies in case of stable field map(s). | 332 // Add proper code dependencies in case of stable field map(s). |
323 Handle<Map> field_owner_map(map->FindFieldOwner(number), isolate()); | 333 Handle<Map> field_owner_map(map->FindFieldOwner(number), |
324 dependencies()->AssumeFieldType(field_owner_map); | 334 isolate()); |
| 335 dependencies()->AssumeFieldType(field_owner_map); |
| 336 } |
| 337 DCHECK(field_type->Is(Type::TaggedPointer())); |
325 } | 338 } |
326 DCHECK(field_type->Is(Type::TaggedPointer())); | 339 *access_info = PropertyAccessInfo::DataField( |
| 340 MapList{receiver_map}, field_index, field_type, holder); |
| 341 return true; |
327 } | 342 } |
328 *access_info = PropertyAccessInfo::DataField( | 343 case ACCESSOR_CONSTANT: { |
329 MapList{receiver_map}, field_index, field_type, holder); | 344 Handle<Object> accessors(descriptors->GetValue(number), isolate()); |
330 return true; | 345 if (!accessors->IsAccessorPair()) return false; |
331 } else { | 346 Handle<Object> accessor( |
332 // TODO(bmeurer): Add support for accessors. | 347 access_mode == AccessMode::kLoad |
333 return false; | 348 ? Handle<AccessorPair>::cast(accessors)->getter() |
| 349 : Handle<AccessorPair>::cast(accessors)->setter(), |
| 350 isolate()); |
| 351 if (!accessor->IsJSFunction()) { |
| 352 // TODO(turbofan): Add support for API accessors. |
| 353 return false; |
| 354 } |
| 355 *access_info = PropertyAccessInfo::AccessorConstant( |
| 356 MapList{receiver_map}, accessor, holder); |
| 357 return true; |
| 358 } |
| 359 case ACCESSOR: { |
| 360 // TODO(turbofan): Add support for general accessors? |
| 361 return false; |
| 362 } |
334 } | 363 } |
| 364 UNREACHABLE(); |
| 365 return false; |
335 } | 366 } |
336 | 367 |
337 // Don't search on the prototype chain for special indices in case of | 368 // Don't search on the prototype chain for special indices in case of |
338 // integer indexed exotic objects (see ES6 section 9.4.5). | 369 // integer indexed exotic objects (see ES6 section 9.4.5). |
339 if (map->IsJSTypedArrayMap() && name->IsString() && | 370 if (map->IsJSTypedArrayMap() && name->IsString() && |
340 IsSpecialIndex(isolate()->unicode_cache(), String::cast(*name))) { | 371 IsSpecialIndex(isolate()->unicode_cache(), String::cast(*name))) { |
341 return false; | 372 return false; |
342 } | 373 } |
343 | 374 |
344 // Don't lookup private symbols on the prototype chain. | 375 // Don't lookup private symbols on the prototype chain. |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
490 } | 521 } |
491 return false; | 522 return false; |
492 } | 523 } |
493 | 524 |
494 | 525 |
495 Factory* AccessInfoFactory::factory() const { return isolate()->factory(); } | 526 Factory* AccessInfoFactory::factory() const { return isolate()->factory(); } |
496 | 527 |
497 } // namespace compiler | 528 } // namespace compiler |
498 } // namespace internal | 529 } // namespace internal |
499 } // namespace v8 | 530 } // namespace v8 |
OLD | NEW |