Commit 63d6b750 authored by Jakob Kummerow's avatar Jakob Kummerow Committed by Commit Bot

Make String::IsOneByteRepresentationUnderneath static

and non-recursive in order to let Clang inline it.
Bonus: Drop IsTwoByteRepresentationUnderneath, which was dead code
except for one test, and is semantically redundant.

Bug: chromium:910573
Change-Id: I86f1c312e93ab875b4b42101ac65ddc94b1c9518
Reviewed-on: https://chromium-review.googlesource.com/c/1369086Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58171}
parent ab5d90da
...@@ -461,7 +461,7 @@ V8_WARN_UNUSED_RESULT static Object* ConvertCase( ...@@ -461,7 +461,7 @@ V8_WARN_UNUSED_RESULT static Object* ConvertCase(
// character is also ASCII. This is currently the case, but it // character is also ASCII. This is currently the case, but it
// might break in the future if we implement more context and locale // might break in the future if we implement more context and locale
// dependent upper/lower conversions. // dependent upper/lower conversions.
if (s->IsOneByteRepresentationUnderneath()) { if (String::IsOneByteRepresentationUnderneath(*s)) {
// Same length as input. // Same length as input.
Handle<SeqOneByteString> result = Handle<SeqOneByteString> result =
isolate->factory()->NewRawOneByteString(length).ToHandleChecked(); isolate->factory()->NewRawOneByteString(length).ToHandleChecked();
......
...@@ -209,7 +209,7 @@ class StringToIntHelper { ...@@ -209,7 +209,7 @@ class StringToIntHelper {
bool IsOneByte() const { bool IsOneByte() const {
return raw_one_byte_subject_ != nullptr || return raw_one_byte_subject_ != nullptr ||
subject_->IsOneByteRepresentationUnderneath(); String::IsOneByteRepresentationUnderneath(*subject_);
} }
Vector<const uint8_t> GetOneByteVector() { Vector<const uint8_t> GetOneByteVector() {
......
...@@ -901,14 +901,14 @@ void JsonStringifier::SerializeDeferredKey(bool deferred_comma, ...@@ -901,14 +901,14 @@ void JsonStringifier::SerializeDeferredKey(bool deferred_comma,
void JsonStringifier::SerializeString(Handle<String> object) { void JsonStringifier::SerializeString(Handle<String> object) {
object = String::Flatten(isolate_, object); object = String::Flatten(isolate_, object);
if (builder_.CurrentEncoding() == String::ONE_BYTE_ENCODING) { if (builder_.CurrentEncoding() == String::ONE_BYTE_ENCODING) {
if (object->IsOneByteRepresentationUnderneath()) { if (String::IsOneByteRepresentationUnderneath(*object)) {
SerializeString_<uint8_t, uint8_t>(object); SerializeString_<uint8_t, uint8_t>(object);
} else { } else {
builder_.ChangeEncoding(); builder_.ChangeEncoding();
SerializeString(object); SerializeString(object);
} }
} else { } else {
if (object->IsOneByteRepresentationUnderneath()) { if (String::IsOneByteRepresentationUnderneath(*object)) {
SerializeString_<uint8_t, uc16>(object); SerializeString_<uint8_t, uc16>(object);
} else { } else {
SerializeString_<uc16, uc16>(object); SerializeString_<uc16, uc16>(object);
......
...@@ -16725,7 +16725,7 @@ MaybeHandle<String> EscapeRegExpSource(Isolate* isolate, ...@@ -16725,7 +16725,7 @@ MaybeHandle<String> EscapeRegExpSource(Isolate* isolate,
Handle<String> source) { Handle<String> source) {
DCHECK(source->IsFlat()); DCHECK(source->IsFlat());
if (source->length() == 0) return isolate->factory()->query_colon_string(); if (source->length() == 0) return isolate->factory()->query_colon_string();
bool one_byte = source->IsOneByteRepresentationUnderneath(); bool one_byte = String::IsOneByteRepresentationUnderneath(*source);
int escapes = one_byte ? CountRequiredEscapes<uint8_t>(source) int escapes = one_byte ? CountRequiredEscapes<uint8_t>(source)
: CountRequiredEscapes<uc16>(source); : CountRequiredEscapes<uc16>(source);
if (escapes == 0) return source; if (escapes == 0) return source;
......
...@@ -162,33 +162,20 @@ bool String::IsTwoByteRepresentation() const { ...@@ -162,33 +162,20 @@ bool String::IsTwoByteRepresentation() const {
return (type & kStringEncodingMask) == kTwoByteStringTag; return (type & kStringEncodingMask) == kTwoByteStringTag;
} }
bool String::IsOneByteRepresentationUnderneath() { bool String::IsOneByteRepresentationUnderneath(String string) {
uint32_t type = map()->instance_type(); while (true) {
STATIC_ASSERT(kIsIndirectStringTag != 0); uint32_t type = string.map()->instance_type();
STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0); STATIC_ASSERT(kIsIndirectStringTag != 0);
DCHECK(IsFlat()); STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0);
switch (type & (kIsIndirectStringMask | kStringEncodingMask)) { DCHECK(string.IsFlat());
case kOneByteStringTag: switch (type & (kIsIndirectStringMask | kStringEncodingMask)) {
return true; case kOneByteStringTag:
case kTwoByteStringTag: return true;
return false; case kTwoByteStringTag:
default: // Cons, sliced, thin, strings need to go deeper. return false;
return GetUnderlying()->IsOneByteRepresentationUnderneath(); default: // Cons, sliced, thin, strings need to go deeper.
} string = string.GetUnderlying();
} }
bool String::IsTwoByteRepresentationUnderneath() {
uint32_t type = map()->instance_type();
STATIC_ASSERT(kIsIndirectStringTag != 0);
STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0);
DCHECK(IsFlat());
switch (type & (kIsIndirectStringMask | kStringEncodingMask)) {
case kOneByteStringTag:
return false;
case kTwoByteStringTag:
return true;
default: // Cons, sliced, thin, strings need to go deeper.
return GetUnderlying()->IsTwoByteRepresentationUnderneath();
} }
} }
......
...@@ -164,9 +164,9 @@ class String : public Name { ...@@ -164,9 +164,9 @@ class String : public Name {
// Cons and slices have an encoding flag that may not represent the actual // Cons and slices have an encoding flag that may not represent the actual
// encoding of the underlying string. This is taken into account here. // encoding of the underlying string. This is taken into account here.
// Requires: this->IsFlat() // This function is static because that helps it get inlined.
inline bool IsOneByteRepresentationUnderneath(); // Requires: string.IsFlat()
inline bool IsTwoByteRepresentationUnderneath(); static inline bool IsOneByteRepresentationUnderneath(String string);
// NOTE: this should be considered only a hint. False negatives are // NOTE: this should be considered only a hint. False negatives are
// possible. // possible.
......
...@@ -410,7 +410,7 @@ int RegExpImpl::IrregexpPrepare(Isolate* isolate, Handle<JSRegExp> regexp, ...@@ -410,7 +410,7 @@ int RegExpImpl::IrregexpPrepare(Isolate* isolate, Handle<JSRegExp> regexp,
DCHECK(subject->IsFlat()); DCHECK(subject->IsFlat());
// Check representation of the underlying storage. // Check representation of the underlying storage.
bool is_one_byte = subject->IsOneByteRepresentationUnderneath(); bool is_one_byte = String::IsOneByteRepresentationUnderneath(*subject);
if (!EnsureCompiledIrregexp(isolate, regexp, subject, is_one_byte)) return -1; if (!EnsureCompiledIrregexp(isolate, regexp, subject, is_one_byte)) return -1;
#ifdef V8_INTERPRETED_REGEXP #ifdef V8_INTERPRETED_REGEXP
...@@ -436,7 +436,7 @@ int RegExpImpl::IrregexpExecRaw(Isolate* isolate, Handle<JSRegExp> regexp, ...@@ -436,7 +436,7 @@ int RegExpImpl::IrregexpExecRaw(Isolate* isolate, Handle<JSRegExp> regexp,
DCHECK_LE(index, subject->length()); DCHECK_LE(index, subject->length());
DCHECK(subject->IsFlat()); DCHECK(subject->IsFlat());
bool is_one_byte = subject->IsOneByteRepresentationUnderneath(); bool is_one_byte = String::IsOneByteRepresentationUnderneath(*subject);
#ifndef V8_INTERPRETED_REGEXP #ifndef V8_INTERPRETED_REGEXP
DCHECK(output_size >= (IrregexpNumberOfCaptures(*irregexp) + 1) * 2); DCHECK(output_size >= (IrregexpNumberOfCaptures(*irregexp) + 1) * 2);
...@@ -472,7 +472,7 @@ int RegExpImpl::IrregexpExecRaw(Isolate* isolate, Handle<JSRegExp> regexp, ...@@ -472,7 +472,7 @@ int RegExpImpl::IrregexpExecRaw(Isolate* isolate, Handle<JSRegExp> regexp,
// being internal and external, and even between being Latin1 and UC16, // being internal and external, and even between being Latin1 and UC16,
// but the characters are always the same). // but the characters are always the same).
IrregexpPrepare(isolate, regexp, subject); IrregexpPrepare(isolate, regexp, subject);
is_one_byte = subject->IsOneByteRepresentationUnderneath(); is_one_byte = String::IsOneByteRepresentationUnderneath(*subject);
} while (true); } while (true);
UNREACHABLE(); UNREACHABLE();
#else // V8_INTERPRETED_REGEXP #else // V8_INTERPRETED_REGEXP
......
...@@ -161,7 +161,7 @@ int NativeRegExpMacroAssembler::CheckStackGuardState( ...@@ -161,7 +161,7 @@ int NativeRegExpMacroAssembler::CheckStackGuardState(
HandleScope handles(isolate); HandleScope handles(isolate);
Handle<Code> code_handle(re_code, isolate); Handle<Code> code_handle(re_code, isolate);
Handle<String> subject_handle(String::cast(ObjectPtr(*subject)), isolate); Handle<String> subject_handle(String::cast(ObjectPtr(*subject)), isolate);
bool is_one_byte = subject_handle->IsOneByteRepresentationUnderneath(); bool is_one_byte = String::IsOneByteRepresentationUnderneath(*subject_handle);
StackLimitCheck check(isolate); StackLimitCheck check(isolate);
bool js_has_overflowed = check.JsHasOverflowed(); bool js_has_overflowed = check.JsHasOverflowed();
...@@ -192,7 +192,8 @@ int NativeRegExpMacroAssembler::CheckStackGuardState( ...@@ -192,7 +192,8 @@ int NativeRegExpMacroAssembler::CheckStackGuardState(
// If we continue, we need to update the subject string addresses. // If we continue, we need to update the subject string addresses.
if (return_value == 0) { if (return_value == 0) {
// String encoding might have changed. // String encoding might have changed.
if (subject_handle->IsOneByteRepresentationUnderneath() != is_one_byte) { if (String::IsOneByteRepresentationUnderneath(*subject_handle) !=
is_one_byte) {
// If we changed between an LATIN1 and an UC16 string, the specialized // If we changed between an LATIN1 and an UC16 string, the specialized
// code cannot be used, and we need to restart regexp matching from // code cannot be used, and we need to restart regexp matching from
// scratch (including, potentially, compiling a new version of the code). // scratch (including, potentially, compiling a new version of the code).
......
...@@ -493,7 +493,7 @@ static MaybeHandle<String> EscapePrivate(Isolate* isolate, ...@@ -493,7 +493,7 @@ static MaybeHandle<String> EscapePrivate(Isolate* isolate,
MaybeHandle<String> Uri::Escape(Isolate* isolate, Handle<String> string) { MaybeHandle<String> Uri::Escape(Isolate* isolate, Handle<String> string) {
Handle<String> result; Handle<String> result;
string = String::Flatten(isolate, string); string = String::Flatten(isolate, string);
return string->IsOneByteRepresentationUnderneath() return String::IsOneByteRepresentationUnderneath(*string)
? EscapePrivate<uint8_t>(isolate, string) ? EscapePrivate<uint8_t>(isolate, string)
: EscapePrivate<uc16>(isolate, string); : EscapePrivate<uc16>(isolate, string);
} }
...@@ -501,7 +501,7 @@ MaybeHandle<String> Uri::Escape(Isolate* isolate, Handle<String> string) { ...@@ -501,7 +501,7 @@ MaybeHandle<String> Uri::Escape(Isolate* isolate, Handle<String> string) {
MaybeHandle<String> Uri::Unescape(Isolate* isolate, Handle<String> string) { MaybeHandle<String> Uri::Unescape(Isolate* isolate, Handle<String> string) {
Handle<String> result; Handle<String> result;
string = String::Flatten(isolate, string); string = String::Flatten(isolate, string);
return string->IsOneByteRepresentationUnderneath() return String::IsOneByteRepresentationUnderneath(*string)
? UnescapePrivate<uint8_t>(isolate, string) ? UnescapePrivate<uint8_t>(isolate, string)
: UnescapePrivate<uc16>(isolate, string); : UnescapePrivate<uc16>(isolate, string);
} }
......
...@@ -1832,9 +1832,8 @@ TEST(Regress876759) { ...@@ -1832,9 +1832,8 @@ TEST(Regress876759) {
CHECK(grandparent->IsOneByteRepresentation()); CHECK(grandparent->IsOneByteRepresentation());
CHECK(parent->IsTwoByteRepresentation()); CHECK(parent->IsTwoByteRepresentation());
CHECK(sliced->IsTwoByteRepresentation()); CHECK(sliced->IsTwoByteRepresentation());
// The *Underneath versions return the correct representation. // The *Underneath version returns the correct representation.
CHECK(sliced->IsOneByteRepresentationUnderneath()); CHECK(String::IsOneByteRepresentationUnderneath(*sliced));
CHECK(!sliced->IsTwoByteRepresentationUnderneath());
} }
} // namespace test_strings } // namespace test_strings
......
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