Bug 157249 - Deduplicated initializer lists of BitmapImage constructors.
Summary: Deduplicated initializer lists of BitmapImage constructors.
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Images (show other bugs)
Version: WebKit Local Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Nobody
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-05-01 14:37 PDT by Konstantin Tokarev
Modified: 2016-05-04 10:52 PDT (History)
6 users (show)

See Also:


Attachments
Patch (8.10 KB, patch)
2016-05-01 14:44 PDT, Konstantin Tokarev
no flags Details | Formatted Diff | Diff
Patch (8.45 KB, patch)
2016-05-04 04:35 PDT, Konstantin Tokarev
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Konstantin Tokarev 2016-05-01 14:37:08 PDT
BitmapImage has 3 constructors, which initialize the same variables. Because of this duplication it's easy to leave some field uninitialized in some code path. Actually, there are already which are already left initialized in 1 or 2 of constructors, e.g. m_desiredFrameStartTime, m_decodedPropertiesSize, m_progressiveLoadChunkTime, m_progressiveLoadChunkCount, m_hasUniformFrameSize.

Use constructor delegation and inline filed initializers to avoid this problem.
Comment 1 Konstantin Tokarev 2016-05-01 14:44:00 PDT
Created attachment 277869 [details]
Patch
Comment 2 Darin Adler 2016-05-01 16:37:57 PDT
Comment on attachment 277869 [details]
Patch

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

> Source/WebCore/platform/graphics/BitmapImage.cpp:48
> +BitmapImage::BitmapImage(ImageObserver* observer, bool fromNativeImage)

This approach of taking a boolean is a little bit inelegant, violates our coding style rule of not using literal "true" for a mysterious meaning that requires reading the code to find out what it means, and also adds a few branches to the constructors, but I think it’s OK.

> Source/WebCore/platform/graphics/BitmapImage.h:302
> +    int m_repetitionCount { cAnimationNone }; // How many total animation loops we should do.

Not sure why we removed the comment explaining the meaning of cAnimationNone. Might be better to move it somewhere rather than removing it entirely.
Comment 3 Konstantin Tokarev 2016-05-04 04:35:58 PDT
Created attachment 278074 [details]
Patch
Comment 4 Konstantin Tokarev 2016-05-04 04:39:20 PDT
(In reply to comment #2)
> Comment on attachment 277869 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=277869&action=review
> 
> > Source/WebCore/platform/graphics/BitmapImage.cpp:48
> > +BitmapImage::BitmapImage(ImageObserver* observer, bool fromNativeImage)
> 
> This approach of taking a boolean is a little bit inelegant, violates our
> coding style rule of not using literal "true" for a mysterious meaning that
> requires reading the code to find out what it means, and also adds a few
> branches to the constructors, but I think it’s OK.

I've got rid of branch in constructor by using template + std::true_type/false_type. Now it should compile to the same code as before, though I understand that it's inelegant.

> 
> > Source/WebCore/platform/graphics/BitmapImage.h:302
> > +    int m_repetitionCount { cAnimationNone }; // How many total animation loops we should do.
> 
> Not sure why we removed the comment explaining the meaning of
> cAnimationNone. Might be better to move it somewhere rather than removing it
> entirely.

I thought it's not so important after we have initializer. Returned it back now.
Comment 5 Darin Adler 2016-05-04 08:28:07 PDT
Comment on attachment 278074 [details]
Patch

OK
Comment 6 WebKit Commit Bot 2016-05-04 09:19:24 PDT
Comment on attachment 278074 [details]
Patch

Clearing flags on attachment: 278074

Committed r200417: <http://trac.webkit.org/changeset/200417>
Comment 7 WebKit Commit Bot 2016-05-04 09:19:28 PDT
All reviewed patches have been landed.  Closing bug.
Comment 8 Michael Catanzaro 2016-05-04 09:46:04 PDT
(In reply to comment #4)
> I've got rid of branch in constructor by using template +
> std::true_type/false_type. Now it should compile to the same code as before,
> though I understand that it's inelegant.

Inelegant indeed... I think we are being too clever here. std::true_type and std::false_type are obtuse and still violate the spirit of the rule against using boolean parameters. I'm also skeptical that there will actually be any significant performance benefit to using templates instead. (Remember that increased code size is likely to hurt performance.) I think this code would be better with boolean parameters, and best with an simple two-value enum class.
Comment 9 Konstantin Tokarev 2016-05-04 09:47:54 PDT
Template here just generates two separate initializer lists for "true" and "false" cases, so no additional bloat.
Comment 10 Konstantin Tokarev 2016-05-04 10:04:15 PDT
If you like, I can change it back to non-inline function + branch with enum argument, or keep template and replace true_type and false_type with tag classes like

BitmapImage(observer, FromNative())
Comment 11 Said Abou-Hallawa 2016-05-04 10:52:59 PDT
Another cleaner way is the following:

1. Convert all the bit-field boolean members in the BitImage class to be non bit-field so you can initialize them in the class header like that:
   << bool m_isSolidColor : 1;
   >> bool m_isSolidColor { false };

2. Move the platform-dependent constructor BitmapImage::BitmapImage() from BitmapImageCairo.cpp and BitmapImageCG.cpp to BitmapImage.cpp and have only one constructor written like that

   BitmapImage(NativeImagePtr&& image, ImageObserver* observer)
        : Image(observer)
        , m_frameCount(1)
        , m_animationFinished(true)
        ...

3. Add two new static methods in FrameData which return the size and the hasAlpha of a NativeImagePtr. And call these functions from the constructor like that:

    BitmapImage::BitmapImage(NativeImagePtr&& image, ImageObserver* observer)
        : mage(observer)
        , m_frameCount(1)
        , m_animationFinished(true)
        ...
    {
        m_size = FrameData::size(image);
        m_decodedSize = size.area() * 4;

        m_frames.grow(1);
        m_frames[0].m_haveMetadata = true;
        m_frames[0].m_hasAlpha = FrameData::hasAlpha(image;
        m_frames[0].m_image = WTFMove(image);

        checkForSolidColor();
    }

5. Have different implementations for these function in BitmapImageCairo.cpp and BitmapImageCG.cpp.

e.g. in BitmapImageCG.cpp:
    FrameData::hasAlpha(NativeImagePtr&)
    {
       return true;
    }

    FrameData::size(NativeImagePtr& image)
    {
       return IntSize(CGImageGetWidth(image.get()), CGImageGetHeight(image.get()))
    }