Bug 238333 - String's startsWith() / endsWith() / replace() should take in a StringView instead of a String
Summary: String's startsWith() / endsWith() / replace() should take in a StringView in...
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Web Template Framework (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Chris Dumez
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2022-03-24 10:14 PDT by Chris Dumez
Modified: 2022-03-24 17:15 PDT (History)
3 users (show)

See Also:


Attachments
Patch (45.69 KB, patch)
2022-03-24 10:57 PDT, Chris Dumez
no flags Details | Formatted Diff | Diff
Patch (46.38 KB, patch)
2022-03-24 11:58 PDT, Chris Dumez
ews-feeder: commit-queue-
Details | Formatted Diff | Diff
Patch (49.26 KB, patch)
2022-03-24 12:20 PDT, Chris Dumez
ews-feeder: commit-queue-
Details | Formatted Diff | Diff
Patch (49.64 KB, patch)
2022-03-24 12:34 PDT, Chris Dumez
no flags Details | Formatted Diff | Diff
Patch (49.58 KB, patch)
2022-03-24 14:19 PDT, Chris Dumez
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Chris Dumez 2022-03-24 10:14:40 PDT
String's startsWith() / endsWith() should take in a StringView instead of a String, to avoid unnecessary String creation in many instances.
Comment 1 Chris Dumez 2022-03-24 10:57:08 PDT
Created attachment 455655 [details]
Patch
Comment 2 Chris Dumez 2022-03-24 11:58:29 PDT
Created attachment 455661 [details]
Patch
Comment 3 Chris Dumez 2022-03-24 12:20:18 PDT
Created attachment 455664 [details]
Patch
Comment 4 Chris Dumez 2022-03-24 12:34:02 PDT
Created attachment 455666 [details]
Patch
Comment 5 Geoffrey Garen 2022-03-24 13:41:33 PDT
Comment on attachment 455666 [details]
Patch

r=me
Comment 6 Darin Adler 2022-03-24 14:02:47 PDT
Comment on attachment 455666 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=455666&action=review

> Source/WTF/wtf/text/StringImpl.h:459
> -    WTF_EXPORT_PRIVATE Ref<StringImpl> replace(unsigned start, unsigned length, StringImpl*);
> +    WTF_EXPORT_PRIVATE Ref<StringImpl> replace(unsigned start, unsigned length, StringView);

This improved interface precludes the possible optimization for cases where the start is 0 and length is >= the existing length of the string, where we can just return the passed-in StringImpl*. Is that an important fast case anywhere?

> Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLE.cpp:1914
> +    static const char angleWarning[] = "WARNING: 0:1: extension 'GL_ARB_gpu_shader5' is not supported\n";

When touching code like this I suggest considering constexpr.

> Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLE.cpp:1915
> +    int startFrom = log.startsWith(angleWarning) ? sizeof(angleWarning) - 1 : 0;

I would probably use std::size instead of sizeof, but I’ve got to admit I am not in love with doing size - 1 for length. Is there some more elegant way to do it? We know that strlen would get const-folded, might even be guaranteed in modern versions of C++. But that’s not completely elegant I suppose.

> Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.cpp:1977
> +    static const char angleWarning[] = "WARNING: 0:1: extension 'GL_ARB_gpu_shader5' is not supported\n";

Ditto.

> Source/WebCore/platform/network/ParsedRequestRange.cpp:36
> +    if (!input.startsWith(StringView("bytes=")))

I think we don’t need the explicit StringView here any more, right?

> Source/WebKit/NetworkProcess/storage/LocalStorageManager.cpp:45
> +    if (!fileName.endsWith(StringView { fileSuffix }))

Do we really need an explicit cast to StringView here? If so, why? What’s ambiguous here?

> Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm:4451
>  static bool matchesExtensionOrEquivalent(const String& filename, const String& extension)

Seems like these arguments could both be StringView.
Comment 7 Chris Dumez 2022-03-24 14:09:32 PDT
(In reply to Darin Adler from comment #6)
> Comment on attachment 455666 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=455666&action=review
> 
> > Source/WTF/wtf/text/StringImpl.h:459
> > -    WTF_EXPORT_PRIVATE Ref<StringImpl> replace(unsigned start, unsigned length, StringImpl*);
> > +    WTF_EXPORT_PRIVATE Ref<StringImpl> replace(unsigned start, unsigned length, StringView);
> 
> This improved interface precludes the possible optimization for cases where
> the start is 0 and length is >= the existing length of the string, where we
> can just return the passed-in StringImpl*. Is that an important fast case
> anywhere?

That's a very good point. I should have paid more attention. I may revert that part after some investigation.

> 
> > Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLE.cpp:1914
> > +    static const char angleWarning[] = "WARNING: 0:1: extension 'GL_ARB_gpu_shader5' is not supported\n";
> 
> When touching code like this I suggest considering constexpr.

OK.

> 
> > Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLE.cpp:1915
> > +    int startFrom = log.startsWith(angleWarning) ? sizeof(angleWarning) - 1 : 0;
> 
> I would probably use std::size instead of sizeof, but I’ve got to admit I am
> not in love with doing size - 1 for length. Is there some more elegant way
> to do it? We know that strlen would get const-folded, might even be
> guaranteed in modern versions of C++. But that’s not completely elegant I
> suppose.

I think I'll just use strlen(). It should get optimized out by the compiler anyway and it does look much nicer.

> 
> > Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.cpp:1977
> > +    static const char angleWarning[] = "WARNING: 0:1: extension 'GL_ARB_gpu_shader5' is not supported\n";
> 
> Ditto.
> 
> > Source/WebCore/platform/network/ParsedRequestRange.cpp:36
> > +    if (!input.startsWith(StringView("bytes=")))
> 
> I think we don’t need the explicit StringView here any more, right?

Indeed.

> 
> > Source/WebKit/NetworkProcess/storage/LocalStorageManager.cpp:45
> > +    if (!fileName.endsWith(StringView { fileSuffix }))
> 
> Do we really need an explicit cast to StringView here? If so, why? What’s
> ambiguous here?

The StringView(ASCIILiteral) constructor is explicit for some reason. It is not directly obvious to me why we want it to be explicit.

> 
> > Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm:4451
> >  static bool matchesExtensionOrEquivalent(const String& filename, const String& extension)
> 
> Seems like these arguments could both be StringView.

Will look into it.
Comment 8 Chris Dumez 2022-03-24 14:11:48 PDT
(In reply to Chris Dumez from comment #7)
> (In reply to Darin Adler from comment #6)
> > Comment on attachment 455666 [details]
> > Patch
> > 
> > View in context:
> > https://bugs.webkit.org/attachment.cgi?id=455666&action=review
> > 
> > > Source/WTF/wtf/text/StringImpl.h:459
> > > -    WTF_EXPORT_PRIVATE Ref<StringImpl> replace(unsigned start, unsigned length, StringImpl*);
> > > +    WTF_EXPORT_PRIVATE Ref<StringImpl> replace(unsigned start, unsigned length, StringView);
> > 
> > This improved interface precludes the possible optimization for cases where
> > the start is 0 and length is >= the existing length of the string, where we
> > can just return the passed-in StringImpl*. Is that an important fast case
> > anywhere?
> 
> That's a very good point. I should have paid more attention. I may revert
> that part after some investigation.
> 
> > 
> > > Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLE.cpp:1914
> > > +    static const char angleWarning[] = "WARNING: 0:1: extension 'GL_ARB_gpu_shader5' is not supported\n";
> > 
> > When touching code like this I suggest considering constexpr.
> 
> OK.
> 
> > 
> > > Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLE.cpp:1915
> > > +    int startFrom = log.startsWith(angleWarning) ? sizeof(angleWarning) - 1 : 0;
> > 
> > I would probably use std::size instead of sizeof, but I’ve got to admit I am
> > not in love with doing size - 1 for length. Is there some more elegant way
> > to do it? We know that strlen would get const-folded, might even be
> > guaranteed in modern versions of C++. But that’s not completely elegant I
> > suppose.
> 
> I think I'll just use strlen(). It should get optimized out by the compiler
> anyway and it does look much nicer.
> 
> > 
> > > Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.cpp:1977
> > > +    static const char angleWarning[] = "WARNING: 0:1: extension 'GL_ARB_gpu_shader5' is not supported\n";
> > 
> > Ditto.
> > 
> > > Source/WebCore/platform/network/ParsedRequestRange.cpp:36
> > > +    if (!input.startsWith(StringView("bytes=")))
> > 
> > I think we don’t need the explicit StringView here any more, right?
> 
> Indeed.
> 
> > 
> > > Source/WebKit/NetworkProcess/storage/LocalStorageManager.cpp:45
> > > +    if (!fileName.endsWith(StringView { fileSuffix }))
> > 
> > Do we really need an explicit cast to StringView here? If so, why? What’s
> > ambiguous here?
> 
> The StringView(ASCIILiteral) constructor is explicit for some reason. It is
> not directly obvious to me why we want it to be explicit.
> 
> > 
> > > Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm:4451
> > >  static bool matchesExtensionOrEquivalent(const String& filename, const String& extension)
> > 
> > Seems like these arguments could both be StringView.
> 
> Will look into it.

There is a single call site and both parameters are of type `NSString *`. As a result, I would need to explicitly construct a String at the call site instead, which would not be obviously better?
Comment 9 Chris Dumez 2022-03-24 14:17:45 PDT
(In reply to Darin Adler from comment #6)
> Comment on attachment 455666 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=455666&action=review
> 
> > Source/WTF/wtf/text/StringImpl.h:459
> > -    WTF_EXPORT_PRIVATE Ref<StringImpl> replace(unsigned start, unsigned length, StringImpl*);
> > +    WTF_EXPORT_PRIVATE Ref<StringImpl> replace(unsigned start, unsigned length, StringView);
> 
> This improved interface precludes the possible optimization for cases where
> the start is 0 and length is >= the existing length of the string, where we
> can just return the passed-in StringImpl*. Is that an important fast case
> anywhere?

I looked at our implementation and there is no such optimization currently. Therefore, my change is not disabling an existing optimization at the very least.
Comment 10 Chris Dumez 2022-03-24 14:19:57 PDT
Created attachment 455682 [details]
Patch
Comment 11 Chris Dumez 2022-03-24 17:14:14 PDT
Comment on attachment 455682 [details]
Patch

Clearing flags on attachment: 455682

Committed r291837 (248854@trunk): <https://commits.webkit.org/248854@trunk>
Comment 12 Chris Dumez 2022-03-24 17:14:18 PDT
All reviewed patches have been landed.  Closing bug.
Comment 13 Radar WebKit Bug Importer 2022-03-24 17:15:18 PDT
<rdar://problem/90806465>