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/ic/keyed-store-generic.cc

Issue 2528583002: Revert of [stubs] KeyedStoreGeneric: inline dictionary property stores (Closed)
Patch Set: 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"
8 #include "src/code-stub-assembler.h" 7 #include "src/code-stub-assembler.h"
9 #include "src/contexts.h" 8 #include "src/contexts.h"
10 #include "src/ic/accessor-assembler-impl.h" 9 #include "src/ic/accessor-assembler-impl.h"
11 #include "src/interface-descriptors.h" 10 #include "src/interface-descriptors.h"
12 #include "src/isolate.h" 11 #include "src/isolate.h"
13 12
14 namespace v8 { 13 namespace v8 {
15 namespace internal { 14 namespace internal {
16 15
17 using compiler::Node; 16 using compiler::Node;
(...skipping 10 matching lines...) Expand all
28 kDontChangeLength, 27 kDontChangeLength,
29 kIncrementLengthByOne, 28 kIncrementLengthByOne,
30 kBumpLengthWithGap 29 kBumpLengthWithGap
31 }; 30 };
32 31
33 void EmitGenericElementStore(Node* receiver, Node* receiver_map, 32 void EmitGenericElementStore(Node* receiver, Node* receiver_map,
34 Node* instance_type, Node* intptr_index, 33 Node* instance_type, Node* intptr_index,
35 Node* value, Node* context, Label* slow); 34 Node* value, Node* context, Label* slow);
36 35
37 void EmitGenericPropertyStore(Node* receiver, Node* receiver_map, 36 void EmitGenericPropertyStore(Node* receiver, Node* receiver_map,
38 const StoreICParameters* p, Label* slow, 37 const StoreICParameters* p, Label* slow);
39 LanguageMode language_mode);
40 38
41 void BranchIfPrototypesHaveNonFastElements(Node* receiver_map, 39 void BranchIfPrototypesHaveNonFastElements(Node* receiver_map,
42 Label* non_fast_elements, 40 Label* non_fast_elements,
43 Label* only_fast_elements); 41 Label* only_fast_elements);
44 42
45 void TryRewriteElements(Node* receiver, Node* receiver_map, Node* elements, 43 void TryRewriteElements(Node* receiver, Node* receiver_map, Node* elements,
46 Node* native_context, ElementsKind from_kind, 44 Node* native_context, ElementsKind from_kind,
47 ElementsKind to_kind, Label* bailout); 45 ElementsKind to_kind, Label* bailout);
48 46
49 void StoreElementWithCapacity(Node* receiver, Node* receiver_map, 47 void StoreElementWithCapacity(Node* receiver, Node* receiver_map,
50 Node* elements, Node* elements_kind, 48 Node* elements, Node* elements_kind,
51 Node* intptr_index, Node* value, Node* context, 49 Node* intptr_index, Node* value, Node* context,
52 Label* slow, UpdateLength update_length); 50 Label* slow, UpdateLength update_length);
53 51
54 void MaybeUpdateLengthAndReturn(Node* receiver, Node* index, Node* value, 52 void MaybeUpdateLengthAndReturn(Node* receiver, Node* index, Node* value,
55 UpdateLength update_length); 53 UpdateLength update_length);
56 54
57 void TryChangeToHoleyMapHelper(Node* receiver, Node* receiver_map, 55 void TryChangeToHoleyMapHelper(Node* receiver, Node* receiver_map,
58 Node* native_context, ElementsKind packed_kind, 56 Node* native_context, ElementsKind packed_kind,
59 ElementsKind holey_kind, Label* done, 57 ElementsKind holey_kind, Label* done,
60 Label* map_mismatch, Label* bailout); 58 Label* map_mismatch, Label* bailout);
61 void TryChangeToHoleyMap(Node* receiver, Node* receiver_map, 59 void TryChangeToHoleyMap(Node* receiver, Node* receiver_map,
62 Node* current_elements_kind, Node* context, 60 Node* current_elements_kind, Node* context,
63 ElementsKind packed_kind, Label* bailout); 61 ElementsKind packed_kind, Label* bailout);
64 void TryChangeToHoleyMapMulti(Node* receiver, Node* receiver_map, 62 void TryChangeToHoleyMapMulti(Node* receiver, Node* receiver_map,
65 Node* current_elements_kind, Node* context, 63 Node* current_elements_kind, Node* context,
66 ElementsKind packed_kind, 64 ElementsKind packed_kind,
67 ElementsKind packed_kind_2, Label* bailout); 65 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);
75 }; 66 };
76 67
77 void KeyedStoreGenericGenerator::Generate(compiler::CodeAssemblerState* state, 68 void KeyedStoreGenericGenerator::Generate(compiler::CodeAssemblerState* state,
78 LanguageMode language_mode) { 69 LanguageMode language_mode) {
79 KeyedStoreGenericAssembler assembler(state); 70 KeyedStoreGenericAssembler assembler(state);
80 assembler.KeyedStoreGeneric(language_mode); 71 assembler.KeyedStoreGeneric(language_mode);
81 } 72 }
82 73
83 void KeyedStoreGenericAssembler::BranchIfPrototypesHaveNonFastElements( 74 void KeyedStoreGenericAssembler::BranchIfPrototypesHaveNonFastElements(
84 Node* receiver_map, Label* non_fast_elements, Label* only_fast_elements) { 75 Node* receiver_map, Label* non_fast_elements, Label* only_fast_elements) {
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 } 471 }
481 472
482 Bind(&if_typed_array); 473 Bind(&if_typed_array);
483 { 474 {
484 Comment("Typed array"); 475 Comment("Typed array");
485 // TODO(jkummerow): Support typed arrays. 476 // TODO(jkummerow): Support typed arrays.
486 Goto(slow); 477 Goto(slow);
487 } 478 }
488 } 479 }
489 480
490 void KeyedStoreGenericAssembler::JumpIfDataProperty(Node* details, 481 void KeyedStoreGenericAssembler::EmitGenericPropertyStore(
491 Label* writable, 482 Node* receiver, Node* receiver_map, const StoreICParameters* p,
492 Label* readonly) { 483 Label* slow) {
493 // Accessor properties never have the READ_ONLY attribute set. 484 Comment("stub cache probe");
494 GotoIf(IsSetWord32(details, PropertyDetails::kAttributesReadOnlyMask), 485 // TODO(jkummerow): Don't rely on the stub cache as much.
495 readonly); 486 // - existing properties can be overwritten inline (unless readonly).
496 Node* kind = DecodeWord32<PropertyDetails::KindField>(details); 487 // - for dictionary mode receivers, we can even add properties inline
497 GotoIf(Word32Equal(kind, Int32Constant(kData)), writable); 488 // (unless the prototype chain prevents it).
498 // Fall through if it's an accessor property. 489 Variable var_handler(this, MachineRepresentation::kTagged);
499 } 490 Label found_handler(this, &var_handler), stub_cache_miss(this);
500 491 TryProbeStubCache(isolate()->store_stub_cache(), receiver, p->name,
501 void KeyedStoreGenericAssembler::LookupPropertyOnPrototypeChain( 492 &found_handler, &var_handler, &stub_cache_miss);
502 Node* receiver_map, Node* name, Label* accessor, 493 Bind(&found_handler);
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 { 494 {
516 Node* holder = var_holder.value(); 495 Comment("KeyedStoreGeneric found handler");
517 Node* holder_map = var_holder_map.value(); 496 HandleStoreICHandlerCase(p, var_handler.value(), slow);
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 } 497 }
604 Bind(&ok_to_write); 498 Bind(&stub_cache_miss);
605 }
606
607 void KeyedStoreGenericAssembler::EmitGenericPropertyStore(
608 Node* receiver, Node* receiver_map, const StoreICParameters* p, Label* slow,
609 LanguageMode language_mode) {
610 Variable var_accessor_pair(this, MachineRepresentation::kTagged);
611 Variable var_accessor_holder(this, MachineRepresentation::kTagged);
612 Label stub_cache(this), fast_properties(this), dictionary_properties(this),
613 accessor(this), readonly(this);
614 Node* properties = LoadProperties(receiver);
615 Node* properties_map = LoadMap(properties);
616 Branch(WordEqual(properties_map, LoadRoot(Heap::kHashTableMapRootIndex)),
617 &dictionary_properties, &fast_properties);
618
619 Bind(&fast_properties);
620 { 499 {
621 // TODO(jkummerow): Does it make sense to support some cases here inline? 500 Comment("KeyedStoreGeneric_miss");
622 // Maybe overwrite existing writable properties? 501 TailCallRuntime(Runtime::kKeyedStoreIC_Miss, p->context, p->value, p->slot,
623 // Maybe support map transitions? 502 p->vector, p->receiver, p->name);
624 Goto(&stub_cache);
625 }
626
627 Bind(&dictionary_properties);
628 {
629 Comment("dictionary property store");
630 // We checked for LAST_CUSTOM_ELEMENTS_RECEIVER before, which rules out
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(IsAccessorPairMap(LoadMap(accessor_pair)), slow);
680 CSA_ASSERT(this, HasInstanceType(accessor_pair, ACCESSOR_PAIR_TYPE));
681 Node* setter = LoadObjectField(accessor_pair, AccessorPair::kSetterOffset);
682 Node* setter_map = LoadMap(setter);
683 // FunctionTemplateInfo setters are not supported yet.
684 GotoIf(IsFunctionTemplateInfoMap(setter_map), slow);
685 GotoUnless(IsCallableMap(setter_map), &not_callable);
686
687 Callable callable = CodeFactory::Call(isolate());
688 CallJS(callable, p->context, setter, receiver, p->value);
689 Return(p->value);
690
691 Bind(&not_callable);
692 {
693 if (language_mode == STRICT) {
694 Node* message =
695 SmiConstant(Smi::FromInt(MessageTemplate::kNoSetterInCallback));
696 TailCallRuntime(Runtime::kThrowTypeError, p->context, message, p->name,
697 var_accessor_holder.value());
698 } else {
699 DCHECK_EQ(SLOPPY, language_mode);
700 Return(p->value);
701 }
702 }
703 }
704
705 Bind(&readonly);
706 {
707 if (language_mode == STRICT) {
708 Node* message =
709 SmiConstant(Smi::FromInt(MessageTemplate::kStrictReadOnlyProperty));
710 Node* type = Typeof(p->receiver, p->context);
711 TailCallRuntime(Runtime::kThrowTypeError, p->context, message, p->name,
712 type, p->receiver);
713 } else {
714 DCHECK_EQ(SLOPPY, language_mode);
715 Return(p->value);
716 }
717 }
718
719 Bind(&stub_cache);
720 {
721 Comment("stub cache probe");
722 Variable var_handler(this, MachineRepresentation::kTagged);
723 Label found_handler(this, &var_handler), stub_cache_miss(this);
724 TryProbeStubCache(isolate()->store_stub_cache(), receiver, p->name,
725 &found_handler, &var_handler, &stub_cache_miss);
726 Bind(&found_handler);
727 {
728 Comment("KeyedStoreGeneric found handler");
729 HandleStoreICHandlerCase(p, var_handler.value(), slow);
730 }
731 Bind(&stub_cache_miss);
732 {
733 Comment("KeyedStoreGeneric_miss");
734 TailCallRuntime(Runtime::kKeyedStoreIC_Miss, p->context, p->value,
735 p->slot, p->vector, p->receiver, p->name);
736 }
737 } 503 }
738 } 504 }
739 505
740 void KeyedStoreGenericAssembler::KeyedStoreGeneric(LanguageMode language_mode) { 506 void KeyedStoreGenericAssembler::KeyedStoreGeneric(LanguageMode language_mode) {
741 typedef StoreWithVectorDescriptor Descriptor; 507 typedef StoreWithVectorDescriptor Descriptor;
742 508
743 Node* receiver = Parameter(Descriptor::kReceiver); 509 Node* receiver = Parameter(Descriptor::kReceiver);
744 Node* name = Parameter(Descriptor::kName); 510 Node* name = Parameter(Descriptor::kName);
745 Node* value = Parameter(Descriptor::kValue); 511 Node* value = Parameter(Descriptor::kValue);
746 Node* slot = Parameter(Descriptor::kSlot); 512 Node* slot = Parameter(Descriptor::kSlot);
(...skipping 19 matching lines...) Expand all
766 Comment("integer index"); 532 Comment("integer index");
767 EmitGenericElementStore(receiver, receiver_map, instance_type, 533 EmitGenericElementStore(receiver, receiver_map, instance_type,
768 var_index.value(), value, context, &slow); 534 var_index.value(), value, context, &slow);
769 } 535 }
770 536
771 Bind(&if_unique_name); 537 Bind(&if_unique_name);
772 { 538 {
773 Comment("key is unique name"); 539 Comment("key is unique name");
774 KeyedStoreGenericAssembler::StoreICParameters p(context, receiver, name, 540 KeyedStoreGenericAssembler::StoreICParameters p(context, receiver, name,
775 value, slot, vector); 541 value, slot, vector);
776 EmitGenericPropertyStore(receiver, receiver_map, &p, &slow, language_mode); 542 EmitGenericPropertyStore(receiver, receiver_map, &p, &slow);
777 } 543 }
778 544
779 Bind(&slow); 545 Bind(&slow);
780 { 546 {
781 Comment("KeyedStoreGeneric_slow"); 547 Comment("KeyedStoreGeneric_slow");
782 TailCallRuntime(Runtime::kSetProperty, context, receiver, name, value, 548 TailCallRuntime(Runtime::kSetProperty, context, receiver, name, value,
783 SmiConstant(language_mode)); 549 SmiConstant(language_mode));
784 } 550 }
785 } 551 }
786 552
787 } // namespace internal 553 } // namespace internal
788 } // namespace v8 554 } // 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