From 921cc2403a9e643dfb29d70564fa435a1d79f972 Mon Sep 17 00:00:00 2001 From: Lei Zhang Date: Thu, 8 Oct 2015 15:14:24 -0700 Subject: Merge to XFA: Various changes to JBig2 cache: - Makes the cache be per-document - Keys the cache on ObjNum and stream offset instead of keying on a pointer to the data (which can result in false cache hits). - Makes it so the cache is only used for the globals stream. - Reenable the cache. R=dml@google.com TBR=dml@google.com BUG=pdfium:207 Review URL: https://codereview.chromium.org/1380243004 . (cherry picked from commit f1b88e76134808f36f16b9e53a2e9dd89b12c8fd) Review URL: https://codereview.chromium.org/1394373002 . --- core/src/fxcodec/jbig2/JBig2_Context.cpp | 80 +++++++++++++++----------------- 1 file changed, 38 insertions(+), 42 deletions(-) (limited to 'core/src/fxcodec/jbig2/JBig2_Context.cpp') diff --git a/core/src/fxcodec/jbig2/JBig2_Context.cpp b/core/src/fxcodec/jbig2/JBig2_Context.cpp index 7b11ca2e5e..bb01cb6be8 100644 --- a/core/src/fxcodec/jbig2/JBig2_Context.cpp +++ b/core/src/fxcodec/jbig2/JBig2_Context.cpp @@ -35,35 +35,26 @@ size_t GetRefAggContextSize(FX_BOOL val) { // list keeps track of the freshness of entries, with freshest ones // at the front. Even a tiny cache size like 2 makes a dramatic // difference for typical JBIG2 documents. -// -// Disabled until we can figure out how to clear cache between documents. -// https://code.google.com/p/pdfium/issues/detail?id=207 -#define DISABLE_SYMBOL_CACHE -#ifndef DISABLE_SYMBOL_CACHE static const int kSymbolDictCacheMaxSize = 2; -#endif CJBig2_Context* CJBig2_Context::CreateContext( - const uint8_t* pGlobalData, - FX_DWORD dwGlobalLength, - const uint8_t* pData, - FX_DWORD dwLength, + CPDF_StreamAcc* pGlobalStream, + CPDF_StreamAcc* pSrcStream, std::list* pSymbolDictCache, IFX_Pause* pPause) { - return new CJBig2_Context(pGlobalData, dwGlobalLength, pData, dwLength, - pSymbolDictCache, pPause); + return new CJBig2_Context(pGlobalStream, pSrcStream, pSymbolDictCache, pPause, + false); } void CJBig2_Context::DestroyContext(CJBig2_Context* pContext) { delete pContext; } -CJBig2_Context::CJBig2_Context(const uint8_t* pGlobalData, - FX_DWORD dwGlobalLength, - const uint8_t* pData, - FX_DWORD dwLength, +CJBig2_Context::CJBig2_Context(CPDF_StreamAcc* pGlobalStream, + CPDF_StreamAcc* pSrcStream, std::list* pSymbolDictCache, - IFX_Pause* pPause) + IFX_Pause* pPause, + bool bIsGlobal) : m_nSegmentDecoded(0), m_bInPage(false), m_bBufSpecified(false), @@ -72,15 +63,16 @@ CJBig2_Context::CJBig2_Context(const uint8_t* pGlobalData, m_ProcessingStatus(FXCODEC_STATUS_FRAME_READY), m_gbContext(NULL), m_dwOffset(0), - m_pSymbolDictCache(pSymbolDictCache) { - if (pGlobalData && (dwGlobalLength > 0)) { - m_pGlobalContext = new CJBig2_Context( - nullptr, 0, pGlobalData, dwGlobalLength, pSymbolDictCache, pPause); + m_pSymbolDictCache(pSymbolDictCache), + m_bIsGlobal(bIsGlobal) { + if (pGlobalStream && (pGlobalStream->GetSize() > 0)) { + m_pGlobalContext = new CJBig2_Context(nullptr, pGlobalStream, + pSymbolDictCache, pPause, true); } else { m_pGlobalContext = nullptr; } - m_pStream.reset(new CJBig2_BitStream(pData, dwLength)); + m_pStream.reset(new CJBig2_BitStream(pSrcStream)); } CJBig2_Context::~CJBig2_Context() { @@ -331,7 +323,8 @@ int32_t CJBig2_Context::parseSegmentHeader(CJBig2_Segment* pSegment) { if (m_pStream->readInteger(&pSegment->m_dwData_length) != 0) return JBIG2_ERROR_TOO_SHORT; - pSegment->m_pData = m_pStream->getPointer(); + pSegment->m_dwObjNum = m_pStream->getObjNum(); + pSegment->m_dwDataOffset = m_pStream->getOffset(); pSegment->m_State = JBIG2_SEGMENT_DATA_UNPARSED; return JBIG2_SUCCESS; } @@ -602,18 +595,21 @@ int32_t CJBig2_Context::parseSymbolDict(CJBig2_Segment* pSegment, JBIG2_memset(grContext.get(), 0, sizeof(JBig2ArithCtx) * size); } } - const uint8_t* key = pSegment->m_pData; + CJBig2_CacheKey key = + CJBig2_CacheKey(pSegment->m_dwObjNum, pSegment->m_dwDataOffset); FX_BOOL cache_hit = false; pSegment->m_nResultType = JBIG2_SYMBOL_DICT_POINTER; - for (std::list::iterator it = m_pSymbolDictCache->begin(); - it != m_pSymbolDictCache->end(); ++it) { - if (it->first == key) { - nonstd::unique_ptr copy(it->second->DeepCopy()); - pSegment->m_Result.sd = copy.release(); - m_pSymbolDictCache->push_front(*it); - m_pSymbolDictCache->erase(it); - cache_hit = true; - break; + if (m_bIsGlobal && key.first != 0) { + for (auto it = m_pSymbolDictCache->begin(); it != m_pSymbolDictCache->end(); + ++it) { + if (it->first == key) { + nonstd::unique_ptr copy(it->second->DeepCopy()); + pSegment->m_Result.sd = copy.release(); + m_pSymbolDictCache->push_front(*it); + m_pSymbolDictCache->erase(it); + cache_hit = true; + break; + } } } if (!cache_hit) { @@ -634,17 +630,17 @@ int32_t CJBig2_Context::parseSymbolDict(CJBig2_Segment* pSegment, return JBIG2_ERROR_FATAL; m_pStream->alignByte(); } -#ifndef DISABLE_SYMBOL_CACHE - nonstd::unique_ptr value = - pSegment->m_Result.sd->DeepCopy(); - if (value && kSymbolDictCacheMaxSize > 0) { - while (m_pSymbolDictCache->size() >= kSymbolDictCacheMaxSize) { - delete m_pSymbolDictCache->back().second; - m_pSymbolDictCache->pop_back(); + if (m_bIsGlobal && kSymbolDictCacheMaxSize > 0) { + nonstd::unique_ptr value = + pSegment->m_Result.sd->DeepCopy(); + if (value) { + while (m_pSymbolDictCache->size() >= kSymbolDictCacheMaxSize) { + delete m_pSymbolDictCache->back().second; + m_pSymbolDictCache->pop_back(); + } + m_pSymbolDictCache->push_front(CJBig2_CachePair(key, value.release())); } - m_pSymbolDictCache->push_front(CJBig2_CachePair(key, value.release())); } -#endif } if (wFlags & 0x0200) { pSegment->m_Result.sd->m_bContextRetained = TRUE; -- cgit v1.2.3