Cache data size in CJBig2_Image Profiling shows GetLine() and other CJBig2_Image methods are all slow because almost every access results in a `data_` size calculation. Avoid that by caching the size. Change-Id: I96dc0341e0533caf6af3f02a40caecb25cf3fbc3 Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/147490 Reviewed-by: Tom Sepez <tsepez@chromium.org> Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fxcodec/jbig2/jbig2_image.cpp b/core/fxcodec/jbig2/jbig2_image.cpp index a197ad8..cae127f 100644 --- a/core/fxcodec/jbig2/jbig2_image.cpp +++ b/core/fxcodec/jbig2/jbig2_image.cpp
@@ -82,8 +82,9 @@ height_ = h; stride_ = stride_pixels / 8; CHECK_GE(stride_, 0); - data_.Reset(std::unique_ptr<uint8_t, FxFreeDeleter>( - FX_Alloc2D(uint8_t, stride_, height_))); + data_size_ = Fx2DSizeOrDie(stride_, height_); + data_.Reset( + std::unique_ptr<uint8_t, FxFreeDeleter>(FX_Alloc(uint8_t, data_size_))); } CJBig2_Image::CJBig2_Image(int32_t w, @@ -112,18 +113,22 @@ height_ = h; stride_ = stride; CHECK_GE(stride_, 0); + data_size_ = Fx2DSizeOrDie(stride_, height_); data_.Reset(pBuf.data()); } CJBig2_Image::CJBig2_Image(const CJBig2_Image& other) - : width_(other.width_), height_(other.height_), stride_(other.stride_) { + : width_(other.width_), + height_(other.height_), + stride_(other.stride_), + data_size_(other.data_size_) { auto other_span = other.span(); if (other_span.empty()) { return; } - data_.Reset(std::unique_ptr<uint8_t, FxFreeDeleter>( - FX_Alloc2D(uint8_t, stride_, height_))); + data_.Reset( + std::unique_ptr<uint8_t, FxFreeDeleter>(FX_Alloc(uint8_t, data_size_))); fxcrt::spancpy(span(), other_span); } @@ -138,14 +143,12 @@ // SAFETY: If `data_` is owned, then `this` must have allocate the right // amount. If `data_` is not owned, then safety requires correctness from the // caller that constructed `this`. - return UNSAFE_BUFFERS( - pdfium::span(data_.Get(), Fx2DSizeOrDie(stride_, height_))); + return UNSAFE_BUFFERS(pdfium::span(data_.Get(), data_size_)); } pdfium::span<uint8_t> CJBig2_Image::span() { // SAFETY: Same as const-version of span() above. - return UNSAFE_BUFFERS( - pdfium::span(data_.Get(), Fx2DSizeOrDie(stride_, height_))); + return UNSAFE_BUFFERS(pdfium::span(data_.Get(), data_size_)); } int CJBig2_Image::GetPixel(int32_t x, pdfium::span<const uint8_t> line) const { @@ -272,9 +275,8 @@ return std::nullopt; } - FX_SAFE_SIZE_T size = stride_; - size *= y; - return size.ValueOrDie(); + // Since `y` is in [0, height), this is safe without `FX_SAFE_SIZE_T`. + return static_cast<size_t>(stride_) * static_cast<size_t>(y); } void CJBig2_Image::SubImageFast(uint32_t x, @@ -333,7 +335,7 @@ return; } - // Won't die unless kMaxImageBytes were to be increased someday. + // Won't die unless `kMaxImageBytes` were to be increased someday. const size_t current_size = Fx2DSizeOrDie(height_, stride_); const size_t desired_size = Fx2DSizeOrDie(h, stride_); @@ -346,10 +348,11 @@ FX_Alloc(uint8_t, desired_size))); fxcrt::spancpy(span(), external_buffer); } - // NOTE: Must update `height_` first, so a subsequent span() call will create - // a span that includes the expanded portion of memory, which needs to be - // filled. Do not reuse other spans here. + // NOTE: Must update `data_size_` first, so a subsequent span() call will + // create a span that includes the expanded portion of memory, which needs to + // be filled. Do not reuse other spans here. height_ = h; + data_size_ = desired_size; std::ranges::fill(span().subspan(current_size), v ? 0xff : 0); }
diff --git a/core/fxcodec/jbig2/jbig2_image.h b/core/fxcodec/jbig2/jbig2_image.h index bd7893e..69935a5 100644 --- a/core/fxcodec/jbig2/jbig2_image.h +++ b/core/fxcodec/jbig2/jbig2_image.h
@@ -110,6 +110,7 @@ int32_t width_ = 0; // 1-bit pixels int32_t height_ = 0; // lines int32_t stride_ = 0; // bytes, must be multiple of 4. + size_t data_size_ = 0; // Total cached span size }; #endif // CORE_FXCODEC_JBIG2_JBIG2_IMAGE_H_