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

Side by Side Diff: src/ic/keyed-store-generic.cc

Issue 2504403005: [stubs] KeyedStoreGeneric: inline dictionary property stores (Closed)
Patch Set: addressed comments Created 4 years 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/ic/accessor-assembler.cc ('k') | src/objects.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 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 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/ic/keyed-store-generic.h" 5 #include "src/ic/keyed-store-generic.h"
6 6
7 #include "src/code-factory.h"
7 #include "src/code-stub-assembler.h" 8 #include "src/code-stub-assembler.h"
8 #include "src/contexts.h" 9 #include "src/contexts.h"
9 #include "src/ic/accessor-assembler-impl.h" 10 #include "src/ic/accessor-assembler-impl.h"
10 #include "src/interface-descriptors.h" 11 #include "src/interface-descriptors.h"
11 #include "src/isolate.h" 12 #include "src/isolate.h"
12 13
13 namespace v8 { 14 namespace v8 {
14 namespace internal { 15 namespace internal {
15 16
16 using compiler::Node; 17 using compiler::Node;
(...skipping 10 matching lines...) Expand all
27 kDontChangeLength, 28 kDontChangeLength,
28 kIncrementLengthByOne, 29 kIncrementLengthByOne,
29 kBumpLengthWithGap 30 kBumpLengthWithGap
30 }; 31 };
31 32
32 void EmitGenericElementStore(Node* receiver, Node* receiver_map, 33 void EmitGenericElementStore(Node* receiver, Node* receiver_map,
33 Node* instance_type, Node* intptr_index, 34 Node* instance_type, Node* intptr_index,
34 Node* value, Node* context, Label* slow); 35 Node* value, Node* context, Label* slow);
35 36
36 void EmitGenericPropertyStore(Node* receiver, Node* receiver_map, 37 void EmitGenericPropertyStore(Node* receiver, Node* receiver_map,
37 const StoreICParameters* p, Label* slow); 38 const StoreICParameters* p, Label* slow,
39 LanguageMode language_mode);
38 40
39 void BranchIfPrototypesHaveNonFastElements(Node* receiver_map, 41 void BranchIfPrototypesHaveNonFastElements(Node* receiver_map,
40 Label* non_fast_elements, 42 Label* non_fast_elements,
41 Label* only_fast_elements); 43 Label* only_fast_elements);
42 44
43 void TryRewriteElements(Node* receiver, Node* receiver_map, Node* elements, 45 void TryRewriteElements(Node* receiver, Node* receiver_map, Node* elements,
44 Node* native_context, ElementsKind from_kind, 46 Node* native_context, ElementsKind from_kind,
45 ElementsKind to_kind, Label* bailout); 47 ElementsKind to_kind, Label* bailout);
46 48
47 void StoreElementWithCapacity(Node* receiver, Node* receiver_map, 49 void StoreElementWithCapacity(Node* receiver, Node* receiver_map,
48 Node* elements, Node* elements_kind, 50 Node* elements, Node* elements_kind,
49 Node* intptr_index, Node* value, Node* context, 51 Node* intptr_index, Node* value, Node* context,
50 Label* slow, UpdateLength update_length); 52 Label* slow, UpdateLength update_length);
51 53
52 void MaybeUpdateLengthAndReturn(Node* receiver, Node* index, Node* value, 54 void MaybeUpdateLengthAndReturn(Node* receiver, Node* index, Node* value,
53 UpdateLength update_length); 55 UpdateLength update_length);
54 56
55 void TryChangeToHoleyMapHelper(Node* receiver, Node* receiver_map, 57 void TryChangeToHoleyMapHelper(Node* receiver, Node* receiver_map,
56 Node* native_context, ElementsKind packed_kind, 58 Node* native_context, ElementsKind packed_kind,
57 ElementsKind holey_kind, Label* done, 59 ElementsKind holey_kind, Label* done,
58 Label* map_mismatch, Label* bailout); 60 Label* map_mismatch, Label* bailout);
59 void TryChangeToHoleyMap(Node* receiver, Node* receiver_map, 61 void TryChangeToHoleyMap(Node* receiver, Node* receiver_map,
60 Node* current_elements_kind, Node* context, 62 Node* current_elements_kind, Node* context,
61 ElementsKind packed_kind, Label* bailout); 63 ElementsKind packed_kind, Label* bailout);
62 void TryChangeToHoleyMapMulti(Node* receiver, Node* receiver_map, 64 void TryChangeToHoleyMapMulti(Node* receiver, Node* receiver_map,
63 Node* current_elements_kind, Node* context, 65 Node* current_elements_kind, Node* context,
64 ElementsKind packed_kind, 66 ElementsKind packed_kind,
65 ElementsKind packed_kind_2, Label* bailout); 67 ElementsKind packed_kind_2, Label* bailout);
68
69 void JumpIfDataProperty(Node* details, Label* writable, Label* readonly);
70 void LookupPropertyOnPrototypeChain(Node* receiver_map, Node* name,
71 Label* accessor,
72 Variable* var_accessor_pair,
73 Variable* var_accessor_holder,
74 Label* readonly, Label* bailout);
66 }; 75 };
67 76
68 void KeyedStoreGenericGenerator::Generate(compiler::CodeAssemblerState* state, 77 void KeyedStoreGenericGenerator::Generate(compiler::CodeAssemblerState* state,
69 LanguageMode language_mode) { 78 LanguageMode language_mode) {
70 KeyedStoreGenericAssembler assembler(state); 79 KeyedStoreGenericAssembler assembler(state);
71 assembler.KeyedStoreGeneric(language_mode); 80 assembler.KeyedStoreGeneric(language_mode);
72 } 81 }
73 82
74 void KeyedStoreGenericAssembler::BranchIfPrototypesHaveNonFastElements( 83 void KeyedStoreGenericAssembler::BranchIfPrototypesHaveNonFastElements(
75 Node* receiver_map, Label* non_fast_elements, Label* only_fast_elements) { 84 Node* receiver_map, Label* non_fast_elements, Label* only_fast_elements) {
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after
471 } 480 }
472 481
473 Bind(&if_typed_array); 482 Bind(&if_typed_array);
474 { 483 {
475 Comment("Typed array"); 484 Comment("Typed array");
476 // TODO(jkummerow): Support typed arrays. 485 // TODO(jkummerow): Support typed arrays.
477 Goto(slow); 486 Goto(slow);
478 } 487 }
479 } 488 }
480 489
490 void KeyedStoreGenericAssembler::JumpIfDataProperty(Node* details,
491 Label* writable,
492 Label* readonly) {
493 // Accessor properties never have the READ_ONLY attribute set.
494 GotoIf(IsSetWord32(details, PropertyDetails::kAttributesReadOnlyMask),
495 readonly);
496 Node* kind = DecodeWord32<PropertyDetails::KindField>(details);
497 GotoIf(Word32Equal(kind, Int32Constant(kData)), writable);
498 // Fall through if it's an accessor property.
499 }
500
501 void KeyedStoreGenericAssembler::LookupPropertyOnPrototypeChain(
502 Node* receiver_map, Node* name, Label* accessor,
503 Variable* var_accessor_pair, Variable* var_accessor_holder, Label* readonly,
504 Label* bailout) {
505 Label ok_to_write(this);
506 Variable var_holder(this, MachineRepresentation::kTagged);
507 var_holder.Bind(LoadMapPrototype(receiver_map));
508 Variable var_holder_map(this, MachineRepresentation::kTagged);
509 var_holder_map.Bind(LoadMap(var_holder.value()));
510
511 Variable* merged_variables[] = {&var_holder, &var_holder_map};
512 Label loop(this, arraysize(merged_variables), merged_variables);
513 Goto(&loop);
514 Bind(&loop);
515 {
516 Node* holder = var_holder.value();
517 Node* holder_map = var_holder_map.value();
518 Node* instance_type = LoadMapInstanceType(holder_map);
519 Label next_proto(this);
520 {
521 Label found(this), found_fast(this), found_dict(this), found_global(this);
522 Variable var_meta_storage(this, MachineRepresentation::kTagged);
523 Variable var_entry(this, MachineType::PointerRepresentation());
524 TryLookupProperty(holder, holder_map, instance_type, name, &found_fast,
525 &found_dict, &found_global, &var_meta_storage,
526 &var_entry, &next_proto, bailout);
527 Bind(&found_fast);
528 {
529 Node* descriptors = var_meta_storage.value();
530 Node* name_index = var_entry.value();
531 // TODO(jkummerow): Add helper functions for accessing value and
532 // details by entry.
533 const int kNameToDetailsOffset = (DescriptorArray::kDescriptorDetails -
534 DescriptorArray::kDescriptorKey) *
535 kPointerSize;
536 Node* details = LoadAndUntagToWord32FixedArrayElement(
537 descriptors, name_index, kNameToDetailsOffset);
538 JumpIfDataProperty(details, &ok_to_write, readonly);
539
540 // Accessor case.
541 Variable var_details(this, MachineRepresentation::kWord32);
542 LoadPropertyFromFastObject(holder, holder_map, descriptors, name_index,
543 &var_details, var_accessor_pair);
544 var_accessor_holder->Bind(holder);
545 Goto(accessor);
546 }
547
548 Bind(&found_dict);
549 {
550 Node* dictionary = var_meta_storage.value();
551 Node* entry = var_entry.value();
552 const int kNameToDetailsOffset = (NameDictionary::kEntryDetailsIndex -
553 NameDictionary::kEntryKeyIndex) *
554 kPointerSize;
555 Node* details = LoadAndUntagToWord32FixedArrayElement(
556 dictionary, entry, kNameToDetailsOffset);
557 JumpIfDataProperty(details, &ok_to_write, readonly);
558
559 // Accessor case.
560 const int kNameToValueOffset = (NameDictionary::kEntryValueIndex -
561 NameDictionary::kEntryKeyIndex) *
562 kPointerSize;
563 var_accessor_pair->Bind(
564 LoadFixedArrayElement(dictionary, entry, kNameToValueOffset));
565 var_accessor_holder->Bind(holder);
566 Goto(accessor);
567 }
568
569 Bind(&found_global);
570 {
571 Node* dictionary = var_meta_storage.value();
572 Node* entry = var_entry.value();
573 const int kNameToValueOffset = (GlobalDictionary::kEntryValueIndex -
574 GlobalDictionary::kEntryKeyIndex) *
575 kPointerSize;
576
577 Node* property_cell =
578 LoadFixedArrayElement(dictionary, entry, kNameToValueOffset);
579
580 Node* value =
581 LoadObjectField(property_cell, PropertyCell::kValueOffset);
582 GotoIf(WordEqual(value, TheHoleConstant()), &next_proto);
583 Node* details = LoadAndUntagToWord32ObjectField(
584 property_cell, PropertyCell::kDetailsOffset);
585 JumpIfDataProperty(details, &ok_to_write, readonly);
586
587 // Accessor case.
588 var_accessor_pair->Bind(value);
589 var_accessor_holder->Bind(holder);
590 Goto(accessor);
591 }
592 }
593
594 Bind(&next_proto);
595 // Bailout if it can be an integer indexed exotic case.
596 GotoIf(Word32Equal(instance_type, Int32Constant(JS_TYPED_ARRAY_TYPE)),
597 bailout);
598 Node* proto = LoadMapPrototype(holder_map);
599 GotoIf(WordEqual(proto, NullConstant()), &ok_to_write);
600 var_holder.Bind(proto);
601 var_holder_map.Bind(LoadMap(proto));
602 Goto(&loop);
603 }
604 Bind(&ok_to_write);
605 }
606
481 void KeyedStoreGenericAssembler::EmitGenericPropertyStore( 607 void KeyedStoreGenericAssembler::EmitGenericPropertyStore(
482 Node* receiver, Node* receiver_map, const StoreICParameters* p, 608 Node* receiver, Node* receiver_map, const StoreICParameters* p, Label* slow,
483 Label* slow) { 609 LanguageMode language_mode) {
484 Comment("stub cache probe"); 610 Variable var_accessor_pair(this, MachineRepresentation::kTagged);
485 // TODO(jkummerow): Don't rely on the stub cache as much. 611 Variable var_accessor_holder(this, MachineRepresentation::kTagged);
486 // - existing properties can be overwritten inline (unless readonly). 612 Label stub_cache(this), fast_properties(this), dictionary_properties(this),
487 // - for dictionary mode receivers, we can even add properties inline 613 accessor(this), readonly(this);
488 // (unless the prototype chain prevents it). 614 Node* properties = LoadProperties(receiver);
489 Variable var_handler(this, MachineRepresentation::kTagged); 615 Node* properties_map = LoadMap(properties);
490 Label found_handler(this, &var_handler), stub_cache_miss(this); 616 Branch(WordEqual(properties_map, LoadRoot(Heap::kHashTableMapRootIndex)),
491 TryProbeStubCache(isolate()->store_stub_cache(), receiver, p->name, 617 &dictionary_properties, &fast_properties);
492 &found_handler, &var_handler, &stub_cache_miss); 618
493 Bind(&found_handler); 619 Bind(&fast_properties);
494 { 620 {
495 Comment("KeyedStoreGeneric found handler"); 621 // TODO(jkummerow): Does it make sense to support some cases here inline?
496 HandleStoreICHandlerCase(p, var_handler.value(), slow); 622 // Maybe overwrite existing writable properties?
497 } 623 // Maybe support map transitions?
498 Bind(&stub_cache_miss); 624 Goto(&stub_cache);
499 { 625 }
500 Comment("KeyedStoreGeneric_miss"); 626
501 TailCallRuntime(Runtime::kKeyedStoreIC_Miss, p->context, p->value, p->slot, 627 Bind(&dictionary_properties);
502 p->vector, p->receiver, p->name); 628 {
503 } 629 Comment("dictionary property store");
504 } 630 // We checked for LAST_CUSTOM_ELEMENTS_RECEIVER before, which rules out
505 631 // seeing global objects here (which would need special handling).
632
633 Variable var_name_index(this, MachineType::PointerRepresentation());
634 Label dictionary_found(this, &var_name_index), not_found(this);
635 NameDictionaryLookup<NameDictionary>(properties, p->name, &dictionary_found,
636 &var_name_index, &not_found);
637 Bind(&dictionary_found);
638 {
639 Label overwrite(this);
640 const int kNameToDetailsOffset = (NameDictionary::kEntryDetailsIndex -
641 NameDictionary::kEntryKeyIndex) *
642 kPointerSize;
643 Node* details = LoadAndUntagToWord32FixedArrayElement(
644 properties, var_name_index.value(), kNameToDetailsOffset);
645 JumpIfDataProperty(details, &overwrite, &readonly);
646
647 // Accessor case.
648 const int kNameToValueOffset =
649 (NameDictionary::kEntryValueIndex - NameDictionary::kEntryKeyIndex) *
650 kPointerSize;
651 var_accessor_pair.Bind(LoadFixedArrayElement(
652 properties, var_name_index.value(), kNameToValueOffset));
653 var_accessor_holder.Bind(receiver);
654 Goto(&accessor);
655
656 Bind(&overwrite);
657 {
658 StoreFixedArrayElement(properties, var_name_index.value(), p->value,
659 UPDATE_WRITE_BARRIER, kNameToValueOffset,
660 INTPTR_PARAMETERS);
661 Return(p->value);
662 }
663 }
664
665 Bind(&not_found);
666 {
667 LookupPropertyOnPrototypeChain(receiver_map, p->name, &accessor,
668 &var_accessor_pair, &var_accessor_holder,
669 &readonly, slow);
670 Add<NameDictionary>(properties, p->name, p->value, slow);
671 Return(p->value);
672 }
673 }
674
675 Bind(&accessor);
676 {
677 Label not_callable(this);
678 Node* accessor_pair = var_accessor_pair.value();
679 GotoIf(WordEqual(LoadMap(accessor_pair),
680 LoadRoot(Heap::kAccessorPairMapRootIndex)),
Igor Sheludko 2016/11/22 14:07:31 Consider populating HEAP_CONSTANT_LIST to use Go
Jakob Kummerow 2016/11/22 14:20:49 Done.
681 slow);
682 CSA_ASSERT(this, HasInstanceType(accessor_pair, ACCESSOR_PAIR_TYPE));
683 Node* setter = LoadObjectField(accessor_pair, AccessorPair::kSetterOffset);
684 Node* setter_map = LoadMap(setter);
685 // FunctionTemplateInfo setters are not supported yet.
686 GotoIf(WordEqual(setter_map,
687 LoadRoot(Heap::kFunctionTemplateInfoMapRootIndex)),
Igor Sheludko 2016/11/22 14:07:31 Same here.
Jakob Kummerow 2016/11/22 14:20:49 Done.
688 slow);
689 GotoUnless(IsCallableMap(setter_map), &not_callable);
690
691 Callable callable = CodeFactory::Call(isolate());
692 CallJS(callable, p->context, setter, receiver, p->value);
693 Return(p->value);
694
695 Bind(&not_callable);
696 {
697 if (language_mode == STRICT) {
698 Node* message =
699 SmiConstant(Smi::FromInt(MessageTemplate::kNoSetterInCallback));
700 TailCallRuntime(Runtime::kThrowTypeError, p->context, message, p->name,
701 var_accessor_holder.value());
702 } else {
703 DCHECK_EQ(SLOPPY, language_mode);
704 Return(p->value);
705 }
706 }
707 }
708
709 Bind(&readonly);
710 {
711 if (language_mode == STRICT) {
712 Node* message =
713 SmiConstant(Smi::FromInt(MessageTemplate::kStrictReadOnlyProperty));
714 Node* type = Typeof(p->receiver, p->context);
715 TailCallRuntime(Runtime::kThrowTypeError, p->context, message, p->name,
716 type, p->receiver);
717 } else {
718 DCHECK_EQ(SLOPPY, language_mode);
719 Return(p->value);
720 }
721 }
722
723 Bind(&stub_cache);
724 {
725 Comment("stub cache probe");
726 Variable var_handler(this, MachineRepresentation::kTagged);
727 Label found_handler(this, &var_handler), stub_cache_miss(this);
728 TryProbeStubCache(isolate()->store_stub_cache(), receiver, p->name,
729 &found_handler, &var_handler, &stub_cache_miss);
730 Bind(&found_handler);
731 {
732 Comment("KeyedStoreGeneric found handler");
733 HandleStoreICHandlerCase(p, var_handler.value(), slow);
734 }
735 Bind(&stub_cache_miss);
736 {
737 Comment("KeyedStoreGeneric_miss");
738 TailCallRuntime(Runtime::kKeyedStoreIC_Miss, p->context, p->value,
739 p->slot, p->vector, p->receiver, p->name);
740 }
741 }
742 }
743
506 void KeyedStoreGenericAssembler::KeyedStoreGeneric(LanguageMode language_mode) { 744 void KeyedStoreGenericAssembler::KeyedStoreGeneric(LanguageMode language_mode) {
507 typedef StoreWithVectorDescriptor Descriptor; 745 typedef StoreWithVectorDescriptor Descriptor;
508 746
509 Node* receiver = Parameter(Descriptor::kReceiver); 747 Node* receiver = Parameter(Descriptor::kReceiver);
510 Node* name = Parameter(Descriptor::kName); 748 Node* name = Parameter(Descriptor::kName);
511 Node* value = Parameter(Descriptor::kValue); 749 Node* value = Parameter(Descriptor::kValue);
512 Node* slot = Parameter(Descriptor::kSlot); 750 Node* slot = Parameter(Descriptor::kSlot);
513 Node* vector = Parameter(Descriptor::kVector); 751 Node* vector = Parameter(Descriptor::kVector);
514 Node* context = Parameter(Descriptor::kContext); 752 Node* context = Parameter(Descriptor::kContext);
515 753
(...skipping 16 matching lines...) Expand all
532 Comment("integer index"); 770 Comment("integer index");
533 EmitGenericElementStore(receiver, receiver_map, instance_type, 771 EmitGenericElementStore(receiver, receiver_map, instance_type,
534 var_index.value(), value, context, &slow); 772 var_index.value(), value, context, &slow);
535 } 773 }
536 774
537 Bind(&if_unique_name); 775 Bind(&if_unique_name);
538 { 776 {
539 Comment("key is unique name"); 777 Comment("key is unique name");
540 KeyedStoreGenericAssembler::StoreICParameters p(context, receiver, name, 778 KeyedStoreGenericAssembler::StoreICParameters p(context, receiver, name,
541 value, slot, vector); 779 value, slot, vector);
542 EmitGenericPropertyStore(receiver, receiver_map, &p, &slow); 780 EmitGenericPropertyStore(receiver, receiver_map, &p, &slow, language_mode);
543 } 781 }
544 782
545 Bind(&slow); 783 Bind(&slow);
546 { 784 {
547 Comment("KeyedStoreGeneric_slow"); 785 Comment("KeyedStoreGeneric_slow");
548 TailCallRuntime(Runtime::kSetProperty, context, receiver, name, value, 786 TailCallRuntime(Runtime::kSetProperty, context, receiver, name, value,
549 SmiConstant(language_mode)); 787 SmiConstant(language_mode));
550 } 788 }
551 } 789 }
552 790
553 } // namespace internal 791 } // namespace internal
554 } // namespace v8 792 } // namespace v8
OLDNEW
« no previous file with comments | « src/ic/accessor-assembler.cc ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698