| Index: src/builtins/builtins-string.cc
|
| diff --git a/src/builtins/builtins-string.cc b/src/builtins/builtins-string.cc
|
| index f889f60b9606ae8c844909c58d520b4b6d74c6c8..b5cd97bf5fac0e1f41648f3bfafba492f17b28e5 100644
|
| --- a/src/builtins/builtins-string.cc
|
| +++ b/src/builtins/builtins-string.cc
|
| @@ -21,6 +21,40 @@ class StringBuiltinsAssembler : public CodeStubAssembler {
|
| : CodeStubAssembler(state) {}
|
|
|
| protected:
|
| + Node* DirectStringData(Node* string, Node* string_instance_type) {
|
| + // Compute the effective offset of the first character.
|
| + Variable var_data(this, MachineType::PointerRepresentation());
|
| + Label if_sequential(this), if_external(this), if_join(this);
|
| + Branch(Word32Equal(Word32And(string_instance_type,
|
| + Int32Constant(kStringRepresentationMask)),
|
| + Int32Constant(kSeqStringTag)),
|
| + &if_sequential, &if_external);
|
| +
|
| + Bind(&if_sequential);
|
| + {
|
| + var_data.Bind(IntPtrAdd(
|
| + IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag),
|
| + BitcastTaggedToWord(string)));
|
| + Goto(&if_join);
|
| + }
|
| +
|
| + Bind(&if_external);
|
| + {
|
| + // This is only valid for ExternalStrings where the resource data
|
| + // pointer is cached (i.e. no short external strings).
|
| + CSA_ASSERT(this, Word32NotEqual(
|
| + Word32And(string_instance_type,
|
| + Int32Constant(kShortExternalStringMask)),
|
| + Int32Constant(kShortExternalStringTag)));
|
| + var_data.Bind(LoadObjectField(string, ExternalString::kResourceDataOffset,
|
| + MachineType::Pointer()));
|
| + Goto(&if_join);
|
| + }
|
| +
|
| + Bind(&if_join);
|
| + return var_data.value();
|
| + }
|
| +
|
| Node* LoadOneByteChar(Node* string, Node* index) {
|
| return Load(MachineType::Uint8(), string, OneByteCharOffset(index));
|
| }
|
| @@ -155,43 +189,45 @@ void StringBuiltinsAssembler::GenerateStringEqual(ResultMode mode) {
|
| Int32Constant(kBothInternalizedTag)),
|
| &if_notequal);
|
|
|
| - // Check that both {lhs} and {rhs} are flat one-byte strings.
|
| - int const kBothSeqOneByteStringMask =
|
| - kStringEncodingMask | kStringRepresentationMask |
|
| - ((kStringEncodingMask | kStringRepresentationMask) << 8);
|
| - int const kBothSeqOneByteStringTag =
|
| - kOneByteStringTag | kSeqStringTag |
|
| - ((kOneByteStringTag | kSeqStringTag) << 8);
|
| - Label if_bothonebyteseqstrings(this), if_notbothonebyteseqstrings(this);
|
| + // Check that both {lhs} and {rhs} are flat one-byte strings, and that
|
| + // in case of ExternalStrings the data pointer is cached..
|
| + STATIC_ASSERT(kShortExternalStringTag != 0);
|
| + int const kBothDirectOneByteStringMask =
|
| + kStringEncodingMask | kIsIndirectStringMask | kShortExternalStringMask |
|
| + ((kStringEncodingMask | kIsIndirectStringMask | kShortExternalStringMask)
|
| + << 8);
|
| + int const kBothDirectOneByteStringTag =
|
| + kOneByteStringTag | (kOneByteStringTag << 8);
|
| + Label if_bothdirectonebytestrings(this), if_notbothdirectonebytestrings(this);
|
| Branch(Word32Equal(Word32And(both_instance_types,
|
| - Int32Constant(kBothSeqOneByteStringMask)),
|
| - Int32Constant(kBothSeqOneByteStringTag)),
|
| - &if_bothonebyteseqstrings, &if_notbothonebyteseqstrings);
|
| + Int32Constant(kBothDirectOneByteStringMask)),
|
| + Int32Constant(kBothDirectOneByteStringTag)),
|
| + &if_bothdirectonebytestrings, &if_notbothdirectonebytestrings);
|
|
|
| - Bind(&if_bothonebyteseqstrings);
|
| + Bind(&if_bothdirectonebytestrings);
|
| {
|
| // Compute the effective offset of the first character.
|
| - Node* begin =
|
| - IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag);
|
| + Node* lhs_data = DirectStringData(lhs, lhs_instance_type);
|
| + Node* rhs_data = DirectStringData(rhs, rhs_instance_type);
|
|
|
| // Compute the first offset after the string from the length.
|
| - Node* end = IntPtrAdd(begin, SmiUntag(lhs_length));
|
| + Node* length = SmiUntag(lhs_length);
|
|
|
| // Loop over the {lhs} and {rhs} strings to see if they are equal.
|
| Variable var_offset(this, MachineType::PointerRepresentation());
|
| Label loop(this, &var_offset);
|
| - var_offset.Bind(begin);
|
| + var_offset.Bind(IntPtrConstant(0));
|
| Goto(&loop);
|
| Bind(&loop);
|
| {
|
| // If {offset} equals {end}, no difference was found, so the
|
| // strings are equal.
|
| Node* offset = var_offset.value();
|
| - GotoIf(WordEqual(offset, end), &if_equal);
|
| + GotoIf(WordEqual(offset, length), &if_equal);
|
|
|
| // Load the next characters from {lhs} and {rhs}.
|
| - Node* lhs_value = Load(MachineType::Uint8(), lhs, offset);
|
| - Node* rhs_value = Load(MachineType::Uint8(), rhs, offset);
|
| + Node* lhs_value = Load(MachineType::Uint8(), lhs_data, offset);
|
| + Node* rhs_value = Load(MachineType::Uint8(), rhs_data, offset);
|
|
|
| // Check if the characters match.
|
| GotoIf(Word32NotEqual(lhs_value, rhs_value), &if_notequal);
|
| @@ -202,7 +238,7 @@ void StringBuiltinsAssembler::GenerateStringEqual(ResultMode mode) {
|
| }
|
| }
|
|
|
| - Bind(&if_notbothonebyteseqstrings);
|
| + Bind(&if_notbothdirectonebytestrings);
|
| {
|
| // Try to unwrap indirect strings, restart the above attempt on success.
|
| MaybeDerefIndirectStrings(&var_left, lhs_instance_type, &var_right,
|
|
|