[string] Unify String::IsEqualTo

Make String::IsEqualTo use a direct string shape dispatch and a direct
call to CompareChars, rather than splitting the behaviour over
IsOneByte/IsTwoByte/HasOneBytePrefix. Avoiding GetFlatContent will make
this method easier to make efficient while staying string-access-lock
safe.

Also, redefines the sequential string table key's matcher in terms of
this IsEqualTo method.

Change-Id: Iab71246e12044ebaeff06f0dbc14d28b3482dcbe
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2557979
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Auto-Submit: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71378}
This commit is contained in:
Leszek Swirski 2020-11-24 14:21:10 +01:00 committed by Commit Bot
parent 20b417503a
commit 0df6a20899
5 changed files with 85 additions and 76 deletions

View File

@ -81,7 +81,7 @@ bool SourceCodeCache::Lookup(Isolate* isolate, Vector<const char> name,
Handle<SharedFunctionInfo>* handle) {
for (int i = 0; i < cache_.length(); i += 2) {
SeqOneByteString str = SeqOneByteString::cast(cache_.get(i));
if (str.IsOneByteEqualTo(Vector<const uint8_t>::cast(name))) {
if (str.IsOneByteEqualTo(name)) {
*handle = Handle<SharedFunctionInfo>(
SharedFunctionInfo::cast(cache_.get(i + 1)), isolate);
return true;

View File

@ -986,14 +986,7 @@ bool Matches(const Vector<const Char>& chars, Handle<String> string) {
DCHECK(!string.is_null());
if (chars.length() != string->length()) return false;
DisallowGarbageCollection no_gc;
if (string->IsOneByteRepresentation()) {
const uint8_t* string_data = string->GetChars<uint8_t>(no_gc);
return CompareChars(chars.begin(), string_data, chars.length()) == 0;
}
const uint16_t* string_data = string->GetChars<uint16_t>(no_gc);
return CompareChars(chars.begin(), string_data, chars.length()) == 0;
return string->IsEqualTo(chars);
}
} // namespace

View File

@ -316,16 +316,7 @@ class SequentialStringKey final : public StringTableKey {
chars_(chars),
convert_(convert) {}
bool IsMatch(String s) override {
SharedStringAccessGuardIfNeeded access_guard(s);
DisallowGarbageCollection no_gc;
if (s.IsOneByteRepresentation()) {
const uint8_t* chars = s.GetChars<uint8_t>(no_gc, access_guard);
return CompareChars(chars, chars_.begin(), chars_.length()) == 0;
}
const uint16_t* chars = s.GetChars<uint16_t>(no_gc, access_guard);
return CompareChars(chars, chars_.begin(), chars_.length()) == 0;
}
bool IsMatch(String s) override { return s.IsEqualTo(chars_); }
Handle<String> AsHandle(Isolate* isolate) {
if (sizeof(Char) == 1) {
@ -388,13 +379,8 @@ class SeqSubStringKey final : public StringTableKey {
bool IsMatch(String string) override {
DisallowGarbageCollection no_gc;
if (string.IsOneByteRepresentation()) {
const uint8_t* data = string.GetChars<uint8_t>(no_gc);
return CompareChars(string_->GetChars(no_gc) + from_, data, length()) ==
0;
}
const uint16_t* data = string.GetChars<uint16_t>(no_gc);
return CompareChars(string_->GetChars(no_gc) + from_, data, length()) == 0;
return string.IsEqualTo(
Vector<const Char>(string_->GetChars(no_gc) + from_, length()));
}
template <typename LocalIsolate>
@ -442,6 +428,80 @@ bool String::Equals(Isolate* isolate, Handle<String> one, Handle<String> two) {
return SlowEquals(isolate, one, two);
}
template <typename Char>
bool String::IsEqualTo(Vector<const Char> str,
String::EqualityType eq_type) const {
size_t len = str.size();
switch (eq_type) {
case EqualityType::kWholeString:
if (static_cast<size_t>(length()) != len) return false;
break;
case EqualityType::kPrefix:
if (static_cast<size_t>(length()) < len) return false;
break;
}
SharedStringAccessGuardIfNeeded access_guard(*this);
DisallowGarbageCollection no_gc;
class IsEqualToDispatcher : public AllStatic {
public:
static inline bool HandleSeqOneByteString(
SeqOneByteString str, const Char* data, size_t len,
const DisallowGarbageCollection& no_gc,
const SharedStringAccessGuardIfNeeded& access_guard) {
return CompareChars(str.GetChars(no_gc, access_guard), data, len) == 0;
}
static inline bool HandleSeqTwoByteString(
SeqTwoByteString str, const Char* data, size_t len,
const DisallowGarbageCollection& no_gc,
const SharedStringAccessGuardIfNeeded& access_guard) {
return CompareChars(str.GetChars(no_gc, access_guard), data, len) == 0;
}
static inline bool HandleExternalOneByteString(
ExternalOneByteString str, const Char* data, size_t len,
const DisallowGarbageCollection& no_gc,
const SharedStringAccessGuardIfNeeded& access_guard) {
return CompareChars(str.GetChars(), data, len) == 0;
}
static inline bool HandleExternalTwoByteString(
ExternalTwoByteString str, const Char* data, size_t len,
const DisallowGarbageCollection& no_gc,
const SharedStringAccessGuardIfNeeded& access_guard) {
return CompareChars(str.GetChars(), data, len) == 0;
}
static inline bool HandleConsString(
ConsString str, const Char* data, size_t len,
const DisallowGarbageCollection& no_gc,
const SharedStringAccessGuardIfNeeded& access_guard) {
UNREACHABLE();
}
static inline bool HandleSlicedString(
SlicedString str, const Char* data, size_t len,
const DisallowGarbageCollection& no_gc,
const SharedStringAccessGuardIfNeeded& access_guard) {
UNREACHABLE();
}
static inline bool HandleThinString(
ThinString str, const Char* data, size_t len,
const DisallowGarbageCollection& no_gc,
const SharedStringAccessGuardIfNeeded& access_guard) {
UNREACHABLE();
}
static inline bool HandleInvalidString(
String str, const Char* data, size_t len,
const DisallowGarbageCollection& no_gc,
const SharedStringAccessGuardIfNeeded& access_guard) {
UNREACHABLE();
}
};
return StringShape(*this).DispatchToSpecificType<IsEqualToDispatcher, bool>(
*this, str.data(), len, no_gc, access_guard);
}
bool String::IsOneByteEqualTo(Vector<const char> str) { return IsEqualTo(str); }
template <typename Char>
const Char* String::GetChars(const DisallowGarbageCollection& no_gc) {
return StringShape(*this).IsExternal()

View File

@ -1302,50 +1302,8 @@ Object String::LastIndexOf(Isolate* isolate, Handle<Object> receiver,
return Smi::FromInt(last_index);
}
template <>
bool String::IsEqualTo(Vector<const uint8_t> str) {
return IsOneByteEqualTo(str);
}
template <>
bool String::IsEqualTo(Vector<const uc16> str) {
return IsTwoByteEqualTo(str);
}
bool String::HasOneBytePrefix(Vector<const char> str) {
int slen = str.length();
if (slen > length()) return false;
DisallowGarbageCollection no_gc;
FlatContent content = GetFlatContent(no_gc);
if (content.IsOneByte()) {
return CompareChars(content.ToOneByteVector().begin(), str.begin(), slen) ==
0;
}
return CompareChars(content.ToUC16Vector().begin(), str.begin(), slen) == 0;
}
bool String::IsOneByteEqualTo(Vector<const uint8_t> str) {
int slen = length();
if (str.length() != slen) return false;
DisallowGarbageCollection no_gc;
FlatContent content = GetFlatContent(no_gc);
if (content.IsOneByte()) {
return CompareChars(content.ToOneByteVector().begin(), str.begin(), slen) ==
0;
}
return CompareChars(content.ToUC16Vector().begin(), str.begin(), slen) == 0;
}
bool String::IsTwoByteEqualTo(Vector<const uc16> str) {
int slen = length();
if (str.length() != slen) return false;
DisallowGarbageCollection no_gc;
FlatContent content = GetFlatContent(no_gc);
if (content.IsOneByte()) {
return CompareChars(content.ToOneByteVector().begin(), str.begin(), slen) ==
0;
}
return CompareChars(content.ToUC16Vector().begin(), str.begin(), slen) == 0;
return IsEqualTo(str, EqualityType::kPrefix);
}
namespace {

View File

@ -317,16 +317,14 @@ class String : public TorqueGeneratedString<String, Name> {
inline static bool Equals(Isolate* isolate, Handle<String> one,
Handle<String> two);
// Dispatches to Is{One,Two}ByteEqualTo.
enum class EqualityType { kWholeString, kPrefix };
template <typename Char>
bool IsEqualTo(Vector<const Char> str);
inline bool IsEqualTo(
Vector<const Char> str,
EqualityType eq_type = EqualityType::kWholeString) const;
V8_EXPORT_PRIVATE bool HasOneBytePrefix(Vector<const char> str);
V8_EXPORT_PRIVATE bool IsOneByteEqualTo(Vector<const uint8_t> str);
V8_EXPORT_PRIVATE bool IsOneByteEqualTo(Vector<const char> str) {
return IsOneByteEqualTo(Vector<const uint8_t>::cast(str));
}
bool IsTwoByteEqualTo(Vector<const uc16> str);
V8_EXPORT_PRIVATE inline bool IsOneByteEqualTo(Vector<const char> str);
// Return a UTF8 representation of the string. The string is null
// terminated but may optionally contain nulls. Length is returned