forked from mirrors/gecko-dev
		
	Bug 1059797 - Really share the same zlib inflate buffers for SeekableZStream chunks. r=nfroyd
This commit is contained in:
		
							parent
							
								
									a81fc4b8c8
								
							
						
					
					
						commit
						693a41b39b
					
				
					 3 changed files with 58 additions and 25 deletions
				
			
		|  | @ -72,7 +72,7 @@ SeekableZStream::DecompressChunk(void *where, size_t chunk, size_t length) | ||||||
| 
 | 
 | ||||||
|   DEBUG_LOG("DecompressChunk #%" PRIdSize " @%p (%" PRIdSize "/% " PRIdSize ")", |   DEBUG_LOG("DecompressChunk #%" PRIdSize " @%p (%" PRIdSize "/% " PRIdSize ")", | ||||||
|         chunk, where, length, chunkLen); |         chunk, where, length, chunkLen); | ||||||
|   zxx_stream zStream; |   zxx_stream zStream(&allocator); | ||||||
|   zStream.avail_in = (isLastChunk ? totalSize : uint32_t(offsetTable[chunk + 1])) |   zStream.avail_in = (isLastChunk ? totalSize : uint32_t(offsetTable[chunk + 1])) | ||||||
|                      - uint32_t(offsetTable[chunk]); |                      - uint32_t(offsetTable[chunk]); | ||||||
|   zStream.next_in = const_cast<Bytef *>(buffer + uint32_t(offsetTable[chunk])); |   zStream.next_in = const_cast<Bytef *>(buffer + uint32_t(offsetTable[chunk])); | ||||||
|  |  | ||||||
|  | @ -139,6 +139,9 @@ private: | ||||||
| 
 | 
 | ||||||
|   /* Deflate dictionary */ |   /* Deflate dictionary */ | ||||||
|   Array<unsigned char> dictionary; |   Array<unsigned char> dictionary; | ||||||
|  | 
 | ||||||
|  |   /* Special allocator for inflate to use the same buffers for every chunk */ | ||||||
|  |   zxx_stream::StaticAllocator allocator; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| inline void | inline void | ||||||
|  |  | ||||||
|  | @ -12,7 +12,6 @@ | ||||||
| #include "Utils.h" | #include "Utils.h" | ||||||
| #include "mozilla/Assertions.h" | #include "mozilla/Assertions.h" | ||||||
| #include "mozilla/RefPtr.h" | #include "mozilla/RefPtr.h" | ||||||
| #include "mozilla/UniquePtr.h" |  | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Helper class wrapping z_stream to avoid malloc() calls during |  * Helper class wrapping z_stream to avoid malloc() calls during | ||||||
|  | @ -30,7 +29,12 @@ | ||||||
| class zxx_stream: public z_stream | class zxx_stream: public z_stream | ||||||
| { | { | ||||||
| public: | public: | ||||||
|   zxx_stream() { |   /* Forward declaration */ | ||||||
|  |   class StaticAllocator; | ||||||
|  | 
 | ||||||
|  |   explicit zxx_stream(StaticAllocator *allocator_=nullptr) | ||||||
|  |   : allocator(allocator_) | ||||||
|  |   { | ||||||
|     memset(this, 0, sizeof(z_stream)); |     memset(this, 0, sizeof(z_stream)); | ||||||
|     zalloc = Alloc; |     zalloc = Alloc; | ||||||
|     zfree = Free; |     zfree = Free; | ||||||
|  | @ -40,45 +44,38 @@ public: | ||||||
| private: | private: | ||||||
|   static void *Alloc(void *data, uInt items, uInt size) |   static void *Alloc(void *data, uInt items, uInt size) | ||||||
|   { |   { | ||||||
|     size_t buf_size = items * size; |  | ||||||
|     zxx_stream *zStream = reinterpret_cast<zxx_stream *>(data); |     zxx_stream *zStream = reinterpret_cast<zxx_stream *>(data); | ||||||
| 
 |     if (zStream->allocator) { | ||||||
|     if (items == 1 && buf_size <= zStream->stateBuf.size) { |       return zStream->allocator->Alloc(items, size); | ||||||
|       return zStream->stateBuf.get(); |  | ||||||
|     } else if (buf_size == zStream->windowBuf.size) { |  | ||||||
|       return zStream->windowBuf.get(); |  | ||||||
|     } else { |  | ||||||
|       MOZ_CRASH("No ZStreamBuf for allocation"); |  | ||||||
|     } |     } | ||||||
|  |     size_t buf_size = items * size; | ||||||
|  |     return ::operator new(buf_size); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   static void Free(void *data, void *ptr) |   static void Free(void *data, void *ptr) | ||||||
|   { |   { | ||||||
|     zxx_stream *zStream = reinterpret_cast<zxx_stream *>(data); |     zxx_stream *zStream = reinterpret_cast<zxx_stream *>(data); | ||||||
| 
 |     if (zStream->allocator) { | ||||||
|     if (zStream->stateBuf.Equals(ptr)) { |       zStream->allocator->Free(ptr); | ||||||
|       zStream->stateBuf.Release(); |  | ||||||
|     } else if (zStream->windowBuf.Equals(ptr)) { |  | ||||||
|       zStream->windowBuf.Release(); |  | ||||||
|     } else { |     } else { | ||||||
|       MOZ_CRASH("Pointer doesn't match a ZStreamBuf"); |       ::operator delete(ptr); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /**
 |   /**
 | ||||||
|    * Helper class for each buffer. |    * Helper class for each buffer in StaticAllocator. | ||||||
|    */ |    */ | ||||||
|   template <size_t Size> |   template <size_t Size> | ||||||
|   class ZStreamBuf |   class ZStreamBuf | ||||||
|   { |   { | ||||||
|   public: |   public: | ||||||
|     ZStreamBuf() : buf(new char[Size]), inUse(false) { } |     ZStreamBuf() : inUse(false) { } | ||||||
| 
 | 
 | ||||||
|     char *get() |     char *get() | ||||||
|     { |     { | ||||||
|       if (!inUse) { |       if (!inUse) { | ||||||
|         inUse = true; |         inUse = true; | ||||||
|         return buf.get(); |         return buf; | ||||||
|       } else { |       } else { | ||||||
|         MOZ_CRASH("ZStreamBuf already in use"); |         MOZ_CRASH("ZStreamBuf already in use"); | ||||||
|       } |       } | ||||||
|  | @ -86,21 +83,54 @@ private: | ||||||
| 
 | 
 | ||||||
|     void Release() |     void Release() | ||||||
|     { |     { | ||||||
|       memset(buf.get(), 0, Size); |       memset(buf, 0, Size); | ||||||
|       inUse = false; |       inUse = false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     bool Equals(const void *other) { return other == buf.get(); } |     bool Equals(const void *other) { return other == buf; } | ||||||
| 
 | 
 | ||||||
|     static const size_t size = Size; |     static const size_t size = Size; | ||||||
| 
 | 
 | ||||||
|   private: |   private: | ||||||
|     mozilla::UniquePtr<char[]> buf; |     char buf[Size]; | ||||||
|     bool inUse; |     bool inUse; | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|  | public: | ||||||
|  |   /**
 | ||||||
|  |    * Special allocator that uses static buffers to allocate from. | ||||||
|  |    */ | ||||||
|  |   class StaticAllocator | ||||||
|  |   { | ||||||
|  |   public: | ||||||
|  |     void *Alloc(uInt items, uInt size) | ||||||
|  |     { | ||||||
|  |       if (items == 1 && size <= stateBuf.size) { | ||||||
|  |         return stateBuf.get(); | ||||||
|  |       } else if (items * size == windowBuf.size) { | ||||||
|  |         return windowBuf.get(); | ||||||
|  |       } else { | ||||||
|  |         MOZ_CRASH("No ZStreamBuf for allocation"); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     void Free(void *ptr) | ||||||
|  |     { | ||||||
|  |       if (stateBuf.Equals(ptr)) { | ||||||
|  |         stateBuf.Release(); | ||||||
|  |       } else if (windowBuf.Equals(ptr)) { | ||||||
|  |         windowBuf.Release(); | ||||||
|  |       } else { | ||||||
|  |         MOZ_CRASH("Pointer doesn't match a ZStreamBuf"); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     ZStreamBuf<0x3000> stateBuf; // 0x3000 is an arbitrary size above 10K.
 |     ZStreamBuf<0x3000> stateBuf; // 0x3000 is an arbitrary size above 10K.
 | ||||||
|     ZStreamBuf<1 << MAX_WBITS> windowBuf; |     ZStreamBuf<1 << MAX_WBITS> windowBuf; | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |   StaticAllocator *allocator; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Mike Hommey
						Mike Hommey