Commit e70cbb83 authored by Leszek Swirski's avatar Leszek Swirski Committed by Commit Bot

[string] Fix non-SeqStrings in IsEqualTo

Bug: chromium:1193903
Change-Id: I80704dd3cba5754779432356b20bd3ea99630291
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2794426
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Auto-Submit: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/master@{#73746}
parent c9b4f3c4
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "src/common/external-pointer-inl.h" #include "src/common/external-pointer-inl.h"
#include "src/common/external-pointer.h" #include "src/common/external-pointer.h"
#include "src/common/globals.h" #include "src/common/globals.h"
#include "src/execution/isolate-utils.h"
#include "src/handles/handles-inl.h" #include "src/handles/handles-inl.h"
#include "src/heap/factory.h" #include "src/heap/factory.h"
#include "src/numbers/conversions-inl.h" #include "src/numbers/conversions-inl.h"
...@@ -403,7 +404,8 @@ class SeqSubStringKey final : public StringTableKey { ...@@ -403,7 +404,8 @@ class SeqSubStringKey final : public StringTableKey {
DCHECK(!SharedStringAccessGuardIfNeeded::IsNeeded(*string_)); DCHECK(!SharedStringAccessGuardIfNeeded::IsNeeded(*string_));
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
return string.IsEqualTo<String::EqualityType::kNoLengthCheck>( return string.IsEqualTo<String::EqualityType::kNoLengthCheck>(
Vector<const Char>(string_->GetChars(no_gc) + from_, length())); Vector<const Char>(string_->GetChars(no_gc) + from_, length()),
isolate);
} }
Handle<String> AsHandle(Isolate* isolate) { Handle<String> AsHandle(Isolate* isolate) {
...@@ -454,19 +456,26 @@ bool String::Equals(Isolate* isolate, Handle<String> one, Handle<String> two) { ...@@ -454,19 +456,26 @@ bool String::Equals(Isolate* isolate, Handle<String> one, Handle<String> two) {
template <String::EqualityType kEqType, typename Char> template <String::EqualityType kEqType, typename Char>
bool String::IsEqualTo(Vector<const Char> str, Isolate* isolate) const { bool String::IsEqualTo(Vector<const Char> str, Isolate* isolate) const {
DCHECK(!SharedStringAccessGuardIfNeeded::IsNeeded(*this)); DCHECK(!SharedStringAccessGuardIfNeeded::IsNeeded(*this));
return IsEqualToImpl<kEqType>(str, return IsEqualToImpl<kEqType>(str, isolate,
SharedStringAccessGuardIfNeeded::NotNeeded());
}
template <String::EqualityType kEqType, typename Char>
bool String::IsEqualTo(Vector<const Char> str) const {
DCHECK(!SharedStringAccessGuardIfNeeded::IsNeeded(*this));
return IsEqualToImpl<kEqType>(str, GetIsolateForPtrCompr(*this),
SharedStringAccessGuardIfNeeded::NotNeeded()); SharedStringAccessGuardIfNeeded::NotNeeded());
} }
template <String::EqualityType kEqType, typename Char> template <String::EqualityType kEqType, typename Char>
bool String::IsEqualTo(Vector<const Char> str, LocalIsolate* isolate) const { bool String::IsEqualTo(Vector<const Char> str, LocalIsolate* isolate) const {
SharedStringAccessGuardIfNeeded access_guard(isolate); SharedStringAccessGuardIfNeeded access_guard(isolate);
return IsEqualToImpl<kEqType>(str, access_guard); return IsEqualToImpl<kEqType>(str, isolate, access_guard);
} }
template <String::EqualityType kEqType, typename Char> template <String::EqualityType kEqType, typename Char>
bool String::IsEqualToImpl( bool String::IsEqualToImpl(
Vector<const Char> str, Vector<const Char> str, IsolateRoot isolate,
const SharedStringAccessGuardIfNeeded& access_guard) const { const SharedStringAccessGuardIfNeeded& access_guard) const {
size_t len = str.size(); size_t len = str.size();
switch (kEqType) { switch (kEqType) {
...@@ -483,60 +492,77 @@ bool String::IsEqualToImpl( ...@@ -483,60 +492,77 @@ bool String::IsEqualToImpl(
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
class IsEqualToDispatcher : public AllStatic { int slice_offset = 0;
public: String string = *this;
static inline bool HandleSeqOneByteString( const Char* data = str.data();
SeqOneByteString str, const Char* data, size_t len, while (true) {
const DisallowGarbageCollection& no_gc, int32_t type = string.map(isolate).instance_type();
const SharedStringAccessGuardIfNeeded& access_guard) { switch (type & (kStringRepresentationMask | kStringEncodingMask)) {
return CompareCharsEqual(str.GetChars(no_gc, access_guard), data, len); case kSeqStringTag | kOneByteStringTag:
return CompareCharsEqual(
SeqOneByteString::cast(string).GetChars(no_gc, access_guard) +
slice_offset,
data, len);
case kSeqStringTag | kTwoByteStringTag:
return CompareCharsEqual(
SeqTwoByteString::cast(string).GetChars(no_gc, access_guard) +
slice_offset,
data, len);
case kExternalStringTag | kOneByteStringTag:
return CompareCharsEqual(
ExternalOneByteString::cast(string).GetChars() + slice_offset, data,
len);
case kExternalStringTag | kTwoByteStringTag:
return CompareCharsEqual(
ExternalTwoByteString::cast(string).GetChars() + slice_offset, data,
len);
case kSlicedStringTag | kOneByteStringTag:
case kSlicedStringTag | kTwoByteStringTag: {
SlicedString slicedString = SlicedString::cast(string);
slice_offset += slicedString.offset();
string = slicedString.parent(isolate);
continue;
} }
static inline bool HandleSeqTwoByteString(
SeqTwoByteString str, const Char* data, size_t len, case kConsStringTag | kOneByteStringTag:
const DisallowGarbageCollection& no_gc, case kConsStringTag | kTwoByteStringTag: {
const SharedStringAccessGuardIfNeeded& access_guard) { ConsStringIterator iter(ConsString::cast(string), slice_offset);
return CompareCharsEqual(str.GetChars(no_gc, access_guard), data, len); const Char* p = data;
size_t remaining_len = len;
for (String segment = iter.Next(&slice_offset); !segment.is_null();
segment = iter.Next(&slice_offset)) {
int str_len = segment.length();
if (kEqType == EqualityType::kPrefix) {
str_len = std::min(str_len, static_cast<int>(remaining_len));
remaining_len -= str_len;
}
DCHECK_LE(p + str_len, data + len);
if (!segment.IsEqualToImpl<EqualityType::kNoLengthCheck>(
VectorOf(p, str_len), isolate, access_guard)) {
return false;
} }
static inline bool HandleExternalOneByteString( p += str_len;
ExternalOneByteString str, const Char* data, size_t len, if (kEqType == EqualityType::kPrefix && remaining_len == 0) {
const DisallowGarbageCollection& no_gc, break;
const SharedStringAccessGuardIfNeeded& access_guard) {
return CompareCharsEqual(str.GetChars(), data, len);
} }
static inline bool HandleExternalTwoByteString(
ExternalTwoByteString str, const Char* data, size_t len,
const DisallowGarbageCollection& no_gc,
const SharedStringAccessGuardIfNeeded& access_guard) {
return CompareCharsEqual(str.GetChars(), data, len);
} }
static inline bool HandleConsString( DCHECK_EQ(p, data + len);
ConsString str, const Char* data, size_t len, if (kEqType == EqualityType::kPrefix) {
const DisallowGarbageCollection& no_gc, DCHECK_EQ(remaining_len, 0);
const SharedStringAccessGuardIfNeeded& access_guard) {
UNREACHABLE();
} }
static inline bool HandleSlicedString( return true;
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, case kThinStringTag | kOneByteStringTag:
const DisallowGarbageCollection& no_gc, case kThinStringTag | kTwoByteStringTag:
const SharedStringAccessGuardIfNeeded& access_guard) { string = ThinString::cast(string).actual(isolate);
continue;
default:
UNREACHABLE(); 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); } bool String::IsOneByteEqualTo(Vector<const char> str) { return IsEqualTo(str); }
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "src/common/assert-scope.h" #include "src/common/assert-scope.h"
#include "src/common/globals.h" #include "src/common/globals.h"
#include "src/execution/isolate-utils.h"
#include "src/execution/thread-id.h" #include "src/execution/thread-id.h"
#include "src/handles/handles-inl.h" #include "src/handles/handles-inl.h"
#include "src/heap/heap-inl.h" #include "src/heap/heap-inl.h"
...@@ -1286,7 +1287,10 @@ Object String::LastIndexOf(Isolate* isolate, Handle<Object> receiver, ...@@ -1286,7 +1287,10 @@ Object String::LastIndexOf(Isolate* isolate, Handle<Object> receiver,
} }
bool String::HasOneBytePrefix(Vector<const char> str) { bool String::HasOneBytePrefix(Vector<const char> str) {
return IsEqualTo<EqualityType::kPrefix>(str); DCHECK(!SharedStringAccessGuardIfNeeded::IsNeeded(*this));
return IsEqualToImpl<EqualityType::kPrefix>(
str, GetIsolateForPtrCompr(*this),
SharedStringAccessGuardIfNeeded::NotNeeded());
} }
namespace { namespace {
......
...@@ -326,8 +326,15 @@ class String : public TorqueGeneratedString<String, Name> { ...@@ -326,8 +326,15 @@ class String : public TorqueGeneratedString<String, Name> {
// The Isolate is passed as "evidence" that this call is on the main thread, // The Isolate is passed as "evidence" that this call is on the main thread,
// and to distiguish from the LocalIsolate overload. // and to distiguish from the LocalIsolate overload.
template <EqualityType kEqType = EqualityType::kWholeString, typename Char> template <EqualityType kEqType = EqualityType::kWholeString, typename Char>
inline bool IsEqualTo(Vector<const Char> str, inline bool IsEqualTo(Vector<const Char> str, Isolate* isolate) const;
Isolate* isolate = nullptr) const;
// Check if this string matches the given vector of characters, either as a
// whole string or just a prefix.
//
// This is main-thread only, like the Isolate* overload, but additionally
// computes the IsolateRoot for IsEqualToImpl.
template <EqualityType kEqType = EqualityType::kWholeString, typename Char>
inline bool IsEqualTo(Vector<const Char> str) const;
// Check if this string matches the given vector of characters, either as a // Check if this string matches the given vector of characters, either as a
// whole string or just a prefix. // whole string or just a prefix.
...@@ -539,7 +546,7 @@ class String : public TorqueGeneratedString<String, Name> { ...@@ -539,7 +546,7 @@ class String : public TorqueGeneratedString<String, Name> {
// Implementation of the IsEqualTo() public methods. Do not use directly. // Implementation of the IsEqualTo() public methods. Do not use directly.
template <EqualityType kEqType, typename Char> template <EqualityType kEqType, typename Char>
V8_INLINE bool IsEqualToImpl( V8_INLINE bool IsEqualToImpl(
Vector<const Char> str, Vector<const Char> str, IsolateRoot isolate,
const SharedStringAccessGuardIfNeeded& access_guard) const; const SharedStringAccessGuardIfNeeded& access_guard) const;
V8_EXPORT_PRIVATE static Handle<String> SlowFlatten( V8_EXPORT_PRIVATE static Handle<String> SlowFlatten(
......
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Flags: --allow-natives-syntax
var no_sync_uninternalized = "no " + "sync";
%InternalizeString(no_sync_uninternalized);
// Make sure %GetOptimizationStatus works with a non-internalized string
// parameter.
%GetOptimizationStatus(function() {}, no_sync_uninternalized)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment