Skip to content

Commit

Permalink
Bug 1459722 - Remove zxx_stream. r=froydnj
Browse files Browse the repository at this point in the history
It was necessary back when we were doing decompression from a signal
handler, because we couldn't then have zlib call malloc, but we don't
do that anymore, so the whole wrapping is effectively unused.

With the wrapping gone, we manually initialize the zalloc, zfree and
opaque fields, as specified in the zlib documentation.
  • Loading branch information
glandium committed May 10, 2018
1 parent e487432 commit 3449797
Show file tree
Hide file tree
Showing 4 changed files with 12 additions and 140 deletions.
2 changes: 1 addition & 1 deletion mozglue/linker/Mappable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ MappableExtractFile::Create(const char *name, Zip *zip, Zip::Stream *stream)
return nullptr;
}

zxx_stream zStream = stream->GetZStream(buffer);
z_stream zStream = stream->GetZStream(buffer);

/* Decompress */
if (inflateInit2(&zStream, -MAX_WBITS) != Z_OK) {
Expand Down
2 changes: 1 addition & 1 deletion mozglue/linker/Mappable.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ class MappableDeflate: public Mappable
mozilla::UniquePtr<_MappableBuffer> buffer;

/* Zlib data */
zxx_stream zStream;
z_stream zStream;
};

#endif /* Mappable_h */
5 changes: 4 additions & 1 deletion mozglue/linker/Zip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,11 +205,14 @@ Zip::VerifyCRCs() const
DEBUG_LOG(" STORE size=%d crc=%08x", int(entry->compressedSize), crc);

} else if (entry->compression == Stream::Type::DEFLATE) {
zxx_stream zstream;
z_stream zstream;
Bytef buffer[1024];
zstream.avail_in = entry->compressedSize;
zstream.next_in = reinterpret_cast<Bytef *>(
const_cast<void *>(file->GetData()));
zstream.zalloc = nullptr;
zstream.zfree = nullptr;
zstream.opaque = nullptr;

if (inflateInit2(&zstream, -MAX_WBITS) != Z_OK) {
return false;
Expand Down
143 changes: 6 additions & 137 deletions mozglue/linker/Zip.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,140 +15,6 @@
#include "mozilla/RefCounted.h"
#include "mozilla/RefPtr.h"

/**
* Helper class wrapping z_stream to avoid malloc() calls during
* inflate. Do not use for deflate.
* inflateInit allocates two buffers:
* - one for its internal state, which is "approximately 10K bytes" according
* to inflate.h from zlib.
* - one for the compression window, which depends on the window size passed
* to inflateInit2, but is never greater than 32K (1 << MAX_WBITS).
* Those buffers are created at instantiation time instead of when calling
* inflateInit2. When inflateInit2 is called, it will call zxx_stream::Alloc
* to get both these buffers. zxx_stream::Alloc will choose one of the
* pre-allocated buffers depending on the requested size.
*/
class zxx_stream: public z_stream
{
public:
/* Forward declaration */
class StaticAllocator;

explicit zxx_stream(StaticAllocator *allocator_=nullptr)
: allocator(allocator_)
{
memset(this, 0, sizeof(z_stream));
zalloc = Alloc;
zfree = Free;
opaque = this;
}

private:
static void *Alloc(void *data, uInt items, uInt size)
{
zxx_stream *zStream = reinterpret_cast<zxx_stream *>(data);
if (zStream->allocator) {
return zStream->allocator->Alloc(items, size);
}
size_t buf_size = items * size;
return ::operator new(buf_size);
}

static void Free(void *data, void *ptr)
{
zxx_stream *zStream = reinterpret_cast<zxx_stream *>(data);
if (zStream->allocator) {
zStream->allocator->Free(ptr);
} else {
::operator delete(ptr);
}
}

/**
* Helper class for each buffer in StaticAllocator.
*/
template <size_t Size>
class ZStreamBuf
{
public:
ZStreamBuf() : inUse(false) { }

bool get(char*& out)
{
if (!inUse) {
inUse = true;
out = buf;
return true;
} else {
return false;
}
}

void Release()
{
memset(buf, 0, Size);
inUse = false;
}

bool Equals(const void *other) { return other == buf; }

static const size_t size = Size;

private:
char buf[Size];
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 <= stateBuf1.size) {
char* res = nullptr;
if (stateBuf1.get(res) || stateBuf2.get(res)) {
return res;
}
MOZ_CRASH("ZStreamBuf already in use");
} else if (items * size == windowBuf1.size) {
char* res = nullptr;
if (windowBuf1.get(res) || windowBuf2.get(res)) {
return res;
}
MOZ_CRASH("ZStreamBuf already in use");
} else {
MOZ_CRASH("No ZStreamBuf for allocation");
}
}

void Free(void *ptr)
{
if (stateBuf1.Equals(ptr)) {
stateBuf1.Release();
} else if (stateBuf2.Equals(ptr)) {
stateBuf2.Release();
}else if (windowBuf1.Equals(ptr)) {
windowBuf1.Release();
} else if (windowBuf2.Equals(ptr)) {
windowBuf2.Release();
} else {
MOZ_CRASH("Pointer doesn't match a ZStreamBuf");
}
}

// 0x3000 is an arbitrary size above 10K.
ZStreamBuf<0x3000> stateBuf1, stateBuf2;
ZStreamBuf<1 << MAX_WBITS> windowBuf1, windowBuf2;
};

private:
StaticAllocator *allocator;
};

/**
* Forward declaration
*/
Expand Down Expand Up @@ -226,18 +92,21 @@ class Zip: public mozilla::external::AtomicRefCounted<Zip>
Type GetType() { return type; }

/**
* Returns a zxx_stream for use with inflate functions using the given
* Returns a z_stream for use with inflate functions using the given
* buffer as inflate output. The caller is expected to allocate enough
* memory for the Stream uncompressed size.
*/
zxx_stream GetZStream(void *buf)
z_stream GetZStream(void *buf)
{
zxx_stream zStream;
z_stream zStream;
zStream.avail_in = compressedSize;
zStream.next_in = reinterpret_cast<Bytef *>(
const_cast<void *>(compressedBuf));
zStream.avail_out = uncompressedSize;
zStream.next_out = static_cast<Bytef *>(buf);
zStream.zalloc = nullptr;
zStream.zfree = nullptr;
zStream.opaque = nullptr;
return zStream;
}

Expand Down

0 comments on commit 3449797

Please sign in to comment.