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

Side by Side Diff: src/compiler/js-native-context-specialization.cc

Issue 1417503002: [turbofan] Lower access to special JSObject field accessors. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 2 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/js-native-context-specialization.h ('k') | no next file » | 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 "src/compiler/js-native-context-specialization.h" 5 #include "src/compiler/js-native-context-specialization.h"
6 6
7 #include "src/accessors.h"
7 #include "src/compilation-dependencies.h" 8 #include "src/compilation-dependencies.h"
8 #include "src/compiler/access-builder.h" 9 #include "src/compiler/access-builder.h"
9 #include "src/compiler/js-graph.h" 10 #include "src/compiler/js-graph.h"
10 #include "src/compiler/js-operator.h" 11 #include "src/compiler/js-operator.h"
11 #include "src/contexts.h" 12 #include "src/contexts.h"
12 #include "src/field-index-inl.h" 13 #include "src/field-index-inl.h"
13 #include "src/lookup.h" 14 #include "src/lookup.h"
14 #include "src/objects-inl.h" // TODO(mstarzinger): Temporary cycle breaker! 15 #include "src/objects-inl.h" // TODO(mstarzinger): Temporary cycle breaker!
15 #include "src/type-feedback-vector.h" 16 #include "src/type-feedback-vector.h"
16 17
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 public: 243 public:
243 enum Kind { kInvalid, kData, kDataConstant }; 244 enum Kind { kInvalid, kData, kDataConstant };
244 245
245 static PropertyAccessInfo DataConstant(Type* receiver_type, 246 static PropertyAccessInfo DataConstant(Type* receiver_type,
246 Handle<Object> constant, 247 Handle<Object> constant,
247 MaybeHandle<JSObject> holder) { 248 MaybeHandle<JSObject> holder) {
248 return PropertyAccessInfo(holder, constant, receiver_type); 249 return PropertyAccessInfo(holder, constant, receiver_type);
249 } 250 }
250 static PropertyAccessInfo Data(Type* receiver_type, FieldIndex field_index, 251 static PropertyAccessInfo Data(Type* receiver_type, FieldIndex field_index,
251 Representation field_representation, 252 Representation field_representation,
253 Type* field_type,
252 MaybeHandle<JSObject> holder) { 254 MaybeHandle<JSObject> holder) {
253 return PropertyAccessInfo(holder, field_index, field_representation, 255 return PropertyAccessInfo(holder, field_index, field_representation,
254 receiver_type); 256 field_type, receiver_type);
255 } 257 }
256 258
257 PropertyAccessInfo() : kind_(kInvalid) {} 259 PropertyAccessInfo() : kind_(kInvalid) {}
258 PropertyAccessInfo(MaybeHandle<JSObject> holder, Handle<Object> constant, 260 PropertyAccessInfo(MaybeHandle<JSObject> holder, Handle<Object> constant,
259 Type* receiver_type) 261 Type* receiver_type)
260 : kind_(kDataConstant), 262 : kind_(kDataConstant),
261 receiver_type_(receiver_type), 263 receiver_type_(receiver_type),
262 constant_(constant), 264 constant_(constant),
263 holder_(holder) {} 265 holder_(holder) {}
264 PropertyAccessInfo(MaybeHandle<JSObject> holder, FieldIndex field_index, 266 PropertyAccessInfo(MaybeHandle<JSObject> holder, FieldIndex field_index,
265 Representation field_representation, Type* receiver_type) 267 Representation field_representation, Type* field_type,
268 Type* receiver_type)
266 : kind_(kData), 269 : kind_(kData),
267 receiver_type_(receiver_type), 270 receiver_type_(receiver_type),
268 holder_(holder), 271 holder_(holder),
269 field_index_(field_index), 272 field_index_(field_index),
270 field_representation_(field_representation) {} 273 field_representation_(field_representation),
274 field_type_(field_type) {}
271 275
272 bool IsDataConstant() const { return kind() == kDataConstant; } 276 bool IsDataConstant() const { return kind() == kDataConstant; }
273 bool IsData() const { return kind() == kData; } 277 bool IsData() const { return kind() == kData; }
274 278
275 Kind kind() const { return kind_; } 279 Kind kind() const { return kind_; }
276 MaybeHandle<JSObject> holder() const { return holder_; } 280 MaybeHandle<JSObject> holder() const { return holder_; }
277 Handle<Object> constant() const { return constant_; } 281 Handle<Object> constant() const { return constant_; }
278 FieldIndex field_index() const { return field_index_; } 282 FieldIndex field_index() const { return field_index_; }
279 Representation field_representation() const { return field_representation_; } 283 Representation field_representation() const { return field_representation_; }
284 Type* field_type() const { return field_type_; }
280 Type* receiver_type() const { return receiver_type_; } 285 Type* receiver_type() const { return receiver_type_; }
281 286
282 private: 287 private:
283 Kind kind_; 288 Kind kind_;
284 Type* receiver_type_; 289 Type* receiver_type_;
285 Handle<Object> constant_; 290 Handle<Object> constant_;
286 MaybeHandle<JSObject> holder_; 291 MaybeHandle<JSObject> holder_;
287 FieldIndex field_index_; 292 FieldIndex field_index_;
288 Representation field_representation_; 293 Representation field_representation_;
294 Type* field_type_ = Type::Any();
289 }; 295 };
290 296
291 297
292 namespace { 298 namespace {
293 299
294 bool CanInlinePropertyAccess(Handle<Map> map) { 300 bool CanInlinePropertyAccess(Handle<Map> map) {
295 // TODO(bmeurer): Do something about the number stuff. 301 // TODO(bmeurer): Do something about the number stuff.
296 if (map->instance_type() == HEAP_NUMBER_TYPE) return false; 302 if (map->instance_type() == HEAP_NUMBER_TYPE) return false;
297 if (map->instance_type() < FIRST_NONSTRING_TYPE) return true; 303 if (map->instance_type() < FIRST_NONSTRING_TYPE) return true;
298 return map->IsJSObjectMap() && !map->is_dictionary_map() && 304 return map->IsJSObjectMap() && !map->is_dictionary_map() &&
299 !map->has_named_interceptor() && 305 !map->has_named_interceptor() &&
300 // TODO(verwaest): Whitelist contexts to which we have access. 306 // TODO(verwaest): Whitelist contexts to which we have access.
301 !map->is_access_check_needed(); 307 !map->is_access_check_needed();
302 } 308 }
303 309
304 } // namespace 310 } // namespace
305 311
306 312
307 bool JSNativeContextSpecialization::ComputePropertyAccessInfo( 313 bool JSNativeContextSpecialization::ComputePropertyAccessInfo(
308 Handle<Map> map, Handle<Name> name, PropertyAccessInfo* access_info) { 314 Handle<Map> map, Handle<Name> name, PropertyAccessInfo* access_info) {
309 MaybeHandle<JSObject> holder; 315 MaybeHandle<JSObject> holder;
310 Type* receiver_type = Type::Class(map, graph()->zone()); 316 Handle<Map> receiver_map = map;
317 Type* receiver_type = Type::Class(receiver_map, graph()->zone());
311 while (CanInlinePropertyAccess(map)) { 318 while (CanInlinePropertyAccess(map)) {
319 // Check for special JSObject field accessors.
320 int offset;
321 if (Accessors::IsJSObjectFieldAccessor(map, name, &offset)) {
322 FieldIndex field_index = FieldIndex::ForInObjectOffset(offset);
323 Representation field_representation = Representation::Tagged();
324 Type* field_type = Type::Tagged();
325 if (receiver_type->Is(Type::String())) {
326 DCHECK(Name::Equals(factory()->length_string(), name));
327 // The String::length property is always a smi in the range
328 // [0, String::kMaxLength].
329 field_representation = Representation::Smi();
330 field_type = Type::Intersect(
331 Type::Range(0.0, String::kMaxLength, graph()->zone()),
332 Type::TaggedSigned(), graph()->zone());
333 } else if (receiver_map->IsJSArrayMap()) {
334 DCHECK(Name::Equals(factory()->length_string(), name));
335 // The JSArray::length property is a smi in the range
336 // [0, FixedDoubleArray::kMaxLength] in case of fast double
337 // elements, a smi in the range [0, FixedArray::kMaxLength]
338 // in case of other fast elements, and [0, kMaxUInt32-1] in
339 // case of other arrays.
340 double field_type_upper = kMaxUInt32 - 1;
341 if (IsFastElementsKind(receiver_map->elements_kind())) {
342 field_representation = Representation::Smi();
343 field_type_upper =
344 IsFastDoubleElementsKind(receiver_map->elements_kind())
345 ? FixedDoubleArray::kMaxLength
346 : FixedArray::kMaxLength;
347 }
348 field_type =
349 Type::Intersect(Type::Range(0.0, field_type_upper, graph()->zone()),
350 Type::TaggedSigned(), graph()->zone());
351 }
352 *access_info = PropertyAccessInfo::Data(
353 receiver_type, field_index, field_representation, field_type, holder);
354 return true;
355 }
356
312 // Lookup the named property on the {map}. 357 // Lookup the named property on the {map}.
313 Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate()); 358 Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate());
314 int const number = descriptors->SearchWithCache(*name, *map); 359 int const number = descriptors->SearchWithCache(*name, *map);
315 if (number != DescriptorArray::kNotFound) { 360 if (number != DescriptorArray::kNotFound) {
316 PropertyDetails const details = descriptors->GetDetails(number); 361 PropertyDetails const details = descriptors->GetDetails(number);
317 if (details.type() == DATA_CONSTANT) { 362 if (details.type() == DATA_CONSTANT) {
318 *access_info = PropertyAccessInfo::DataConstant( 363 *access_info = PropertyAccessInfo::DataConstant(
319 receiver_type, handle(descriptors->GetValue(number), isolate()), 364 receiver_type, handle(descriptors->GetValue(number), isolate()),
320 holder); 365 holder);
321 return true; 366 return true;
322 } else if (details.type() == DATA) { 367 } else if (details.type() == DATA) {
323 int index = descriptors->GetFieldIndex(number); 368 int index = descriptors->GetFieldIndex(number);
324 Representation field_representation = details.representation(); 369 Representation field_representation = details.representation();
325 FieldIndex field_index = FieldIndex::ForPropertyIndex( 370 FieldIndex field_index = FieldIndex::ForPropertyIndex(
326 *map, index, field_representation.IsDouble()); 371 *map, index, field_representation.IsDouble());
327 *access_info = PropertyAccessInfo::Data(receiver_type, field_index, 372 Type* field_type = Type::Any();
328 field_representation, holder); 373 if (field_representation.IsSmi()) {
374 field_type = Type::Intersect(Type::SignedSmall(),
375 Type::TaggedSigned(), graph()->zone());
376 } else if (field_representation.IsDouble()) {
377 field_type = Type::Intersect(Type::Number(), Type::UntaggedFloat64(),
378 graph()->zone());
379 } else if (field_representation.IsHeapObject()) {
380 field_type = Type::TaggedPointer();
381 }
382 *access_info =
383 PropertyAccessInfo::Data(receiver_type, field_index,
384 field_representation, field_type, holder);
329 return true; 385 return true;
330 } else { 386 } else {
331 // TODO(bmeurer): Add support for accessors. 387 // TODO(bmeurer): Add support for accessors.
332 break; 388 break;
333 } 389 }
334 } 390 }
335 391
336 // Don't search on the prototype chain for special indices in case of 392 // Don't search on the prototype chain for special indices in case of
337 // integer indexed exotic objects (see ES6 section 9.4.5). 393 // integer indexed exotic objects (see ES6 section 9.4.5).
338 if (map->IsJSTypedArrayMap() && name->IsString() && 394 if (map->IsJSTypedArrayMap() && name->IsString() &&
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
503 // Generate the actual property access. 559 // Generate the actual property access.
504 if (access_info.IsDataConstant()) { 560 if (access_info.IsDataConstant()) {
505 this_value = jsgraph()->Constant(access_info.constant()); 561 this_value = jsgraph()->Constant(access_info.constant());
506 } else { 562 } else {
507 // TODO(bmeurer): This is sort of adhoc, and must be refactored into some 563 // TODO(bmeurer): This is sort of adhoc, and must be refactored into some
508 // common code once we also have support for stores. 564 // common code once we also have support for stores.
509 DCHECK(access_info.IsData()); 565 DCHECK(access_info.IsData());
510 FieldIndex const field_index = access_info.field_index(); 566 FieldIndex const field_index = access_info.field_index();
511 Representation const field_representation = 567 Representation const field_representation =
512 access_info.field_representation(); 568 access_info.field_representation();
569 Type* const field_type = access_info.field_type();
513 if (!field_index.is_inobject()) { 570 if (!field_index.is_inobject()) {
514 this_value = this_effect = graph()->NewNode( 571 this_value = this_effect = graph()->NewNode(
515 simplified()->LoadField(AccessBuilder::ForJSObjectProperties()), 572 simplified()->LoadField(AccessBuilder::ForJSObjectProperties()),
516 this_value, this_effect, this_control); 573 this_value, this_effect, this_control);
517 } 574 }
518 FieldAccess field_access; 575 FieldAccess field_access;
519 field_access.base_is_tagged = kTaggedBase; 576 field_access.base_is_tagged = kTaggedBase;
520 field_access.offset = field_index.offset(); 577 field_access.offset = field_index.offset();
521 field_access.name = name; 578 field_access.name = name;
522 field_access.type = Type::Any(); 579 field_access.type = field_type;
523 field_access.machine_type = kMachAnyTagged; 580 field_access.machine_type = kMachAnyTagged;
524 if (field_representation.IsSmi()) { 581 if (field_representation.IsDouble()) {
525 field_access.type = Type::Intersect(
526 Type::SignedSmall(), Type::TaggedSigned(), graph()->zone());
527 } else if (field_representation.IsDouble()) {
528 if (!field_index.is_inobject() || field_index.is_hidden_field() || 582 if (!field_index.is_inobject() || field_index.is_hidden_field() ||
529 !FLAG_unbox_double_fields) { 583 !FLAG_unbox_double_fields) {
530 this_value = this_effect = 584 this_value = this_effect =
531 graph()->NewNode(simplified()->LoadField(field_access), 585 graph()->NewNode(simplified()->LoadField(field_access),
532 this_value, this_effect, this_control); 586 this_value, this_effect, this_control);
533 field_access.offset = HeapNumber::kValueOffset; 587 field_access.offset = HeapNumber::kValueOffset;
534 field_access.name = MaybeHandle<Name>(); 588 field_access.name = MaybeHandle<Name>();
535 } 589 }
536 field_access.type = Type::Intersect(
537 Type::Number(), Type::UntaggedFloat64(), graph()->zone());
538 field_access.machine_type = kMachFloat64; 590 field_access.machine_type = kMachFloat64;
539 } else if (field_representation.IsHeapObject()) {
540 field_access.type = Type::TaggedPointer();
541 } 591 }
542 this_value = this_effect = 592 this_value = this_effect =
543 graph()->NewNode(simplified()->LoadField(field_access), this_value, 593 graph()->NewNode(simplified()->LoadField(field_access), this_value,
544 this_effect, this_control); 594 this_effect, this_control);
545 } 595 }
546 596
547 // Remember the final state for this property access. 597 // Remember the final state for this property access.
548 values.push_back(this_value); 598 values.push_back(this_value);
549 effects.push_back(this_effect); 599 effects.push_back(this_effect);
550 controls.push_back(this_control); 600 controls.push_back(this_control);
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
633 Graph* JSNativeContextSpecialization::graph() const { 683 Graph* JSNativeContextSpecialization::graph() const {
634 return jsgraph()->graph(); 684 return jsgraph()->graph();
635 } 685 }
636 686
637 687
638 Isolate* JSNativeContextSpecialization::isolate() const { 688 Isolate* JSNativeContextSpecialization::isolate() const {
639 return jsgraph()->isolate(); 689 return jsgraph()->isolate();
640 } 690 }
641 691
642 692
693 Factory* JSNativeContextSpecialization::factory() const {
694 return isolate()->factory();
695 }
696
697
643 MachineOperatorBuilder* JSNativeContextSpecialization::machine() const { 698 MachineOperatorBuilder* JSNativeContextSpecialization::machine() const {
644 return jsgraph()->machine(); 699 return jsgraph()->machine();
645 } 700 }
646 701
647 702
648 CommonOperatorBuilder* JSNativeContextSpecialization::common() const { 703 CommonOperatorBuilder* JSNativeContextSpecialization::common() const {
649 return jsgraph()->common(); 704 return jsgraph()->common();
650 } 705 }
651 706
652 707
653 JSOperatorBuilder* JSNativeContextSpecialization::javascript() const { 708 JSOperatorBuilder* JSNativeContextSpecialization::javascript() const {
654 return jsgraph()->javascript(); 709 return jsgraph()->javascript();
655 } 710 }
656 711
657 712
658 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { 713 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const {
659 return jsgraph()->simplified(); 714 return jsgraph()->simplified();
660 } 715 }
661 716
662 } // namespace compiler 717 } // namespace compiler
663 } // namespace internal 718 } // namespace internal
664 } // namespace v8 719 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-native-context-specialization.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698