@@ -622,15 +622,15 @@ static bool UpdateNurseryBuffersOnTransfer(js::Nursery& nursery, JSString* from,
622
622
return true ;
623
623
}
624
624
625
- static bool CanReuseLeftmostBuffer (JSRope* leftmostRope , size_t wholeLength,
625
+ static bool CanReuseLeftmostBuffer (JSString* leftmostChild , size_t wholeLength,
626
626
bool hasTwoByteChars) {
627
- if (!leftmostRope-> leftChild () ->isExtensible ()) {
627
+ if (!leftmostChild ->isExtensible ()) {
628
628
return false ;
629
629
}
630
630
631
- JSExtensibleString& leftmostChild = leftmostRope-> leftChild () ->asExtensible ();
632
- return leftmostChild .capacity () >= wholeLength &&
633
- leftmostChild .hasTwoByteChars () == hasTwoByteChars;
631
+ JSExtensibleString& str = leftmostChild ->asExtensible ();
632
+ return str .capacity () >= wholeLength &&
633
+ str .hasTwoByteChars () == hasTwoByteChars;
634
634
}
635
635
636
636
JSLinearString* JSRope::flatten (JSContext* maybecx) {
@@ -733,49 +733,24 @@ JSLinearString* JSRope::flattenInternal(JSRope* root) {
733
733
while (leftmostRope->leftChild ()->isRope ()) {
734
734
leftmostRope = &leftmostRope->leftChild ()->asRope ();
735
735
}
736
+ JSString* leftmostChild = leftmostRope->leftChild ();
736
737
737
738
bool reuseLeftmostBuffer = CanReuseLeftmostBuffer (
738
- leftmostRope, wholeLength, std::is_same_v<CharT, char16_t >);
739
-
740
- uint32_t leftmostChildLength = 0 ; // Only set if we reuse leftmost buffer.
739
+ leftmostChild, wholeLength, std::is_same_v<CharT, char16_t >);
741
740
742
741
if (reuseLeftmostBuffer) {
743
- JSExtensibleString& left = leftmostRope-> leftChild () ->asExtensible ();
744
- size_t capacity = left.capacity ();
742
+ JSExtensibleString& left = leftmostChild ->asExtensible ();
743
+ wholeCapacity = left.capacity ();
745
744
wholeChars = const_cast <CharT*>(left.nonInlineChars <CharT>(nogc));
746
- wholeCapacity = capacity;
747
745
748
746
// Nursery::registerMallocedBuffer is fallible, so attempt it first before
749
747
// doing anything irreversible.
750
748
if (!UpdateNurseryBuffersOnTransfer (nursery, &left, root, wholeChars,
751
749
wholeCapacity * sizeof (CharT))) {
752
750
return nullptr ;
753
751
}
754
-
755
- ropeBarrierDuringFlattening<usingBarrier>(leftmostRope);
756
- leftmostRope->setNonInlineChars (wholeChars);
757
- leftmostChildLength = left.length ();
758
-
759
- // Remove memory association for left node we're about to make into a
760
- // dependent string.
761
- if (left.isTenured ()) {
762
- RemoveCellMemory (&left, left.allocSize (), MemoryUse::StringContents);
763
- }
764
-
765
- uint32_t flags = INIT_DEPENDENT_FLAGS;
766
- if (left.inStringToAtomCache ()) {
767
- flags |= IN_STRING_TO_ATOM_CACHE;
768
- }
769
- left.setLengthAndFlags (leftmostChildLength,
770
- StringFlagsForCharType<CharT>(flags));
771
- left.d .s .u3 .base = (JSLinearString*)root; /* will be true on exit */
772
- if (left.isTenured () && !root->isTenured ()) {
773
- // leftmost child -> root is a tenured -> nursery edge.
774
- root->storeBuffer ()->putWholeCell (&left);
775
- }
776
752
} else {
777
753
// If we can't reuse the leftmost child's buffer, allocate a new one.
778
-
779
754
if (!AllocChars (root, wholeLength, &wholeChars, &wholeCapacity)) {
780
755
return nullptr ;
781
756
}
@@ -807,19 +782,16 @@ first_visit_node : {
807
782
parent = nullptr ;
808
783
parentFlag = 0 ;
809
784
810
- if (reuseLeftmostBuffer && str == leftmostRope) {
811
- // Left child has already been overwritten.
812
- pos += leftmostChildLength;
813
- goto visit_right_child;
814
- }
815
785
if (left.isRope ()) {
816
786
/* Return to this node when 'left' done, then goto visit_right_child. */
817
787
parent = str;
818
788
parentFlag = FLATTEN_VISIT_RIGHT;
819
789
str = &left;
820
790
goto first_visit_node;
821
791
}
822
- CopyChars (pos, left.asLinear ());
792
+ if (!(reuseLeftmostBuffer && &left == leftmostChild)) {
793
+ CopyChars (pos, left.asLinear ());
794
+ }
823
795
pos += left.length ();
824
796
}
825
797
@@ -881,12 +853,33 @@ finish_node : {
881
853
MOZ_ASSERT (str == root);
882
854
MOZ_ASSERT (pos == wholeChars + wholeLength);
883
855
884
- str->setLengthAndFlags (wholeLength,
885
- StringFlagsForCharType<CharT>(EXTENSIBLE_FLAGS));
886
- str->setNonInlineChars (wholeChars);
887
- str->d .s .u3 .capacity = wholeCapacity;
888
- if (str->isTenured ()) {
889
- AddCellMemory (str, str->asLinear ().allocSize (), MemoryUse::StringContents);
856
+ root->setLengthAndFlags (wholeLength,
857
+ StringFlagsForCharType<CharT>(EXTENSIBLE_FLAGS));
858
+ root->setNonInlineChars (wholeChars);
859
+ root->d .s .u3 .capacity = wholeCapacity;
860
+ if (root->isTenured ()) {
861
+ AddCellMemory (root, root->asLinear ().allocSize (),
862
+ MemoryUse::StringContents);
863
+ }
864
+
865
+ if (reuseLeftmostBuffer) {
866
+ // Remove memory association for left node we're about to make into a
867
+ // dependent string.
868
+ JSString& left = *leftmostChild;
869
+ if (left.isTenured ()) {
870
+ RemoveCellMemory (&left, left.allocSize (), MemoryUse::StringContents);
871
+ }
872
+
873
+ uint32_t flags = INIT_DEPENDENT_FLAGS;
874
+ if (left.inStringToAtomCache ()) {
875
+ flags |= IN_STRING_TO_ATOM_CACHE;
876
+ }
877
+ left.setLengthAndFlags (left.length (), StringFlagsForCharType<CharT>(flags));
878
+ left.d .s .u3 .base = &root->asLinear ();
879
+ if (left.isTenured () && !root->isTenured ()) {
880
+ // leftmost child -> root is a tenured -> nursery edge.
881
+ root->storeBuffer ()->putWholeCell (&left);
882
+ }
890
883
}
891
884
892
885
return &root->asLinear ();
0 commit comments