Bug 160282 - StringView should have an explicit m_is8Bit field.
Summary: StringView should have an explicit m_is8Bit field.
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Web Template Framework (show other bugs)
Version: WebKit Local Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Mark Lam
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2016-07-27 20:22 PDT by Mark Lam
Modified: 2016-07-29 10:13 PDT (History)
12 users (show)

See Also:


Attachments
proposed patch. (10.08 KB, patch)
2016-07-27 20:44 PDT, Mark Lam
no flags Details | Formatted Diff | Diff
proposed patch: added rdar links to ChangeLogs. (10.15 KB, patch)
2016-07-27 21:06 PDT, Mark Lam
benjamin: review+
Details | Formatted Diff | Diff
x86_64 benchmark results. (77.62 KB, text/plain)
2016-07-28 12:54 PDT, Mark Lam
no flags Details
x86 benchmark results. (77.72 KB, text/plain)
2016-07-28 12:55 PDT, Mark Lam
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Mark Lam 2016-07-27 20:22:54 PDT
The current implementation reserves 1 bit in the m_length field as a is16Bit flag.  As a result, a StringView is incapable of handling strings that have a length of a 32-bit in size.  This results in a mismatch with the expectations of String, StringImpl, and JavaScriptCore's JSString.
Comment 1 Mark Lam 2016-07-27 20:23:48 PDT
<rdar://problem/27327943>
Comment 2 Mark Lam 2016-07-27 20:44:46 PDT
Created attachment 284754 [details]
proposed patch.
Comment 3 Mark Lam 2016-07-27 21:06:14 PDT
Created attachment 284756 [details]
proposed patch: added rdar links to ChangeLogs.
Comment 4 Benjamin Poulain 2016-07-27 21:13:41 PDT
Comment on attachment 284756 [details]
proposed patch: added rdar links to ChangeLogs.

Thanks for fixing this.
Comment 5 Geoffrey Garen 2016-07-28 10:42:22 PDT
Mark pointed out that, if we needed to save space, we could store the flag in the low bit of the characters pointer without losing information -- but StringView seems to be a temporary object whose size doesn't matter.
Comment 6 Anders Carlsson 2016-07-28 10:43:54 PDT
(In reply to comment #5)
> Mark pointed out that, if we needed to save space, we could store the flag
> in the low bit of the characters pointer without losing information -- but
> StringView seems to be a temporary object whose size doesn't matter.

This won't work, the pointer is byte aligned. 

The reason we store it in the upper bit is to make it possible to put the length + pointer in two registers.
Comment 7 Geoffrey Garen 2016-07-28 10:45:24 PDT
Anders explained on IRC that we originally used bit packing so we could pass StringView by value in two registers.
Comment 8 Saam Barati 2016-07-28 11:53:36 PDT
(In reply to comment #7)
> Anders explained on IRC that we originally used bit packing so we could pass
> StringView by value in two registers.

Won't that still happen on 64-bit?
Comment 9 Geoffrey Garen 2016-07-28 12:05:05 PDT
> > Anders explained on IRC that we originally used bit packing so we could pass
> > StringView by value in two registers.
> 
> Won't that still happen on 64-bit?

Yes.
Comment 10 Anders Carlsson 2016-07-28 12:14:24 PDT
(In reply to comment #9)
> > > Anders explained on IRC that we originally used bit packing so we could pass
> > > StringView by value in two registers.
> > 
> > Won't that still happen on 64-bit?
> 
> Yes.

Did you verify this?
Comment 11 Geoffrey Garen 2016-07-28 12:25:38 PDT
> Did you verify this?

http://agner.org/optimize/calling_conventions.pdf, page 20:

"Entire object is transferred in integer registers and/or XMM registers if the size is no bigger than 128 bits... Examples: int and float: RDI."

~/scratch> cat scratch.cc

struct Object
{
    unsigned x;
    bool y;
};

__attribute__((noinline)) void f(Object)
{
}

int main()
{
    Object o;
    f(o);
}

~/scratch> clang++ -o scratch scratch.cc && otool -tvV scratch
scratch:
(__TEXT,__text) section
__Z1f6Object:
0000000100000f60	pushq	%rbp
0000000100000f61	movq	%rsp, %rbp
0000000100000f64	movq	%rdi, -0x8(%rbp)
0000000100000f68	popq	%rbp
0000000100000f69	retq
0000000100000f6a	nopw	(%rax,%rax)
_main:
0000000100000f70	pushq	%rbp
0000000100000f71	movq	%rsp, %rbp
0000000100000f74	subq	$0x10, %rsp
0000000100000f78	movq	-0x8(%rbp), %rax
0000000100000f7c	movq	%rax, -0x10(%rbp)
0000000100000f80	movq	-0x10(%rbp), %rdi       ## Hi Anders!
0000000100000f84	callq	__Z1f6Object            ## f(Object)
0000000100000f89	xorl	%eax, %eax
0000000100000f8b	addq	$0x10, %rsp
0000000100000f8f	popq	%rbp
0000000100000f90	retq
Comment 12 Mark Lam 2016-07-28 12:54:59 PDT
Created attachment 284806 [details]
x86_64 benchmark results.
Comment 13 Mark Lam 2016-07-28 12:55:29 PDT
Created attachment 284807 [details]
x86 benchmark results.
Comment 14 Mark Lam 2016-07-28 12:56:03 PDT
Benchmark results show that perf is neutral in aggregate with this patch.
Comment 15 Geoffrey Garen 2016-07-28 13:25:09 PDT
Actually, StringView never passed in registers because it has non-trivial copy and move constructors -- and it still doesn't pass in registers :(.
Comment 16 Mark Lam 2016-07-28 13:30:32 PDT
Landed in r203834: <http://trac.webkit.org/r203834>.
Comment 17 Darin Adler 2016-07-28 14:56:23 PDT
(In reply to comment #15)
> Actually, StringView never passed in registers because it has non-trivial
> copy and move constructors -- and it still doesn't pass in registers :(.

I think part of that statement wrong.

I am almost sure that the original version did pass in registers.

The work done in the copy and move constructors is only needed for debugging, so we should fix this so that in production builds it passes in registers again. I believe I caused this problem when adding the underlying string debugging mechanism.

This should be easy to fix!
Comment 18 Mark Lam 2016-07-29 10:13:59 PDT
(In reply to comment #17)
> (In reply to comment #15)
> > Actually, StringView never passed in registers because it has non-trivial
> > copy and move constructors -- and it still doesn't pass in registers :(.
> 
> I think part of that statement wrong.
> 
> I am almost sure that the original version did pass in registers.
> 
> The work done in the copy and move constructors is only needed for
> debugging, so we should fix this so that in production builds it passes in
> registers again. I believe I caused this problem when adding the underlying
> string debugging mechanism.
> 
> This should be easy to fix!

FYI, I'll address this in https://bugs.webkit.org/show_bug.cgi?id=160344.