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;
|
||||||
};
|
};
|
||||||
|
|
||||||
ZStreamBuf<0x3000> stateBuf; // 0x3000 is an arbitrary size above 10K.
|
public:
|
||||||
ZStreamBuf<1 << MAX_WBITS> windowBuf;
|
/**
|
||||||
|
* 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<1 << MAX_WBITS> windowBuf;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
StaticAllocator *allocator;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue