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

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

Issue 2191823002: [turbofan] Refactor the lowering of element/property accesses. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 4 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
« no previous file with comments | « src/compiler/access-info.h ('k') | src/compiler/js-native-context-specialization.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/field-index-inl.h" 10 #include "src/field-index-inl.h"
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 switch (access_mode) { 49 switch (access_mode) {
50 case AccessMode::kLoad: 50 case AccessMode::kLoad:
51 return os << "Load"; 51 return os << "Load";
52 case AccessMode::kStore: 52 case AccessMode::kStore:
53 return os << "Store"; 53 return os << "Store";
54 } 54 }
55 UNREACHABLE(); 55 UNREACHABLE();
56 return os; 56 return os;
57 } 57 }
58 58
59 ElementAccessInfo::ElementAccessInfo() {}
59 60
60 // static 61 ElementAccessInfo::ElementAccessInfo(MapList const& receiver_maps,
61 PropertyAccessInfo PropertyAccessInfo::NotFound(Type* receiver_type,
62 MaybeHandle<JSObject> holder) {
63 return PropertyAccessInfo(holder, receiver_type);
64 }
65
66
67 // static
68 PropertyAccessInfo PropertyAccessInfo::DataConstant(
69 Type* receiver_type, Handle<Object> constant,
70 MaybeHandle<JSObject> holder) {
71 return PropertyAccessInfo(holder, constant, receiver_type);
72 }
73
74
75 // static
76 PropertyAccessInfo PropertyAccessInfo::DataField(
77 Type* receiver_type, FieldIndex field_index, Type* field_type,
78 MaybeHandle<JSObject> holder, MaybeHandle<Map> transition_map) {
79 return PropertyAccessInfo(holder, transition_map, field_index, field_type,
80 receiver_type);
81 }
82
83
84 ElementAccessInfo::ElementAccessInfo() : receiver_type_(Type::None()) {}
85
86
87 ElementAccessInfo::ElementAccessInfo(Type* receiver_type,
88 ElementsKind elements_kind, 62 ElementsKind elements_kind,
89 MaybeHandle<JSObject> holder) 63 MaybeHandle<JSObject> holder)
90 : elements_kind_(elements_kind), 64 : elements_kind_(elements_kind),
91 holder_(holder), 65 holder_(holder),
92 receiver_type_(receiver_type) {} 66 receiver_maps_(receiver_maps) {}
93 67
68 // static
69 PropertyAccessInfo PropertyAccessInfo::NotFound(MapList const& receiver_maps,
70 MaybeHandle<JSObject> holder) {
71 return PropertyAccessInfo(holder, receiver_maps);
72 }
73
74 // static
75 PropertyAccessInfo PropertyAccessInfo::DataConstant(
76 MapList const& receiver_maps, Handle<Object> constant,
77 MaybeHandle<JSObject> holder) {
78 return PropertyAccessInfo(holder, constant, receiver_maps);
79 }
80
81 // static
82 PropertyAccessInfo PropertyAccessInfo::DataField(
83 MapList const& receiver_maps, FieldIndex field_index, Type* field_type,
84 MaybeHandle<JSObject> holder, MaybeHandle<Map> transition_map) {
85 return PropertyAccessInfo(holder, transition_map, field_index, field_type,
86 receiver_maps);
87 }
94 88
95 PropertyAccessInfo::PropertyAccessInfo() 89 PropertyAccessInfo::PropertyAccessInfo()
96 : kind_(kInvalid), receiver_type_(Type::None()), field_type_(Type::Any()) {} 90 : kind_(kInvalid), field_type_(Type::Any()) {}
97
98 91
99 PropertyAccessInfo::PropertyAccessInfo(MaybeHandle<JSObject> holder, 92 PropertyAccessInfo::PropertyAccessInfo(MaybeHandle<JSObject> holder,
100 Type* receiver_type) 93 MapList const& receiver_maps)
101 : kind_(kNotFound), 94 : kind_(kNotFound),
102 receiver_type_(receiver_type), 95 receiver_maps_(receiver_maps),
103 holder_(holder), 96 holder_(holder),
104 field_type_(Type::Any()) {} 97 field_type_(Type::Any()) {}
105 98
106
107 PropertyAccessInfo::PropertyAccessInfo(MaybeHandle<JSObject> holder, 99 PropertyAccessInfo::PropertyAccessInfo(MaybeHandle<JSObject> holder,
108 Handle<Object> constant, 100 Handle<Object> constant,
109 Type* receiver_type) 101 MapList const& receiver_maps)
110 : kind_(kDataConstant), 102 : kind_(kDataConstant),
111 receiver_type_(receiver_type), 103 receiver_maps_(receiver_maps),
112 constant_(constant), 104 constant_(constant),
113 holder_(holder), 105 holder_(holder),
114 field_type_(Type::Any()) {} 106 field_type_(Type::Any()) {}
115 107
116 PropertyAccessInfo::PropertyAccessInfo(MaybeHandle<JSObject> holder, 108 PropertyAccessInfo::PropertyAccessInfo(MaybeHandle<JSObject> holder,
117 MaybeHandle<Map> transition_map, 109 MaybeHandle<Map> transition_map,
118 FieldIndex field_index, Type* field_type, 110 FieldIndex field_index, Type* field_type,
119 Type* receiver_type) 111 MapList const& receiver_maps)
120 : kind_(kDataField), 112 : kind_(kDataField),
121 receiver_type_(receiver_type), 113 receiver_maps_(receiver_maps),
122 transition_map_(transition_map), 114 transition_map_(transition_map),
123 holder_(holder), 115 holder_(holder),
124 field_index_(field_index), 116 field_index_(field_index),
125 field_type_(field_type) {} 117 field_type_(field_type) {}
126 118
119 bool PropertyAccessInfo::Merge(PropertyAccessInfo const* that) {
120 if (this->kind_ != that->kind_) return false;
121 if (this->holder_.address() != that->holder_.address()) return false;
122
123 switch (this->kind_) {
124 case kInvalid:
125 break;
126
127 case kNotFound:
128 return true;
129
130 case kDataField: {
131 // Check if we actually access the same field.
132 if (this->transition_map_.address() == that->transition_map_.address() &&
133 this->field_index_ == that->field_index_ &&
134 this->field_type_->Is(that->field_type_) &&
135 that->field_type_->Is(this->field_type_)) {
136 this->receiver_maps_.insert(this->receiver_maps_.end(),
137 that->receiver_maps_.begin(),
138 that->receiver_maps_.end());
139 return true;
140 }
141 return false;
142 }
143
144 case kDataConstant: {
145 // Check if we actually access the same constant.
146 if (this->constant_.address() == that->constant_.address()) {
147 this->receiver_maps_.insert(this->receiver_maps_.end(),
148 that->receiver_maps_.begin(),
149 that->receiver_maps_.end());
150 return true;
151 }
152 return false;
153 }
154 }
155
156 UNREACHABLE();
157 return false;
158 }
159
127 AccessInfoFactory::AccessInfoFactory(CompilationDependencies* dependencies, 160 AccessInfoFactory::AccessInfoFactory(CompilationDependencies* dependencies,
128 Handle<Context> native_context, Zone* zone) 161 Handle<Context> native_context, Zone* zone)
129 : dependencies_(dependencies), 162 : dependencies_(dependencies),
130 native_context_(native_context), 163 native_context_(native_context),
131 isolate_(native_context->GetIsolate()), 164 isolate_(native_context->GetIsolate()),
132 type_cache_(TypeCache::Get()), 165 type_cache_(TypeCache::Get()),
133 zone_(zone) { 166 zone_(zone) {
134 DCHECK(native_context->IsNativeContext()); 167 DCHECK(native_context->IsNativeContext());
135 } 168 }
136 169
(...skipping 17 matching lines...) Expand all
154 // TODO(bmeurer): We do not currently support unstable prototypes. 187 // TODO(bmeurer): We do not currently support unstable prototypes.
155 // We might want to revisit the way we handle certain keyed stores 188 // We might want to revisit the way we handle certain keyed stores
156 // because this whole prototype chain check is essential a hack, 189 // because this whole prototype chain check is essential a hack,
157 // and I'm not sure that it is correct at all with dictionaries in 190 // and I'm not sure that it is correct at all with dictionaries in
158 // the prototype chain. 191 // the prototype chain.
159 if (!prototype->map()->is_stable()) return false; 192 if (!prototype->map()->is_stable()) return false;
160 holder = Handle<JSObject>::cast(prototype); 193 holder = Handle<JSObject>::cast(prototype);
161 } 194 }
162 } 195 }
163 196
164 *access_info = 197 *access_info = ElementAccessInfo(MapList{map}, elements_kind, holder);
165 ElementAccessInfo(Type::Class(map, zone()), elements_kind, holder);
166 return true; 198 return true;
167 } 199 }
168 200
169 201
170 bool AccessInfoFactory::ComputeElementAccessInfos( 202 bool AccessInfoFactory::ComputeElementAccessInfos(
171 MapHandleList const& maps, AccessMode access_mode, 203 MapHandleList const& maps, AccessMode access_mode,
172 ZoneVector<ElementAccessInfo>* access_infos) { 204 ZoneVector<ElementAccessInfo>* access_infos) {
173 // Collect possible transition targets. 205 // Collect possible transition targets.
174 MapHandleList possible_transition_targets(maps.length()); 206 MapHandleList possible_transition_targets(maps.length());
175 for (Handle<Map> map : maps) { 207 for (Handle<Map> map : maps) {
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 // Check for store to data property on a prototype. 283 // Check for store to data property on a prototype.
252 if (details.kind() == kData && !holder.is_null()) { 284 if (details.kind() == kData && !holder.is_null()) {
253 // Store to property not found on the receiver but on a prototype, we 285 // Store to property not found on the receiver but on a prototype, we
254 // need to transition to a new data property. 286 // need to transition to a new data property.
255 // Implemented according to ES6 section 9.1.9 [[Set]] (P, V, Receiver) 287 // Implemented according to ES6 section 9.1.9 [[Set]] (P, V, Receiver)
256 return LookupTransition(receiver_map, name, holder, access_info); 288 return LookupTransition(receiver_map, name, holder, access_info);
257 } 289 }
258 } 290 }
259 if (details.type() == DATA_CONSTANT) { 291 if (details.type() == DATA_CONSTANT) {
260 *access_info = PropertyAccessInfo::DataConstant( 292 *access_info = PropertyAccessInfo::DataConstant(
261 Type::Class(receiver_map, zone()), 293 MapList{receiver_map},
262 handle(descriptors->GetValue(number), isolate()), holder); 294 handle(descriptors->GetValue(number), isolate()), holder);
263 return true; 295 return true;
264 } else if (details.type() == DATA) { 296 } else if (details.type() == DATA) {
265 int index = descriptors->GetFieldIndex(number); 297 int index = descriptors->GetFieldIndex(number);
266 Representation field_representation = details.representation(); 298 Representation field_representation = details.representation();
267 FieldIndex field_index = FieldIndex::ForPropertyIndex( 299 FieldIndex field_index = FieldIndex::ForPropertyIndex(
268 *map, index, field_representation.IsDouble()); 300 *map, index, field_representation.IsDouble());
269 Type* field_type = Type::Tagged(); 301 Type* field_type = Type::Tagged();
270 if (field_representation.IsSmi()) { 302 if (field_representation.IsSmi()) {
271 field_type = type_cache_.kSmi; 303 field_type = type_cache_.kSmi;
(...skipping 15 matching lines...) Expand all
287 // runtime/GC interaction. 319 // runtime/GC interaction.
288 field_type = Type::TaggedPointer(); 320 field_type = Type::TaggedPointer();
289 } else if (!Type::Any()->Is(field_type)) { 321 } else if (!Type::Any()->Is(field_type)) {
290 // Add proper code dependencies in case of stable field map(s). 322 // Add proper code dependencies in case of stable field map(s).
291 Handle<Map> field_owner_map(map->FindFieldOwner(number), isolate()); 323 Handle<Map> field_owner_map(map->FindFieldOwner(number), isolate());
292 dependencies()->AssumeFieldType(field_owner_map); 324 dependencies()->AssumeFieldType(field_owner_map);
293 } 325 }
294 DCHECK(field_type->Is(Type::TaggedPointer())); 326 DCHECK(field_type->Is(Type::TaggedPointer()));
295 } 327 }
296 *access_info = PropertyAccessInfo::DataField( 328 *access_info = PropertyAccessInfo::DataField(
297 Type::Class(receiver_map, zone()), field_index, field_type, holder); 329 MapList{receiver_map}, field_index, field_type, holder);
298 return true; 330 return true;
299 } else { 331 } else {
300 // TODO(bmeurer): Add support for accessors. 332 // TODO(bmeurer): Add support for accessors.
301 return false; 333 return false;
302 } 334 }
303 } 335 }
304 336
305 // Don't search on the prototype chain for special indices in case of 337 // Don't search on the prototype chain for special indices in case of
306 // integer indexed exotic objects (see ES6 section 9.4.5). 338 // integer indexed exotic objects (see ES6 section 9.4.5).
307 if (map->IsJSTypedArrayMap() && name->IsString() && 339 if (map->IsJSTypedArrayMap() && name->IsString() &&
(...skipping 16 matching lines...) Expand all
324 } else if (map->prototype()->IsNull(isolate())) { 356 } else if (map->prototype()->IsNull(isolate())) {
325 // Store to property not found on the receiver or any prototype, we need 357 // Store to property not found on the receiver or any prototype, we need
326 // to transition to a new data property. 358 // to transition to a new data property.
327 // Implemented according to ES6 section 9.1.9 [[Set]] (P, V, Receiver) 359 // Implemented according to ES6 section 9.1.9 [[Set]] (P, V, Receiver)
328 if (access_mode == AccessMode::kStore) { 360 if (access_mode == AccessMode::kStore) {
329 return LookupTransition(receiver_map, name, holder, access_info); 361 return LookupTransition(receiver_map, name, holder, access_info);
330 } 362 }
331 // The property was not found, return undefined or throw depending 363 // The property was not found, return undefined or throw depending
332 // on the language mode of the load operation. 364 // on the language mode of the load operation.
333 // Implemented according to ES6 section 9.1.8 [[Get]] (P, Receiver) 365 // Implemented according to ES6 section 9.1.8 [[Get]] (P, Receiver)
334 *access_info = PropertyAccessInfo::NotFound( 366 *access_info =
335 Type::Class(receiver_map, zone()), holder); 367 PropertyAccessInfo::NotFound(MapList{receiver_map}, holder);
336 return true; 368 return true;
337 } else { 369 } else {
338 return false; 370 return false;
339 } 371 }
340 } 372 }
341 Handle<JSObject> map_prototype(JSObject::cast(map->prototype()), isolate()); 373 Handle<JSObject> map_prototype(JSObject::cast(map->prototype()), isolate());
342 if (map_prototype->map()->is_deprecated()) { 374 if (map_prototype->map()->is_deprecated()) {
343 // Try to migrate the prototype object so we don't embed the deprecated 375 // Try to migrate the prototype object so we don't embed the deprecated
344 // map into the optimized code. 376 // map into the optimized code.
345 JSObject::TryMigrateInstance(map_prototype); 377 JSObject::TryMigrateInstance(map_prototype);
346 } 378 }
347 map = handle(map_prototype->map(), isolate()); 379 map = handle(map_prototype->map(), isolate());
348 holder = map_prototype; 380 holder = map_prototype;
349 } while (CanInlinePropertyAccess(map)); 381 } while (CanInlinePropertyAccess(map));
350 return false; 382 return false;
351 } 383 }
352 384
353
354 bool AccessInfoFactory::ComputePropertyAccessInfos( 385 bool AccessInfoFactory::ComputePropertyAccessInfos(
355 MapHandleList const& maps, Handle<Name> name, AccessMode access_mode, 386 MapHandleList const& maps, Handle<Name> name, AccessMode access_mode,
356 ZoneVector<PropertyAccessInfo>* access_infos) { 387 ZoneVector<PropertyAccessInfo>* access_infos) {
357 for (Handle<Map> map : maps) { 388 for (Handle<Map> map : maps) {
358 if (Map::TryUpdate(map).ToHandle(&map)) { 389 if (Map::TryUpdate(map).ToHandle(&map)) {
359 PropertyAccessInfo access_info; 390 PropertyAccessInfo access_info;
360 if (!ComputePropertyAccessInfo(map, name, access_mode, &access_info)) { 391 if (!ComputePropertyAccessInfo(map, name, access_mode, &access_info)) {
361 return false; 392 return false;
362 } 393 }
363 access_infos->push_back(access_info); 394 // Try to merge the {access_info} with an existing one.
395 bool merged = false;
396 for (PropertyAccessInfo& other_info : *access_infos) {
397 if (other_info.Merge(&access_info)) {
398 merged = true;
399 break;
400 }
401 }
402 if (!merged) access_infos->push_back(access_info);
364 } 403 }
365 } 404 }
366 return true; 405 return true;
367 } 406 }
368 407
369 408
370 bool AccessInfoFactory::LookupSpecialFieldAccessor( 409 bool AccessInfoFactory::LookupSpecialFieldAccessor(
371 Handle<Map> map, Handle<Name> name, PropertyAccessInfo* access_info) { 410 Handle<Map> map, Handle<Name> name, PropertyAccessInfo* access_info) {
372 // Check for special JSObject field accessors. 411 // Check for special JSObject field accessors.
373 int offset; 412 int offset;
(...skipping 13 matching lines...) Expand all
387 // in case of other fast elements, and [0, kMaxUInt32] in 426 // in case of other fast elements, and [0, kMaxUInt32] in
388 // case of other arrays. 427 // case of other arrays.
389 if (IsFastDoubleElementsKind(map->elements_kind())) { 428 if (IsFastDoubleElementsKind(map->elements_kind())) {
390 field_type = type_cache_.kFixedDoubleArrayLengthType; 429 field_type = type_cache_.kFixedDoubleArrayLengthType;
391 } else if (IsFastElementsKind(map->elements_kind())) { 430 } else if (IsFastElementsKind(map->elements_kind())) {
392 field_type = type_cache_.kFixedArrayLengthType; 431 field_type = type_cache_.kFixedArrayLengthType;
393 } else { 432 } else {
394 field_type = type_cache_.kJSArrayLengthType; 433 field_type = type_cache_.kJSArrayLengthType;
395 } 434 }
396 } 435 }
397 *access_info = PropertyAccessInfo::DataField(Type::Class(map, zone()), 436 *access_info =
398 field_index, field_type); 437 PropertyAccessInfo::DataField(MapList{map}, field_index, field_type);
399 return true; 438 return true;
400 } 439 }
401 return false; 440 return false;
402 } 441 }
403 442
404 443
405 bool AccessInfoFactory::LookupTransition(Handle<Map> map, Handle<Name> name, 444 bool AccessInfoFactory::LookupTransition(Handle<Map> map, Handle<Name> name,
406 MaybeHandle<JSObject> holder, 445 MaybeHandle<JSObject> holder,
407 PropertyAccessInfo* access_info) { 446 PropertyAccessInfo* access_info) {
408 // Check if the {map} has a data transition with the given {name}. 447 // Check if the {map} has a data transition with the given {name}.
(...skipping 29 matching lines...) Expand all
438 return false; 477 return false;
439 } else if (!Type::Any()->Is(field_type)) { 478 } else if (!Type::Any()->Is(field_type)) {
440 // Add proper code dependencies in case of stable field map(s). 479 // Add proper code dependencies in case of stable field map(s).
441 Handle<Map> field_owner_map(transition_map->FindFieldOwner(number), 480 Handle<Map> field_owner_map(transition_map->FindFieldOwner(number),
442 isolate()); 481 isolate());
443 dependencies()->AssumeFieldType(field_owner_map); 482 dependencies()->AssumeFieldType(field_owner_map);
444 } 483 }
445 DCHECK(field_type->Is(Type::TaggedPointer())); 484 DCHECK(field_type->Is(Type::TaggedPointer()));
446 } 485 }
447 dependencies()->AssumeMapNotDeprecated(transition_map); 486 dependencies()->AssumeMapNotDeprecated(transition_map);
448 *access_info = 487 *access_info = PropertyAccessInfo::DataField(
449 PropertyAccessInfo::DataField(Type::Class(map, zone()), field_index, 488 MapList{map}, field_index, field_type, holder, transition_map);
450 field_type, holder, transition_map);
451 return true; 489 return true;
452 } 490 }
453 return false; 491 return false;
454 } 492 }
455 493
456 494
457 Factory* AccessInfoFactory::factory() const { return isolate()->factory(); } 495 Factory* AccessInfoFactory::factory() const { return isolate()->factory(); }
458 496
459 } // namespace compiler 497 } // namespace compiler
460 } // namespace internal 498 } // namespace internal
461 } // namespace v8 499 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/access-info.h ('k') | src/compiler/js-native-context-specialization.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698