Bug 120389

Summary: JSArray::shiftCountWithArrayStorage doesn't change indexBias when shifting the last element in m_vector
Product: WebKit Reporter: Mark Hahnenberg <mhahnenberg>
Component: JavaScriptCoreAssignee: Mark Hahnenberg <mhahnenberg>
Status: RESOLVED FIXED    
Severity: Normal    
Priority: P2    
Version: 528+ (Nightly build)   
Hardware: Unspecified   
OS: Unspecified   
Bug Depends on:    
Bug Blocks: 121074    
Attachments:
Description Flags
Patch
none
Patch
none
Patch none

Description Mark Hahnenberg 2013-08-27 19:07:26 PDT
This leads to the JSArray forgetting it's true size (it thinks it has 8 bytes less than it actually does).
Comment 1 Mark Hahnenberg 2013-08-27 19:16:04 PDT
Created attachment 209836 [details]
Patch
Comment 2 Geoffrey Garen 2013-08-27 20:28:57 PDT
Comment on attachment 209836 [details]
Patch

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

> Source/JavaScriptCore/ChangeLog:8
> +        This leads to the JSArray forgetting it's true size (it thinks it has 8 bytes less 

Should be "its true size".
Comment 3 Mark Hahnenberg 2013-08-27 21:17:01 PDT
(In reply to comment #2)
> (From update of attachment 209836 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=209836&action=review
> 
> > Source/JavaScriptCore/ChangeLog:8
> > +        This leads to the JSArray forgetting it's true size (it thinks it has 8 bytes less 
> 
> Should be "its true size".

Will fix.
Comment 4 Michael Saboff 2013-08-27 21:21:36 PDT
Comment on attachment 209836 [details]
Patch

r=me - With change log fix.
Comment 5 Filip Pizlo 2013-08-27 21:38:45 PDT
Comment on attachment 209836 [details]
Patch

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

> Source/JavaScriptCore/runtime/JSArray.cpp:729
> +        return true;
>      }
> +
> +    storage->m_indexBias += count;
>      return true;

This looks like it's introducing a new bug: the (startIndex < usedVectorLength - (startIndex + count)) == true case already adds count to indexBias.  So now you're adding it twice.
Comment 6 Mark Hahnenberg 2013-08-27 21:41:24 PDT
Comment on attachment 209836 [details]
Patch

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

>> Source/JavaScriptCore/runtime/JSArray.cpp:729
>>      return true;
> 
> This looks like it's introducing a new bug: the (startIndex < usedVectorLength - (startIndex + count)) == true case already adds count to indexBias.  So now you're adding it twice.

I don't think so. There's an early return inside the if block.
Comment 7 Mark Hahnenberg 2013-08-28 08:25:20 PDT
(In reply to comment #6)
> (From update of attachment 209836 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=209836&action=review
> 
> >> Source/JavaScriptCore/runtime/JSArray.cpp:729
> >>      return true;
> > 
> > This looks like it's introducing a new bug: the (startIndex < usedVectorLength - (startIndex + count)) == true case already adds count to indexBias.  So now you're adding it twice.
> 
> I don't think so. There's an early return inside the if block.

But it does look like the other branch of the if-statement isn't modifying indexBias either, and it appears that it should.
Comment 8 Mark Hahnenberg 2013-08-28 10:37:10 PDT
Created attachment 209901 [details]
Patch
Comment 9 Mark Hahnenberg 2013-08-28 17:34:18 PDT
Comment on attachment 209901 [details]
Patch

This patch is wrong. It breaks Facebook.
Comment 10 Mark Hahnenberg 2013-08-29 10:26:34 PDT
Created attachment 209997 [details]
Patch
Comment 11 Mark Hahnenberg 2013-08-29 10:28:14 PDT
(In reply to comment #10)
> Created an attachment (id=209997) [details]
> Patch

I went through the code and tried to figure out exactly what it was doing. As I went I added new variables that more accurately describe some of the intermediate calculations that are going on, which make the code much clearer. I also added comments to explain why we're doing certain things in certain places.
Comment 12 Mark Hahnenberg 2013-08-29 10:30:23 PDT
Comment on attachment 209997 [details]
Patch

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

> Source/JavaScriptCore/runtime/JSArray.cpp:726
> +        // Since we're consuming part of the vector by moving its beginning to the left,

...beginning to the *right*
Comment 13 Michael Saboff 2013-08-29 13:44:50 PDT
Comment on attachment 209997 [details]
Patch

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

> Source/JavaScriptCore/runtime/JSArray.cpp:717
>              memmove(
> -                storage->m_vector + startIndex,
> -                storage->m_vector + startIndex + count,
> -                sizeof(JSValue) * (usedVectorLength - (startIndex + count)));
> -            for (unsigned i = usedVectorLength - count; i < usedVectorLength; ++i)
> -                storage->m_vector[i].clear();
> -        }
> +                storage->m_vector + count,
> +                storage->m_vector,
> +                sizeof(JSValue) * startIndex);

What about when the result of the shift will result with a vector length of 0.  Copying in that case is wasteful and may also be wrong.

> Source/JavaScriptCore/runtime/JSArray.cpp:735
> +        memmove(
> +            storage->m_vector + startIndex,
> +            storage->m_vector + firstIndexAfterShiftRegion,
> +            sizeof(JSValue) * numElementsAfterShiftRegion);

Ditto.
Comment 14 Mark Hahnenberg 2013-08-29 13:47:38 PDT
(In reply to comment #13)
> (From update of attachment 209997 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=209997&action=review
> 
> > Source/JavaScriptCore/runtime/JSArray.cpp:717
> >              memmove(
> > -                storage->m_vector + startIndex,
> > -                storage->m_vector + startIndex + count,
> > -                sizeof(JSValue) * (usedVectorLength - (startIndex + count)));
> > -            for (unsigned i = usedVectorLength - count; i < usedVectorLength; ++i)
> > -                storage->m_vector[i].clear();
> > -        }
> > +                storage->m_vector + count,
> > +                storage->m_vector,
> > +                sizeof(JSValue) * startIndex);
> 
> What about when the result of the shift will result with a vector length of 0.  Copying in that case is wasteful and may also be wrong.
Why create a special case for that? I ran benchmarks with this patch and it had no effect. 

> 
> > Source/JavaScriptCore/runtime/JSArray.cpp:735
> > +        memmove(
> > +            storage->m_vector + startIndex,
> > +            storage->m_vector + firstIndexAfterShiftRegion,
> > +            sizeof(JSValue) * numElementsAfterShiftRegion);
> 
> Ditto.
Comment 15 Michael Saboff 2013-09-09 15:06:41 PDT
Comment on attachment 209997 [details]
Patch

r=me per our discussion.  Please add RELEASE_ASSERTs to make sure that neither memmove will write past the end (first memmove) or beginning (second memmove).
Comment 16 Mark Hahnenberg 2013-09-09 15:40:01 PDT
Committed r155395: <http://trac.webkit.org/changeset/155395>
Comment 17 Csaba Osztrogonác 2013-11-05 09:05:50 PST
Comment on attachment 209997 [details]
Patch

Cleared review? from attachment 209997 [details] so that this bug does not appear in http://webkit.org/pending-review.  If you would like this patch reviewed, please attach it to a new bug (or re-open this bug before marking it for review again).