Avoid static storage. Also keep as many destinations as possible,

and keep them together on the wheel during "cold cache" startup.

committer: jreiser <jreiser> 978729012 +0000
This commit is contained in:
John Reiser
2001-01-05 21:10:12 +00:00
parent 8e90fd0b63
commit 766b3edeee
+63 -30
View File
@@ -1,4 +1,4 @@
/* ctjo.h -- filter CTO implementation /* ctjor.h -- filter CTO implementation; renumber destinations MRU
This file is part of the UPX executable compressor. This file is part of the UPX executable compressor.
@@ -32,19 +32,41 @@
// //
**************************************************************************/ **************************************************************************/
#ifdef U //{ #ifdef U //{
static int const N_LRU = 1024; // does not have to be a power of 2 static int const N_MRU = 1024; // does not have to be a power of 2
static unsigned lru[N_LRU];
static int hand; // Adaptively remember recent destinations.
static void
update_mru(
unsigned const jc, // destination address
int const kh, // mru[kh] is slot where found
unsigned mru[N_MRU], // circular buffer of most recent destinations
int &hand, // mru[hand] is most recent destination
int &tail // mru[tail] is beyond oldest destination ("cold cache" startup)
)
{
if (0 > --hand) {
hand = N_MRU -1;
}
unsigned const t = mru[hand]; // entry which will be overwritten by jc
if (0!=t) { // have seen at least N_MRU destinations
mru[kh] = t;
}
else { // "cold cache": keep active region contiguous
if (0 > --tail) {
tail = N_MRU -1;
}
mru[kh] = mru[tail];
}
mru[hand] = jc;
}
#endif //} #endif //}
static int F(Filter *f) static int F(Filter *f)
{ {
#ifdef U #ifdef U
// filter // filter
upx_byte *b = f->buf; upx_byte *const b = f->buf;
const unsigned addvalue = f->addvalue; const unsigned addvalue = f->addvalue;
hand = 0;
memset(&lru[0], 0, sizeof(lru));
#else #else
// scan // scan
const upx_byte *b = f->buf; const upx_byte *b = f->buf;
@@ -57,6 +79,12 @@ static int F(Filter *f)
unsigned calls = 0, noncalls = 0, noncalls2 = 0; unsigned calls = 0, noncalls = 0, noncalls2 = 0;
unsigned lastnoncall = size, lastcall = 0; unsigned lastnoncall = size, lastcall = 0;
#ifdef U //{
int hand = 0, tail = 0;
unsigned mru[N_MRU];
memset(&mru[0], 0, sizeof(mru));
#endif //}
// FIXME: We must fit into 8MB because we steal one bit. // FIXME: We must fit into 8MB because we steal one bit.
// find a 16MB large empty address space // find a 16MB large empty address space
if (f->forced_cto >= 0 && f->forced_cto <= 255) if (f->forced_cto >= 0 && f->forced_cto <= 255)
@@ -123,7 +151,7 @@ static int F(Filter *f)
#ifdef U #ifdef U
if (COND2(b,lastcall,ic,ic-1,ic)) { // 6-byte Jcc <disp32> if (COND2(b,lastcall,ic,ic-1,ic)) { // 6-byte Jcc <disp32>
// Prefix 0x0f is constant, but opcode condition 0x80..0x8f // Prefix 0x0f is constant, but opcode condition 0x80..0x8f
// varies. Because we store the destination (or its lru index) // varies. Because we store the destination (or its mru index)
// in be32 big endian format, the low-addressed bytes // in be32 big endian format, the low-addressed bytes
// will tend to be constant. Swap prefix and opcode // will tend to be constant. Swap prefix and opcode
// so that constants are together for better compression. // so that constants are together for better compression.
@@ -136,28 +164,29 @@ static int F(Filter *f)
// FIXME [?]: Extend to 8 bytes if "ADD ESP, byte 4*n" follows CALL. // FIXME [?]: Extend to 8 bytes if "ADD ESP, byte 4*n" follows CALL.
// This will require two related cto's (consecutive, or otherwise). // This will require two related cto's (consecutive, or otherwise).
{ {
// Recode the destination: narrower lru indices // Recode the destination: narrower mru indices
// should compress better than wider addresses. // should compress better than wider addresses.
int k; int k;
for (k = 0; k < N_LRU; ++k) { for (k = 0; k < N_MRU; ++k) {
int kh = hand + k; int kh = hand + k;
if (N_LRU <= kh) { if (N_MRU <= kh) {
kh -= N_LRU; kh -= N_MRU;
} }
if (lru[kh] == jc) { // destination was seen recently if (mru[kh] == jc) { // destination was seen recently
set_be32(b+ic+1,((k<<1)|0)+cto); set_be32(b+ic+1,((k<<1)|0)+cto);
update_mru(jc, kh, mru, hand, tail);
break; break;
} }
} }
if (k == N_LRU) { // loop failed; jc is not in lru[] if (k == N_MRU) { // loop failed; jc is not in mru[]
set_be32(b+ic+1,((jc<<1)|1)+cto); set_be32(b+ic+1,((jc<<1)|1)+cto);
}
}
// Adaptively remember recent destinations. // Adaptively remember recent destinations.
if (0 > --hand) { if (0 > --hand) {
hand = N_LRU -1; hand = N_MRU -1;
}
mru[hand] = jc;
}
} }
lru[hand] = jc;
#endif #endif
if (ic - lastnoncall < 5) if (ic - lastnoncall < 5)
{ {
@@ -212,16 +241,18 @@ static int F(Filter *f)
#ifdef U #ifdef U
static int U(Filter *f) static int U(Filter *f)
{ {
upx_byte *b = f->buf; unsigned ic, jc;
upx_byte *const b = f->buf;
const unsigned size5 = f->buf_len - 5; const unsigned size5 = f->buf_len - 5;
const unsigned addvalue = f->addvalue; const unsigned addvalue = f->addvalue;
const unsigned cto = f->cto << 24; const unsigned cto = f->cto << 24;
unsigned lastcall = 0; unsigned lastcall = 0;
int hand = 0, tail = 0;
unsigned mru[N_MRU];
memset(&mru[0], 0, sizeof(mru));
unsigned ic, jc; for (ic = 0; ic < size5; ic++) {
hand = 0;
for (ic = 0; ic < size5; ic++)
if (CONDU(b,ic,lastcall)) if (CONDU(b,ic,lastcall))
{ {
jc = get_be32(b+ic+1) - cto; jc = get_be32(b+ic+1) - cto;
@@ -229,19 +260,20 @@ static int U(Filter *f)
{ {
if (1&jc) { // 1st time at this destination if (1&jc) { // 1st time at this destination
jc = (jc >> 1) - addvalue; jc = (jc >> 1) - addvalue;
if (0 > --hand) {
hand = N_MRU -1;
}
mru[hand] = jc;
} }
else { // not 1st time at this destination else { // not 1st time at this destination
jc = (jc >> 1) - addvalue; jc = (jc >> 1) - addvalue;
int kh = jc + hand; int kh = jc + hand;
if (N_LRU <= kh) { if (N_MRU <= kh) {
kh -= N_LRU; kh -= N_MRU;
} }
jc = lru[kh]; jc = mru[kh];
update_mru(jc, kh, mru, hand, tail);
} }
if (0 > --hand) {
hand = N_LRU -1;
}
lru[hand] = jc;
set_le32(b+ic+1,jc-ic-1); set_le32(b+ic+1,jc-ic-1);
if (COND2(b,lastcall,ic,ic,ic-1)) { if (COND2(b,lastcall,ic,ic,ic-1)) {
@@ -258,6 +290,7 @@ static int U(Filter *f)
else else
f->noncalls++; f->noncalls++;
} }
}
return 0; return 0;
} }
#endif #endif