Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(10)

Side by Side Diff: core/src/fxcodec/jbig2/JBig2_Context.cpp

Issue 1380243004: Various changes to JBig2 cache: (Closed) Base URL: https://pdfium.googlesource.com/pdfium.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 PDFium Authors. All rights reserved. 1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 6
7 #include "JBig2_Context.h" 7 #include "JBig2_Context.h"
8 8
9 #include <list> 9 #include <list>
10 10
11 #include "JBig2_GrdProc.h" 11 #include "JBig2_GrdProc.h"
12 #include "JBig2_GrrdProc.h" 12 #include "JBig2_GrrdProc.h"
13 #include "JBig2_HtrdProc.h" 13 #include "JBig2_HtrdProc.h"
14 #include "JBig2_PddProc.h" 14 #include "JBig2_PddProc.h"
15 #include "JBig2_SddProc.h" 15 #include "JBig2_SddProc.h"
16 #include "JBig2_TrdProc.h" 16 #include "JBig2_TrdProc.h"
17 17
18 // Implement a very small least recently used (LRU) cache. It is very 18 // Implement a very small least recently used (LRU) cache. It is very
19 // common for a JBIG2 dictionary to span multiple pages in a PDF file, 19 // common for a JBIG2 dictionary to span multiple pages in a PDF file,
20 // and we do not want to decode the same dictionary over and over 20 // and we do not want to decode the same dictionary over and over
21 // again. We key off of the memory location of the dictionary. The 21 // again. We key off of the memory location of the dictionary. The
jbreiden 2015/10/07 17:50:16 not keying off memory location anymore.
22 // list keeps track of the freshness of entries, with freshest ones 22 // list keeps track of the freshness of entries, with freshest ones
23 // at the front. Even a tiny cache size like 2 makes a dramatic 23 // at the front. Even a tiny cache size like 2 makes a dramatic
24 // difference for typical JBIG2 documents. 24 // difference for typical JBIG2 documents.
25 // 25 //
26 // Disabled until we can figure out how to clear cache between documents. 26 // Disabled until we can figure out how to clear cache between documents.
Lei Zhang 2015/10/06 22:40:24 This should be deleted too.
David Lattimore 2015/10/07 22:41:53 Done.
27 // https://code.google.com/p/pdfium/issues/detail?id=207 27 // https://code.google.com/p/pdfium/issues/detail?id=207
28 #define DISABLE_SYMBOL_CACHE
29 #ifndef DISABLE_SYMBOL_CACHE 28 #ifndef DISABLE_SYMBOL_CACHE
Lei Zhang 2015/10/06 22:40:24 Do we still want to keep this then? With a proper
jbreiden 2015/10/07 17:50:17 I'd like to think that we can disable the cache an
Lei Zhang 2015/10/07 17:59:24 No, you can't. Setting it to 0 triggers compiler w
David Lattimore 2015/10/07 22:41:53 Removed DISABLE_SYMBOL_CACHE Set cache size back
30 static const int kSymbolDictCacheMaxSize = 2; 29 static const int kSymbolDictCacheMaxSize = 1;
31 #endif 30 #endif
32 31
33 CJBig2_Context* CJBig2_Context::CreateContext( 32 CJBig2_Context* CJBig2_Context::CreateContext(
34 const uint8_t* pGlobalData, 33 CPDF_StreamAcc* pGlobalStream,
35 FX_DWORD dwGlobalLength, 34 CPDF_StreamAcc* pSrcStream,
36 const uint8_t* pData,
37 FX_DWORD dwLength,
38 std::list<CJBig2_CachePair>* pSymbolDictCache, 35 std::list<CJBig2_CachePair>* pSymbolDictCache,
39 IFX_Pause* pPause) { 36 IFX_Pause* pPause) {
40 return new CJBig2_Context(pGlobalData, dwGlobalLength, pData, dwLength, 37 return new CJBig2_Context(pGlobalStream, pSrcStream, pSymbolDictCache, pPause,
41 pSymbolDictCache, pPause); 38 false);
42 } 39 }
43 40
44 void CJBig2_Context::DestroyContext(CJBig2_Context* pContext) { 41 void CJBig2_Context::DestroyContext(CJBig2_Context* pContext) {
45 delete pContext; 42 delete pContext;
46 } 43 }
47 44
48 CJBig2_Context::CJBig2_Context(const uint8_t* pGlobalData, 45 CJBig2_Context::CJBig2_Context(CPDF_StreamAcc* pGlobalStream,
49 FX_DWORD dwGlobalLength, 46 CPDF_StreamAcc* pSrcStream,
50 const uint8_t* pData,
51 FX_DWORD dwLength,
52 std::list<CJBig2_CachePair>* pSymbolDictCache, 47 std::list<CJBig2_CachePair>* pSymbolDictCache,
53 IFX_Pause* pPause) 48 IFX_Pause* pPause,
49 bool isGlobal)
54 : m_nSegmentDecoded(0), 50 : m_nSegmentDecoded(0),
55 m_bInPage(false), 51 m_bInPage(false),
56 m_bBufSpecified(false), 52 m_bBufSpecified(false),
57 m_PauseStep(10), 53 m_PauseStep(10),
58 m_pPause(pPause), 54 m_pPause(pPause),
59 m_ProcessingStatus(FXCODEC_STATUS_FRAME_READY), 55 m_ProcessingStatus(FXCODEC_STATUS_FRAME_READY),
60 m_pArithDecoder(NULL), 56 m_pArithDecoder(NULL),
61 m_gbContext(NULL), 57 m_gbContext(NULL),
62 m_dwOffset(0), 58 m_dwOffset(0),
63 m_pSymbolDictCache(pSymbolDictCache) { 59 m_pSymbolDictCache(pSymbolDictCache),
64 if (pGlobalData && (dwGlobalLength > 0)) { 60 m_IsGlobal(isGlobal) {
65 m_pGlobalContext = new CJBig2_Context( 61 if (pGlobalStream && (pGlobalStream->GetSize() > 0)) {
66 nullptr, 0, pGlobalData, dwGlobalLength, pSymbolDictCache, pPause); 62 m_pGlobalContext =
63 new CJBig2_Context(NULL, pGlobalStream, pSymbolDictCache, pPause, true);
67 } else { 64 } else {
68 m_pGlobalContext = nullptr; 65 m_pGlobalContext = nullptr;
69 } 66 }
70 67
71 m_pStream.reset(new CJBig2_BitStream(pData, dwLength)); 68 m_pStream.reset(new CJBig2_BitStream(pSrcStream));
72 } 69 }
73 70
74 CJBig2_Context::~CJBig2_Context() { 71 CJBig2_Context::~CJBig2_Context() {
75 delete m_pArithDecoder; 72 delete m_pArithDecoder;
76 m_pArithDecoder = NULL; 73 m_pArithDecoder = NULL;
77 FX_Free(m_gbContext); 74 FX_Free(m_gbContext);
78 m_gbContext = NULL; 75 m_gbContext = NULL;
79 delete m_pGlobalContext; 76 delete m_pGlobalContext;
80 m_pGlobalContext = NULL; 77 m_pGlobalContext = NULL;
81 } 78 }
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 return JBIG2_ERROR_TOO_SHORT; 315 return JBIG2_ERROR_TOO_SHORT;
319 pSegment->m_dwPage_association = cTemp; 316 pSegment->m_dwPage_association = cTemp;
320 } else { 317 } else {
321 if (m_pStream->readInteger(&pSegment->m_dwPage_association) != 0) { 318 if (m_pStream->readInteger(&pSegment->m_dwPage_association) != 0) {
322 return JBIG2_ERROR_TOO_SHORT; 319 return JBIG2_ERROR_TOO_SHORT;
323 } 320 }
324 } 321 }
325 if (m_pStream->readInteger(&pSegment->m_dwData_length) != 0) 322 if (m_pStream->readInteger(&pSegment->m_dwData_length) != 0)
326 return JBIG2_ERROR_TOO_SHORT; 323 return JBIG2_ERROR_TOO_SHORT;
327 324
328 pSegment->m_pData = m_pStream->getPointer(); 325 pSegment->m_dwObjNum = m_pStream->getObjNum();
326 pSegment->m_dwDataOffset = m_pStream->getOffset();
329 pSegment->m_State = JBIG2_SEGMENT_DATA_UNPARSED; 327 pSegment->m_State = JBIG2_SEGMENT_DATA_UNPARSED;
330 return JBIG2_SUCCESS; 328 return JBIG2_SUCCESS;
331 } 329 }
332 330
333 int32_t CJBig2_Context::parseSegmentData(CJBig2_Segment* pSegment, 331 int32_t CJBig2_Context::parseSegmentData(CJBig2_Segment* pSegment,
334 IFX_Pause* pPause) { 332 IFX_Pause* pPause) {
335 int32_t ret = ProcessingParseSegmentData(pSegment, pPause); 333 int32_t ret = ProcessingParseSegmentData(pSegment, pPause);
336 while (m_ProcessingStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE && 334 while (m_ProcessingStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE &&
337 m_pStream->getByteLeft() > 0) { 335 m_pStream->getByteLeft() > 0) {
338 ret = ProcessingParseSegmentData(pSegment, pPause); 336 ret = ProcessingParseSegmentData(pSegment, pPause);
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
438 CJBig2_HuffmanTable* Table_B5 = nullptr; 436 CJBig2_HuffmanTable* Table_B5 = nullptr;
439 int32_t i, nIndex, nRet; 437 int32_t i, nIndex, nRet;
440 CJBig2_Segment* pSeg = nullptr; 438 CJBig2_Segment* pSeg = nullptr;
441 CJBig2_Segment* pLRSeg = nullptr; 439 CJBig2_Segment* pLRSeg = nullptr;
442 FX_BOOL bUsed; 440 FX_BOOL bUsed;
443 CJBig2_Image** SDINSYMS = nullptr; 441 CJBig2_Image** SDINSYMS = nullptr;
444 JBig2ArithCtx* gbContext = nullptr; 442 JBig2ArithCtx* gbContext = nullptr;
445 JBig2ArithCtx* grContext = nullptr; 443 JBig2ArithCtx* grContext = nullptr;
446 CJBig2_ArithDecoder* pArithDecoder; 444 CJBig2_ArithDecoder* pArithDecoder;
447 CJBig2_SDDProc* pSymbolDictDecoder = new CJBig2_SDDProc(); 445 CJBig2_SDDProc* pSymbolDictDecoder = new CJBig2_SDDProc();
448 const uint8_t* key = pSegment->m_pData; 446 CJBig2_CacheKey key =
447 CJBig2_CacheKey(pSegment->m_dwObjNum, pSegment->m_dwDataOffset);
449 FX_BOOL cache_hit = false; 448 FX_BOOL cache_hit = false;
450 if (m_pStream->readShortInteger(&wFlags) != 0) { 449 if (m_pStream->readShortInteger(&wFlags) != 0) {
451 nRet = JBIG2_ERROR_TOO_SHORT; 450 nRet = JBIG2_ERROR_TOO_SHORT;
452 goto failed; 451 goto failed;
453 } 452 }
454 pSymbolDictDecoder->SDHUFF = wFlags & 0x0001; 453 pSymbolDictDecoder->SDHUFF = wFlags & 0x0001;
455 pSymbolDictDecoder->SDREFAGG = (wFlags >> 1) & 0x0001; 454 pSymbolDictDecoder->SDREFAGG = (wFlags >> 1) & 0x0001;
456 pSymbolDictDecoder->SDTEMPLATE = (wFlags >> 10) & 0x0003; 455 pSymbolDictDecoder->SDTEMPLATE = (wFlags >> 10) & 0x0003;
457 pSymbolDictDecoder->SDRTEMPLATE = (wFlags >> 12) & 0x0003; 456 pSymbolDictDecoder->SDRTEMPLATE = (wFlags >> 12) & 0x0003;
458 cSDHUFFDH = (wFlags >> 2) & 0x0003; 457 cSDHUFFDH = (wFlags >> 2) & 0x0003;
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
616 gbContext = FX_Alloc(JBig2ArithCtx, dwTemp); 615 gbContext = FX_Alloc(JBig2ArithCtx, dwTemp);
617 JBIG2_memset(gbContext, 0, sizeof(JBig2ArithCtx) * dwTemp); 616 JBIG2_memset(gbContext, 0, sizeof(JBig2ArithCtx) * dwTemp);
618 } 617 }
619 if (pSymbolDictDecoder->SDREFAGG == 1) { 618 if (pSymbolDictDecoder->SDREFAGG == 1) {
620 dwTemp = pSymbolDictDecoder->SDRTEMPLATE ? 1 << 10 : 1 << 13; 619 dwTemp = pSymbolDictDecoder->SDRTEMPLATE ? 1 << 10 : 1 << 13;
621 grContext = FX_Alloc(JBig2ArithCtx, dwTemp); 620 grContext = FX_Alloc(JBig2ArithCtx, dwTemp);
622 JBIG2_memset(grContext, 0, sizeof(JBig2ArithCtx) * dwTemp); 621 JBIG2_memset(grContext, 0, sizeof(JBig2ArithCtx) * dwTemp);
623 } 622 }
624 } 623 }
625 pSegment->m_nResultType = JBIG2_SYMBOL_DICT_POINTER; 624 pSegment->m_nResultType = JBIG2_SYMBOL_DICT_POINTER;
626 for (std::list<CJBig2_CachePair>::iterator it = m_pSymbolDictCache->begin(); 625 if (m_IsGlobal) {
627 it != m_pSymbolDictCache->end(); ++it) { 626 for (std::list<CJBig2_CachePair>::iterator it = m_pSymbolDictCache->begin();
Lei Zhang 2015/10/06 22:40:24 You can probaby use auto here.
David Lattimore 2015/10/07 22:41:53 Done.
628 if (it->first == key) { 627 it != m_pSymbolDictCache->end(); ++it) {
629 nonstd::unique_ptr<CJBig2_SymbolDict> copy(it->second->DeepCopy()); 628 if (it->first == key) {
630 pSegment->m_Result.sd = copy.release(); 629 nonstd::unique_ptr<CJBig2_SymbolDict> copy(it->second->DeepCopy());
631 m_pSymbolDictCache->push_front(*it); 630 pSegment->m_Result.sd = copy.release();
632 m_pSymbolDictCache->erase(it); 631 m_pSymbolDictCache->push_front(*it);
633 cache_hit = true; 632 m_pSymbolDictCache->erase(it);
634 break; 633 cache_hit = true;
634 break;
635 }
635 } 636 }
636 } 637 }
637 if (!cache_hit) { 638 if (!cache_hit) {
638 if (pSymbolDictDecoder->SDHUFF == 0) { 639 if (pSymbolDictDecoder->SDHUFF == 0) {
639 pArithDecoder = new CJBig2_ArithDecoder(m_pStream.get()); 640 pArithDecoder = new CJBig2_ArithDecoder(m_pStream.get());
640 pSegment->m_Result.sd = 641 pSegment->m_Result.sd =
641 pSymbolDictDecoder->decode_Arith(pArithDecoder, gbContext, grContext); 642 pSymbolDictDecoder->decode_Arith(pArithDecoder, gbContext, grContext);
642 delete pArithDecoder; 643 delete pArithDecoder;
643 if (pSegment->m_Result.sd == NULL) { 644 if (pSegment->m_Result.sd == NULL) {
644 nRet = JBIG2_ERROR_FATAL; 645 nRet = JBIG2_ERROR_FATAL;
645 goto failed; 646 goto failed;
646 } 647 }
647 m_pStream->alignByte(); 648 m_pStream->alignByte();
648 m_pStream->offset(2); 649 m_pStream->offset(2);
649 } else { 650 } else {
650 pSegment->m_Result.sd = pSymbolDictDecoder->decode_Huffman( 651 pSegment->m_Result.sd = pSymbolDictDecoder->decode_Huffman(
651 m_pStream.get(), gbContext, grContext, pPause); 652 m_pStream.get(), gbContext, grContext, pPause);
652 if (pSegment->m_Result.sd == NULL) { 653 if (pSegment->m_Result.sd == NULL) {
653 nRet = JBIG2_ERROR_FATAL; 654 nRet = JBIG2_ERROR_FATAL;
654 goto failed; 655 goto failed;
655 } 656 }
656 m_pStream->alignByte(); 657 m_pStream->alignByte();
657 } 658 }
658 #ifndef DISABLE_SYMBOL_CACHE 659 #ifndef DISABLE_SYMBOL_CACHE
jbreiden 2015/10/07 17:50:17 not sure why we have the ifdef
Lei Zhang 2015/10/07 17:59:24 Because the compiler sees a constant with a value
jbreiden 2015/10/07 19:22:51 Something seems wrong when a compiler pushes us to
Lei Zhang 2015/10/07 19:31:59 I agree Clang behaved unexpectedly in this case. I
David Lattimore 2015/10/07 22:41:53 Done.
659 nonstd::unique_ptr<CJBig2_SymbolDict> value = 660 if (m_IsGlobal && kSymbolDictCacheMaxSize > 0) {
660 pSegment->m_Result.sd->DeepCopy(); 661 nonstd::unique_ptr<CJBig2_SymbolDict> value =
661 if (value && kSymbolDictCacheMaxSize > 0) { 662 pSegment->m_Result.sd->DeepCopy();
662 while (m_pSymbolDictCache->size() >= kSymbolDictCacheMaxSize) { 663 if (value) {
663 delete m_pSymbolDictCache->back().second; 664 while (m_pSymbolDictCache->size() >= kSymbolDictCacheMaxSize) {
664 m_pSymbolDictCache->pop_back(); 665 delete m_pSymbolDictCache->back().second;
666 m_pSymbolDictCache->pop_back();
667 }
668 m_pSymbolDictCache->push_front(CJBig2_CachePair(key, value.release()));
665 } 669 }
666 m_pSymbolDictCache->push_front(CJBig2_CachePair(key, value.release()));
667 } 670 }
668 #endif 671 #endif
669 } 672 }
670 if (wFlags & 0x0200) { 673 if (wFlags & 0x0200) {
671 pSegment->m_Result.sd->m_bContextRetained = TRUE; 674 pSegment->m_Result.sd->m_bContextRetained = TRUE;
672 if (pSymbolDictDecoder->SDHUFF == 0) { 675 if (pSymbolDictDecoder->SDHUFF == 0) {
673 pSegment->m_Result.sd->m_gbContext = gbContext; 676 pSegment->m_Result.sd->m_gbContext = gbContext;
674 } 677 }
675 if (pSymbolDictDecoder->SDREFAGG == 1) { 678 if (pSymbolDictDecoder->SDREFAGG == 1) {
676 pSegment->m_Result.sd->m_grContext = grContext; 679 pSegment->m_Result.sd->m_grContext = grContext;
(...skipping 902 matching lines...) Expand 10 before | Expand all | Expand 10 after
1579 SBSYMCODES[CURTEMP].code = CURCODE; 1582 SBSYMCODES[CURTEMP].code = CURCODE;
1580 CURCODE = CURCODE + 1; 1583 CURCODE = CURCODE + 1;
1581 } 1584 }
1582 CURTEMP = CURTEMP + 1; 1585 CURTEMP = CURTEMP + 1;
1583 } 1586 }
1584 CURLEN = CURLEN + 1; 1587 CURLEN = CURLEN + 1;
1585 } 1588 }
1586 FX_Free(LENCOUNT); 1589 FX_Free(LENCOUNT);
1587 FX_Free(FIRSTCODE); 1590 FX_Free(FIRSTCODE);
1588 } 1591 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698