зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1084177 - Maintain only one zlib compression context per helper thread. r=njn
--HG-- extra : rebase_source : 0966f6cbfc1c8548b00ba5745b20136a6e2aad10
This commit is contained in:
Родитель
c3e46a1ad1
Коммит
7e524d721b
|
@ -1752,7 +1752,7 @@ ScriptSource::setSourceCopy(ExclusiveContext *cx, SourceBufferHolder &srcBuf,
|
|||
}
|
||||
|
||||
SourceCompressionTask::ResultType
|
||||
SourceCompressionTask::work()
|
||||
SourceCompressionTask::work(Compressor &comp)
|
||||
{
|
||||
// Try to keep the maximum memory usage down by only allocating half the
|
||||
// size of the string, first.
|
||||
|
@ -1762,8 +1762,7 @@ SourceCompressionTask::work()
|
|||
if (!compressed)
|
||||
return OOM;
|
||||
|
||||
Compressor comp(reinterpret_cast<const unsigned char *>(ss->uncompressedChars()), inputBytes);
|
||||
if (!comp.init())
|
||||
if (!comp.prepare(reinterpret_cast<const unsigned char *>(ss->uncompressedChars()), inputBytes))
|
||||
return OOM;
|
||||
|
||||
comp.setOutput((unsigned char *) compressed, firstSize);
|
||||
|
|
|
@ -6,8 +6,13 @@
|
|||
|
||||
#include "vm/Compression.h"
|
||||
|
||||
#include "mozilla/DebugOnly.h"
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#include "js/Utility.h"
|
||||
|
||||
using mozilla::DebugOnly;
|
||||
using namespace js;
|
||||
|
||||
static void *
|
||||
|
@ -22,79 +27,91 @@ zlib_free(void *cx, void *addr)
|
|||
js_free(addr);
|
||||
}
|
||||
|
||||
Compressor::Compressor(const unsigned char *inp, size_t inplen)
|
||||
: inp(inp),
|
||||
inplen(inplen),
|
||||
outbytes(0),
|
||||
initialized(false)
|
||||
{
|
||||
MOZ_ASSERT(inplen > 0);
|
||||
zs.opaque = nullptr;
|
||||
zs.next_in = (Bytef *)inp;
|
||||
zs.avail_in = 0;
|
||||
zs.next_out = nullptr;
|
||||
zs.avail_out = 0;
|
||||
zs.zalloc = zlib_alloc;
|
||||
zs.zfree = zlib_free;
|
||||
}
|
||||
|
||||
|
||||
Compressor::~Compressor()
|
||||
{
|
||||
if (initialized) {
|
||||
int ret = deflateEnd(&zs);
|
||||
int ret = deflateEnd(zs);
|
||||
if (ret != Z_OK) {
|
||||
// If we finished early, we can get a Z_DATA_ERROR.
|
||||
MOZ_ASSERT(ret == Z_DATA_ERROR);
|
||||
MOZ_ASSERT(uInt(zs.next_in - inp) < inplen || !zs.avail_out);
|
||||
MOZ_ASSERT(uInt(zs->next_in - inp) < inplen || !zs->avail_out);
|
||||
}
|
||||
}
|
||||
js_free(zs);
|
||||
}
|
||||
|
||||
bool
|
||||
Compressor::init()
|
||||
Compressor::prepare(const unsigned char *inp_, size_t inplen_)
|
||||
{
|
||||
if (inplen >= UINT32_MAX)
|
||||
return false;
|
||||
// zlib is slow and we'd rather be done compression sooner
|
||||
// even if it means decompression is slower which penalizes
|
||||
// Function.toString()
|
||||
int ret = deflateInit(&zs, Z_BEST_SPEED);
|
||||
if (ret != Z_OK) {
|
||||
MOZ_ASSERT(ret == Z_MEM_ERROR);
|
||||
MOZ_ASSERT(inplen_ > 0);
|
||||
|
||||
if (inplen_ >= UINT32_MAX)
|
||||
return false;
|
||||
|
||||
if (!zs) {
|
||||
zs = js_pod_malloc<z_stream>();
|
||||
if (!zs)
|
||||
return false;
|
||||
zs->zalloc = zlib_alloc;
|
||||
zs->zfree = zlib_free;
|
||||
}
|
||||
initialized = true;
|
||||
|
||||
inp = inp_;
|
||||
inplen = inplen_;
|
||||
outbytes = 0;
|
||||
|
||||
zs->opaque = nullptr;
|
||||
zs->next_in = (Bytef *)inp;
|
||||
zs->avail_in = 0;
|
||||
zs->next_out = nullptr;
|
||||
zs->avail_out = 0;
|
||||
|
||||
if (initialized) {
|
||||
DebugOnly<int> ret = deflateReset(zs);
|
||||
MOZ_ASSERT(ret == Z_OK);
|
||||
} else {
|
||||
// zlib is slow and we'd rather be done compression sooner even if it
|
||||
// means decompression is slower which penalizes Function.toString()
|
||||
int ret = deflateInit(zs, Z_BEST_SPEED);
|
||||
if (ret != Z_OK) {
|
||||
MOZ_ASSERT(ret == Z_MEM_ERROR);
|
||||
return false;
|
||||
}
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Compressor::setOutput(unsigned char *out, size_t outlen)
|
||||
{
|
||||
MOZ_ASSERT(initialized);
|
||||
MOZ_ASSERT(outlen > outbytes);
|
||||
zs.next_out = out + outbytes;
|
||||
zs.avail_out = outlen - outbytes;
|
||||
zs->next_out = out + outbytes;
|
||||
zs->avail_out = outlen - outbytes;
|
||||
}
|
||||
|
||||
Compressor::Status
|
||||
Compressor::compressMore()
|
||||
{
|
||||
MOZ_ASSERT(zs.next_out);
|
||||
uInt left = inplen - (zs.next_in - inp);
|
||||
MOZ_ASSERT(initialized);
|
||||
MOZ_ASSERT(zs->next_out);
|
||||
uInt left = inplen - (zs->next_in - inp);
|
||||
bool done = left <= CHUNKSIZE;
|
||||
if (done)
|
||||
zs.avail_in = left;
|
||||
else if (zs.avail_in == 0)
|
||||
zs.avail_in = CHUNKSIZE;
|
||||
Bytef *oldout = zs.next_out;
|
||||
int ret = deflate(&zs, done ? Z_FINISH : Z_NO_FLUSH);
|
||||
outbytes += zs.next_out - oldout;
|
||||
zs->avail_in = left;
|
||||
else if (zs->avail_in == 0)
|
||||
zs->avail_in = CHUNKSIZE;
|
||||
Bytef *oldout = zs->next_out;
|
||||
int ret = deflate(zs, done ? Z_FINISH : Z_NO_FLUSH);
|
||||
outbytes += zs->next_out - oldout;
|
||||
if (ret == Z_MEM_ERROR) {
|
||||
zs.avail_out = 0;
|
||||
zs->avail_out = 0;
|
||||
return OOM;
|
||||
}
|
||||
if (ret == Z_BUF_ERROR || (done && ret == Z_OK)) {
|
||||
MOZ_ASSERT(zs.avail_out == 0);
|
||||
MOZ_ASSERT(zs->avail_out == 0);
|
||||
return MOREOUTPUT;
|
||||
}
|
||||
MOZ_ASSERT_IF(!done, ret == Z_OK);
|
||||
|
|
|
@ -7,17 +7,17 @@
|
|||
#ifndef vm_Compression_h
|
||||
#define vm_Compression_h
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#include "jstypes.h"
|
||||
|
||||
struct z_stream_s; // from <zlib.h>
|
||||
|
||||
namespace js {
|
||||
|
||||
class Compressor
|
||||
{
|
||||
/* Number of bytes we should hand to zlib each compressMore() call. */
|
||||
static const size_t CHUNKSIZE = 2048;
|
||||
z_stream zs;
|
||||
struct z_stream_s *zs;
|
||||
const unsigned char *inp;
|
||||
size_t inplen;
|
||||
size_t outbytes;
|
||||
|
@ -31,12 +31,22 @@ class Compressor
|
|||
OOM
|
||||
};
|
||||
|
||||
Compressor(const unsigned char *inp, size_t inplen);
|
||||
Compressor()
|
||||
: zs(nullptr),
|
||||
initialized(false)
|
||||
{}
|
||||
~Compressor();
|
||||
bool init();
|
||||
/*
|
||||
* Prepare the compressor to process the string |inp| of length
|
||||
* |inplen|. Return false if initialization failed (usually OOM).
|
||||
*
|
||||
* The compressor may be reused for a different input by calling prepare()
|
||||
* again.
|
||||
*/
|
||||
bool prepare(const unsigned char *inp, size_t inplen);
|
||||
void setOutput(unsigned char *out, size_t outlen);
|
||||
size_t outWritten() const { return outbytes; }
|
||||
/* Compress some of the input. Return true if it should be called again. */
|
||||
/* Compress some of the input. Return CONTINUE if it should be called again. */
|
||||
Status compressMore();
|
||||
};
|
||||
|
||||
|
|
|
@ -1201,7 +1201,7 @@ HelperThread::handleCompressionWorkload()
|
|||
|
||||
{
|
||||
AutoUnlockHelperThreadState unlock;
|
||||
compressionTask->result = compressionTask->work();
|
||||
compressionTask->result = compressionTask->work(sourceCompressor);
|
||||
}
|
||||
|
||||
compressionTask->helperThread = nullptr;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "frontend/TokenStream.h"
|
||||
#include "jit/Ion.h"
|
||||
#include "vm/Compression.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
|
@ -306,6 +307,12 @@ struct HelperThread
|
|||
/* Any source being compressed on this thread. */
|
||||
SourceCompressionTask *compressionTask;
|
||||
|
||||
/*
|
||||
* Compressor that is used for servicing SourceCompressionTasks on this
|
||||
* thread.
|
||||
*/
|
||||
Compressor sourceCompressor;
|
||||
|
||||
/* Any GC state for background sweeping or allocating being performed. */
|
||||
GCHelperState *gcHelperState;
|
||||
|
||||
|
@ -533,7 +540,7 @@ struct SourceCompressionTask
|
|||
complete();
|
||||
}
|
||||
|
||||
ResultType work();
|
||||
ResultType work(Compressor &comp);
|
||||
bool complete();
|
||||
void abort() { abort_ = true; }
|
||||
bool active() const { return !!ss; }
|
||||
|
|
Загрузка…
Ссылка в новой задаче