Closed Bug 857957 Opened 11 years ago Closed 11 years ago

cleanup NS_SWAP* using mozilla/Endian.h

Categories

(Core :: XPCOM, defect)

defect
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla23

People

(Reporter: m_kato, Assigned: m_kato)

References

Details

Attachments

(2 files, 2 obsolete files)

Attached patch fix (obsolete) — Splinter Review
mozilla/Endian.h uses compiler built-in functions, so it can optimize endian swap code.
Attachment #733228 - Flags: review?(benjamin)
Comment on attachment 733228 [details] [diff] [review]
fix

My original plan was to use Endian.h to remove NS_SWAP* altogether; I think it makes the code clearer and removes unnecessary #ifdefs in a few places.  But Benjamin has the final say on this.
Attachment #733228 - Flags: feedback-
Attachment #733228 - Flags: review?(benjamin)
per froydnj's comment #1.  Replace NS_SWAP* and GFX_NOTHL
Attachment #733228 - Attachment is obsolete: true
Attachment #733758 - Flags: review?(benjamin)
Comment on attachment 733758 [details] [diff] [review]
replace with edian's functions

Review of attachment 733758 [details] [diff] [review]:
-----------------------------------------------------------------

This patch is great, thank you for doing this!  You probably want to get a gfx peer review on the gfx changes.

::: dom/indexedDB/Key.cpp
@@ +400,1 @@
>    memcpy(buffer, &number, sizeof(number));

The swap and the memcpy could just be replaced with:

  mozilla::BigEndian::writeUint64(buffer, number);

::: gfx/thebes/gfxColor.h
@@ +23,5 @@
>   * Attempt to use fast byte-swapping instruction(s), e.g. bswap on x86, in
>   *   preference to a sequence of shift/or operations.
>   */
> +#define GFX_0XFF_PPIXEL_FROM_UINT32(x) \
> +  ( (mozilla::NativeEndian::swapToBigEndian(uint32_t(x)) >> 8) | (0xFF << 24) )

I think this would be clearer as swapFromBigEndian, since the original version is network-to-host (host-from-network).  That 0xFF should be 0xFFU.

@@ +43,5 @@
>               m1 = GFX_UINT32_FROM_BPTR(from,1), \
>               m2 = GFX_UINT32_FROM_BPTR(from,2), \
> +             rgbr = mozilla::NativeEndian::swapToBigEndian(m0), \
> +             gbrg = mozilla::NativeEndian::swapToBigEndian(m1), \
> +             brgb = mozilla::NativeEndian::swapToBigEndian(m2), \

swapFromBigEndian here too.  (Or swapFromNetworkOrder for consistency with the earlier code.)  It seems kind of ugly that GFX_UINT32_FROM_BPTR is going to swap (on little-endian platforms) and then this is going to swap back, but that's the way it was before...

You might be able to replace GFX_UINT32_FROM_BPTR with {Little,Big}Endian::readUint32 and then the byteswapping could likely be cleaned up a bit.

::: gfx/thebes/gfxFontUtils.cpp
@@ +1120,1 @@
>      }

This entire loop could probably just be:

  mozilla::NativeEndian::copyAndSwapToBigEndian(strData, nameStr, aName.Length());

with an appropriate change to the null-termination below.

::: xpcom/io/nsBinaryStream.cpp
@@ +191,5 @@
>              return NS_ERROR_OUT_OF_MEMORY;
>      }
>      NS_ASSERTION((uintptr_t(aString) & 0x1) == 0, "aString not properly aligned");
>      for (uint32_t i = 0; i < length; i++)
> +        copy[i] = mozilla::NativeEndian::swapToBigEndian(uint16_t(aString[i]));

Use mozilla::NativeEndian::copyAndSwapToBigEndian for the loop.

@@ +631,1 @@
>  #endif

The memcpy and loop here can all be replaced with copyAndSwapToBigEndian.
Attachment #733758 - Flags: feedback+
Comment on attachment 733758 [details] [diff] [review]
replace with edian's functions

Did the gfx guys approve of replacing the GFX macros (GFX_NTOHL)? Otherwise, r+sr=me
Attachment #733758 - Flags: superreview+
Attachment #733758 - Flags: review?(benjamin)
Attachment #733758 - Flags: review+
Comment on attachment 733758 [details] [diff] [review]
replace with edian's functions

could you review gfx part?
Attachment #733758 - Flags: review?(jmuizelaar)
Comment on attachment 733758 [details] [diff] [review]
replace with edian's functions

Review of attachment 733758 [details] [diff] [review]:
-----------------------------------------------------------------

Jonathan Kew is a better reviewer for this.

::: gfx/thebes/gfxSVGGlyphs.cpp
@@ +92,5 @@
>  
>      mIndex = reinterpret_cast<IndexEntry*>(mSVGData.Elements() + sizeof(Header));
>  
>      for (uint16_t i = 0; i < mHeader->mIndexLength; i++) {
> +        mIndex[i].mStartGlyph = mozilla::NativeEndian::swapToBigEndian(mIndex[i].mStartGlyph);

I believe this is swapping from BigEndian instead of to BigEndian
Attachment #733758 - Flags: review?(jmuizelaar) → review?(jfkthame)
Comment on attachment 733758 [details] [diff] [review]
replace with edian's functions

Review of attachment 733758 [details] [diff] [review]:
-----------------------------------------------------------------

Basically looks good, modulo some notes here; also see earlier comments from Nathan and Jeff.

Clearing r? for now, as I'd like to have a second look at an updated patch, but in principle it's the right thing to do.

::: dom/indexedDB/Key.cpp
@@ +410,5 @@
>    ++aPos;
>  
>    uint64_t number = 0;
>    memcpy(&number, aPos, std::min<size_t>(sizeof(number), aEnd - aPos));
> +  number = mozilla::NativeEndian::swapToBigEndian(number);

I'm not familiar with IndexedDB code, but if we're in a function called DecodeNumber, isn't it more likely we need to swap FROM big endian?

::: gfx/thebes/gfxFontUtils.h
@@ +346,4 @@
>  #else
> +    AutoSwap_PRUint16(uint16_t aValue)
> +    {
> +        value = mozilla::NativeEndian::swapToBigEndian(aValue);

These AutoSwap_* types exist to be used in structs that map TrueType tables that are specified to hold values in big-endian form; as such, it seems like the fields should be defined using swapFromBigEndian.

@@ +367,1 @@
>      uint16_t value;

While you're here, can we make the value fields in these structs private, to avoid inadvertently accessing them directly? (They should have always been that way, I think.)

::: xpcom/io/nsBinaryStream.cpp
@@ +468,5 @@
>      rv = Read(reinterpret_cast<char*>(a16), sizeof *a16, &bytesRead);
>      if (NS_FAILED(rv)) return rv;
>      if (bytesRead != sizeof *a16)
>          return NS_ERROR_FAILURE;
> +    *a16 = mozilla::NativeEndian::swapToBigEndian(*a16);

In a Read method, this should be swapping FROM big endian, no? (Here and below.)
Attachment #733758 - Flags: review?(jfkthame)
Attached patch v2 (obsolete) — Splinter Review
Attachment #740200 - Flags: review?(jfkthame)
Comment on attachment 740200 [details] [diff] [review]
v2

Review of attachment 740200 [details] [diff] [review]:
-----------------------------------------------------------------

::: gfx/thebes/gfxFontUtils.cpp
@@ +1111,5 @@
>      
>      // -- string data, located after the name records, stored in big-endian form
>      PRUnichar *strData = reinterpret_cast<PRUnichar*>(nameRecord);
>  
> +    mozilla::NativeEndian::copyAndSwapToBigEndian(strData, aName.BeginReading(), aName.Length());

This line seems very long - could we wrap it, please?

::: gfx/thebes/gfxFontUtils.h
@@ +339,5 @@
>  struct AutoSwap_PRUint16 {
>  #ifdef __SUNPRO_CC
>      AutoSwap_PRUint16& operator = (const uint16_t aValue)
> +    {
> +        this->value = mozilla::NativeEndian::swapFromBigEndian(aValue);

On looking at this again, I think what we really should do is to use swapToBigEndian when -assigning- the value field in these AutoSwap types, as in this case we're being passed a native-endian argument as aValue, and the AutoSwap_* struct expects its value field to always be bigendian.

(So this line was correct last time - sorry!)

@@ +346,4 @@
>  #else
> +    AutoSwap_PRUint16(uint16_t aValue)
> +    {
> +        value = mozilla::NativeEndian::swapFromBigEndian(aValue);

Same here...

@@ +351,4 @@
>  #endif
> +    operator uint16_t() const
> +    {
> +        return mozilla::NativeEndian::swapFromBigEndian(value);

...but then the cast operators that -retrieve- the value need to convert FROM the stored bigendian field to native-endian for their return value. So swapFromBigEndian is correct here.

Same applies throughout these structs, of course. Sorry I didn't think this through clearly and address the setting/getting distinction last time I looked at it.

@@ +371,5 @@
>  struct AutoSwap_PRInt16 {
>  #ifdef __SUNPRO_CC
>      AutoSwap_PRInt16& operator = (const int16_t aValue)
> +    {
> +        this->value = mozilla::NativeEndian::swapFromBigEndian(uint16_t(aValue));

We should probably have an explicit cast when assigning the (unsigned) result of swapFromBigEndian to the (signed) value field in these methods.

@@ +383,4 @@
>  #endif
> +    operator int16_t() const
> +    {
> +        return mozilla::NativeEndian::swapFromBigEndian(uint16_t(value));

And similarly for the signed return values.
Attachment #740200 - Flags: review?(jfkthame)
Attached patch v3Splinter Review
Attachment #740200 - Attachment is obsolete: true
Attachment #740758 - Flags: review?(jfkthame)
Attachment #740758 - Flags: review?(jfkthame) → review+
I notice you didn't add explicit signed/unsigned casts where we're using the "unsigned" functions on values declared as signed, etc -- I guess that's OK, unless a compiler decides to issue warnings for them, in which case we'll need to add the typecasts.
https://hg.mozilla.org/mozilla-central/rev/1541b06b7a6b
Status: NEW → RESOLVED
Closed: 11 years ago
Resolution: --- → FIXED
Depends on: 866428
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: