[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:
parent
20b417503a
commit
0df6a20899
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user