| Index: src/code-stub-assembler.cc
|
| diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc
|
| index a6f831d935b87423125bc7b4f2993f364ce6058b..97f77e22244d1b043c4cadfe483a075a9425b256 100644
|
| --- a/src/code-stub-assembler.cc
|
| +++ b/src/code-stub-assembler.cc
|
| @@ -1566,9 +1566,6 @@
|
| Node* CodeStubAssembler::AllocateSeqOneByteString(int length,
|
| AllocationFlags flags) {
|
| Comment("AllocateSeqOneByteString");
|
| - if (length == 0) {
|
| - return LoadRoot(Heap::kempty_stringRootIndex);
|
| - }
|
| Node* result = Allocate(SeqOneByteString::SizeFor(length), flags);
|
| DCHECK(Heap::RootIsImmortalImmovable(Heap::kOneByteStringMapRootIndex));
|
| StoreMapNoWriteBarrier(result, Heap::kOneByteStringMapRootIndex);
|
| @@ -1588,10 +1585,8 @@
|
| Variable var_result(this, MachineRepresentation::kTagged);
|
|
|
| // Compute the SeqOneByteString size and check if it fits into new space.
|
| - Label if_lengthiszero(this), if_sizeissmall(this),
|
| - if_notsizeissmall(this, Label::kDeferred), if_join(this);
|
| - GotoIf(WordEqual(length, IntPtrOrSmiConstant(0, mode)), &if_lengthiszero);
|
| -
|
| + Label if_sizeissmall(this), if_notsizeissmall(this, Label::kDeferred),
|
| + if_join(this);
|
| Node* raw_size = GetArrayAllocationSize(
|
| length, UINT8_ELEMENTS, mode,
|
| SeqOneByteString::kHeaderSize + kObjectAlignmentMask);
|
| @@ -1624,12 +1619,6 @@
|
| Goto(&if_join);
|
| }
|
|
|
| - Bind(&if_lengthiszero);
|
| - {
|
| - var_result.Bind(LoadRoot(Heap::kempty_stringRootIndex));
|
| - Goto(&if_join);
|
| - }
|
| -
|
| Bind(&if_join);
|
| return var_result.value();
|
| }
|
| @@ -1637,9 +1626,6 @@
|
| Node* CodeStubAssembler::AllocateSeqTwoByteString(int length,
|
| AllocationFlags flags) {
|
| Comment("AllocateSeqTwoByteString");
|
| - if (length == 0) {
|
| - return LoadRoot(Heap::kempty_stringRootIndex);
|
| - }
|
| Node* result = Allocate(SeqTwoByteString::SizeFor(length), flags);
|
| DCHECK(Heap::RootIsImmortalImmovable(Heap::kStringMapRootIndex));
|
| StoreMapNoWriteBarrier(result, Heap::kStringMapRootIndex);
|
| @@ -1659,10 +1645,8 @@
|
| Variable var_result(this, MachineRepresentation::kTagged);
|
|
|
| // Compute the SeqTwoByteString size and check if it fits into new space.
|
| - Label if_lengthiszero(this), if_sizeissmall(this),
|
| - if_notsizeissmall(this, Label::kDeferred), if_join(this);
|
| - GotoIf(WordEqual(length, IntPtrOrSmiConstant(0, mode)), &if_lengthiszero);
|
| -
|
| + Label if_sizeissmall(this), if_notsizeissmall(this, Label::kDeferred),
|
| + if_join(this);
|
| Node* raw_size = GetArrayAllocationSize(
|
| length, UINT16_ELEMENTS, mode,
|
| SeqOneByteString::kHeaderSize + kObjectAlignmentMask);
|
| @@ -1694,12 +1678,6 @@
|
| CallRuntime(Runtime::kAllocateSeqTwoByteString, context,
|
| mode == SMI_PARAMETERS ? length : SmiFromWord(length));
|
| var_result.Bind(result);
|
| - Goto(&if_join);
|
| - }
|
| -
|
| - Bind(&if_lengthiszero);
|
| - {
|
| - var_result.Bind(LoadRoot(Heap::kempty_stringRootIndex));
|
| Goto(&if_join);
|
| }
|
|
|
| @@ -3013,7 +2991,7 @@
|
| // Translate the {index} into a Word.
|
| index = ParameterToWord(index, parameter_mode);
|
|
|
| - // We may need to loop in case of cons, thin, or sliced strings.
|
| + // We may need to loop in case of cons or sliced strings.
|
| Variable var_index(this, MachineType::PointerRepresentation());
|
| Variable var_result(this, MachineRepresentation::kWord32);
|
| Variable var_string(this, MachineRepresentation::kTagged);
|
| @@ -3165,29 +3143,14 @@
|
|
|
| Bind(&if_stringisnotexternal);
|
| {
|
| - Label if_stringissliced(this), if_stringisthin(this);
|
| - Branch(
|
| - Word32Equal(Word32And(string_instance_type,
|
| - Int32Constant(kStringRepresentationMask)),
|
| - Int32Constant(kSlicedStringTag)),
|
| - &if_stringissliced, &if_stringisthin);
|
| - Bind(&if_stringissliced);
|
| - {
|
| - // The {string} is a SlicedString, continue with its parent.
|
| - Node* string_offset =
|
| - LoadAndUntagObjectField(string, SlicedString::kOffsetOffset);
|
| - Node* string_parent =
|
| - LoadObjectField(string, SlicedString::kParentOffset);
|
| - var_index.Bind(IntPtrAdd(index, string_offset));
|
| - var_string.Bind(string_parent);
|
| - Goto(&loop);
|
| - }
|
| - Bind(&if_stringisthin);
|
| - {
|
| - // The {string} is a ThinString, continue with its actual value.
|
| - var_string.Bind(LoadObjectField(string, ThinString::kActualOffset));
|
| - Goto(&loop);
|
| - }
|
| + // The {string} is a SlicedString, continue with its parent.
|
| + Node* string_offset =
|
| + LoadAndUntagObjectField(string, SlicedString::kOffsetOffset);
|
| + Node* string_parent =
|
| + LoadObjectField(string, SlicedString::kParentOffset);
|
| + var_index.Bind(IntPtrAdd(index, string_offset));
|
| + var_string.Bind(string_parent);
|
| + Goto(&loop);
|
| }
|
| }
|
| }
|
| @@ -3318,13 +3281,11 @@
|
| Label runtime(this);
|
|
|
| Variable var_instance_type(this, MachineRepresentation::kWord32); // Int32.
|
| - Variable var_representation(this, MachineRepresentation::kWord32); // Int32.
|
| Variable var_result(this, MachineRepresentation::kTagged); // String.
|
| Variable var_from(this, MachineRepresentation::kTagged); // Smi.
|
| Variable var_string(this, MachineRepresentation::kTagged); // String.
|
|
|
| var_instance_type.Bind(Int32Constant(0));
|
| - var_representation.Bind(Int32Constant(0));
|
| var_string.Bind(string);
|
| var_from.Bind(from);
|
|
|
| @@ -3365,8 +3326,7 @@
|
| // and put the underlying string into var_string.
|
|
|
| // If the string is not indirect, it can only be sequential or external.
|
| - STATIC_ASSERT(kIsIndirectStringMask ==
|
| - (kSlicedStringTag & kConsStringTag & kThinStringTag));
|
| + STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag));
|
| STATIC_ASSERT(kIsIndirectStringMask != 0);
|
| Label underlying_unpacked(this);
|
| GotoIf(Word32Equal(
|
| @@ -3374,14 +3334,13 @@
|
| Int32Constant(0)),
|
| &underlying_unpacked);
|
|
|
| - // The subject string is a sliced, cons, or thin string.
|
| -
|
| - Label sliced_string(this), thin_or_sliced(this);
|
| - var_representation.Bind(
|
| - Word32And(instance_type, Int32Constant(kStringRepresentationMask)));
|
| - GotoIf(
|
| - Word32NotEqual(var_representation.value(), Int32Constant(kConsStringTag)),
|
| - &thin_or_sliced);
|
| + // The subject string is either a sliced or cons string.
|
| +
|
| + Label sliced_string(this);
|
| + GotoIf(Word32NotEqual(
|
| + Word32And(instance_type, Int32Constant(kSlicedNotConsMask)),
|
| + Int32Constant(0)),
|
| + &sliced_string);
|
|
|
| // Cons string. Check whether it is flat, then fetch first part.
|
| // Flat cons strings have an empty second part.
|
| @@ -3393,33 +3352,14 @@
|
| Node* first_string_part = LoadObjectField(string, ConsString::kFirstOffset);
|
| var_string.Bind(first_string_part);
|
| var_instance_type.Bind(LoadInstanceType(first_string_part));
|
| - var_representation.Bind(Word32And(
|
| - var_instance_type.value(), Int32Constant(kStringRepresentationMask)));
|
| -
|
| - // The loaded first part might be a thin string.
|
| - Branch(Word32Equal(Word32And(var_instance_type.value(),
|
| - Int32Constant(kIsIndirectStringMask)),
|
| - Int32Constant(0)),
|
| - &underlying_unpacked, &thin_or_sliced);
|
| - }
|
| -
|
| - Bind(&thin_or_sliced);
|
| - {
|
| - GotoIf(Word32Equal(var_representation.value(),
|
| - Int32Constant(kSlicedStringTag)),
|
| - &sliced_string);
|
| - Node* actual_string =
|
| - LoadObjectField(var_string.value(), ThinString::kActualOffset);
|
| - var_string.Bind(actual_string);
|
| - var_instance_type.Bind(LoadInstanceType(actual_string));
|
| +
|
| Goto(&underlying_unpacked);
|
| }
|
|
|
| Bind(&sliced_string);
|
| {
|
| // Fetch parent and correct start index by offset.
|
| - Node* sliced_offset =
|
| - LoadObjectField(var_string.value(), SlicedString::kOffsetOffset);
|
| + Node* sliced_offset = LoadObjectField(string, SlicedString::kOffsetOffset);
|
| var_from.Bind(SmiAdd(from, sliced_offset));
|
|
|
| Node* slice_parent = LoadObjectField(string, SlicedString::kParentOffset);
|
| @@ -4192,6 +4132,45 @@
|
| return result.value();
|
| }
|
|
|
| +Node* CodeStubAssembler::FlattenString(Node* string) {
|
| + CSA_ASSERT(this, IsString(string));
|
| + Variable var_result(this, MachineRepresentation::kTagged);
|
| + var_result.Bind(string);
|
| +
|
| + Node* instance_type = LoadInstanceType(string);
|
| +
|
| + // Check if the {string} is not a ConsString (i.e. already flat).
|
| + Label is_cons(this, Label::kDeferred), is_flat_in_cons(this), end(this);
|
| + {
|
| + GotoUnless(Word32Equal(Word32And(instance_type,
|
| + Int32Constant(kStringRepresentationMask)),
|
| + Int32Constant(kConsStringTag)),
|
| + &end);
|
| +
|
| + // Check whether the right hand side is the empty string (i.e. if
|
| + // this is really a flat string in a cons string).
|
| + Node* rhs = LoadObjectField(string, ConsString::kSecondOffset);
|
| + Branch(WordEqual(rhs, EmptyStringConstant()), &is_flat_in_cons, &is_cons);
|
| + }
|
| +
|
| + // Bail out to the runtime.
|
| + Bind(&is_cons);
|
| + {
|
| + var_result.Bind(
|
| + CallRuntime(Runtime::kFlattenString, NoContextConstant(), string));
|
| + Goto(&end);
|
| + }
|
| +
|
| + Bind(&is_flat_in_cons);
|
| + {
|
| + var_result.Bind(LoadObjectField(string, ConsString::kFirstOffset));
|
| + Goto(&end);
|
| + }
|
| +
|
| + Bind(&end);
|
| + return var_result.value();
|
| +}
|
| +
|
| Node* CodeStubAssembler::JSReceiverToPrimitive(Node* context, Node* input) {
|
| Label if_isreceiver(this, Label::kDeferred), if_isnotreceiver(this);
|
| Variable result(this, MachineRepresentation::kTagged);
|
| @@ -4333,19 +4312,17 @@
|
|
|
| void CodeStubAssembler::TryToName(Node* key, Label* if_keyisindex,
|
| Variable* var_index, Label* if_keyisunique,
|
| - Variable* var_unique, Label* if_bailout) {
|
| + Label* if_bailout) {
|
| DCHECK_EQ(MachineType::PointerRepresentation(), var_index->rep());
|
| - DCHECK_EQ(MachineRepresentation::kTagged, var_unique->rep());
|
| Comment("TryToName");
|
|
|
| - Label if_hascachedindex(this), if_keyisnotindex(this), if_thinstring(this);
|
| + Label if_hascachedindex(this), if_keyisnotindex(this);
|
| // Handle Smi and HeapNumber keys.
|
| var_index->Bind(TryToIntptr(key, &if_keyisnotindex));
|
| Goto(if_keyisindex);
|
|
|
| Bind(&if_keyisnotindex);
|
| Node* key_map = LoadMap(key);
|
| - var_unique->Bind(key);
|
| // Symbols are unique.
|
| GotoIf(IsSymbolMap(key_map), if_keyisunique);
|
| Node* key_instance_type = LoadMapInstanceType(key_map);
|
| @@ -4362,21 +4339,11 @@
|
| Node* not_an_index =
|
| Word32And(hash, Int32Constant(Name::kIsNotArrayIndexMask));
|
| GotoIf(Word32Equal(not_an_index, Int32Constant(0)), if_bailout);
|
| - // Check if we have a ThinString.
|
| - GotoIf(Word32Equal(key_instance_type, Int32Constant(THIN_STRING_TYPE)),
|
| - &if_thinstring);
|
| - GotoIf(
|
| - Word32Equal(key_instance_type, Int32Constant(THIN_ONE_BYTE_STRING_TYPE)),
|
| - &if_thinstring);
|
| // Finally, check if |key| is internalized.
|
| STATIC_ASSERT(kNotInternalizedTag != 0);
|
| Node* not_internalized =
|
| Word32And(key_instance_type, Int32Constant(kIsNotInternalizedMask));
|
| GotoIf(Word32NotEqual(not_internalized, Int32Constant(0)), if_bailout);
|
| - Goto(if_keyisunique);
|
| -
|
| - Bind(&if_thinstring);
|
| - var_unique->Bind(LoadObjectField(key, ThinString::kActualOffset));
|
| Goto(if_keyisunique);
|
|
|
| Bind(&if_hascachedindex);
|
| @@ -5228,11 +5195,9 @@
|
| }
|
|
|
| Variable var_index(this, MachineType::PointerRepresentation());
|
| - Variable var_unique(this, MachineRepresentation::kTagged);
|
|
|
| Label if_keyisindex(this), if_iskeyunique(this);
|
| - TryToName(key, &if_keyisindex, &var_index, &if_iskeyunique, &var_unique,
|
| - if_bailout);
|
| + TryToName(key, &if_keyisindex, &var_index, &if_iskeyunique, if_bailout);
|
|
|
| Bind(&if_iskeyunique);
|
| {
|
| @@ -5254,8 +5219,8 @@
|
|
|
| Label next_proto(this);
|
| lookup_property_in_holder(receiver, var_holder.value(), holder_map,
|
| - holder_instance_type, var_unique.value(),
|
| - &next_proto, if_bailout);
|
| + holder_instance_type, key, &next_proto,
|
| + if_bailout);
|
| Bind(&next_proto);
|
|
|
| // Bailout if it can be an integer indexed exotic case.
|
|
|