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

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.
@ -32,19 +32,41 @@
//
**************************************************************************/
#ifdef U //{
static int const N_LRU = 1024; // does not have to be a power of 2
static unsigned lru[N_LRU];
static int hand;
static int const N_MRU = 1024; // does not have to be a power of 2
// 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 //}
static int F(Filter *f)
{
#ifdef U
// filter
upx_byte *b = f->buf;
upx_byte *const b = f->buf;
const unsigned addvalue = f->addvalue;
hand = 0;
memset(&lru[0], 0, sizeof(lru));
#else
// scan
const upx_byte *b = f->buf;
@ -57,6 +79,12 @@ static int F(Filter *f)
unsigned calls = 0, noncalls = 0, noncalls2 = 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.
// find a 16MB large empty address space
if (f->forced_cto >= 0 && f->forced_cto <= 255)
@ -123,7 +151,7 @@ static int F(Filter *f)
#ifdef U
if (COND2(b,lastcall,ic,ic-1,ic)) { // 6-byte Jcc <disp32>
// 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
// will tend to be constant. Swap prefix and opcode
// 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.
// 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.
int k;
for (k = 0; k < N_LRU; ++k) {
int kh = hand + k;
if (N_LRU <= kh) {
kh -= N_LRU;
}
if (lru[kh] == jc) { // destination was seen recently
set_be32(b+ic+1,((k<<1)|0)+cto);
break;
}
}
if (k == N_LRU) { // loop failed; jc is not in lru[]
set_be32(b+ic+1,((jc<<1)|1)+cto);
}
for (k = 0; k < N_MRU; ++k) {
int kh = hand + k;
if (N_MRU <= kh) {
kh -= N_MRU;
}
if (mru[kh] == jc) { // destination was seen recently
set_be32(b+ic+1,((k<<1)|0)+cto);
update_mru(jc, kh, mru, hand, tail);
break;
}
}
if (k == N_MRU) { // loop failed; jc is not in mru[]
set_be32(b+ic+1,((jc<<1)|1)+cto);
// Adaptively remember recent destinations.
if (0 > --hand) {
hand = N_MRU -1;
}
mru[hand] = jc;
}
}
// Adaptively remember recent destinations.
if (0 > --hand) {
hand = N_LRU -1;
}
lru[hand] = jc;
#endif
if (ic - lastnoncall < 5)
{
@ -212,16 +241,18 @@ static int F(Filter *f)
#ifdef U
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 addvalue = f->addvalue;
const unsigned cto = f->cto << 24;
unsigned lastcall = 0;
int hand = 0, tail = 0;
unsigned mru[N_MRU];
memset(&mru[0], 0, sizeof(mru));
unsigned ic, jc;
hand = 0;
for (ic = 0; ic < size5; ic++)
for (ic = 0; ic < size5; ic++) {
if (CONDU(b,ic,lastcall))
{
jc = get_be32(b+ic+1) - cto;
@ -229,19 +260,20 @@ static int U(Filter *f)
{
if (1&jc) { // 1st time at this destination
jc = (jc >> 1) - addvalue;
if (0 > --hand) {
hand = N_MRU -1;
}
mru[hand] = jc;
}
else { // not 1st time at this destination
jc = (jc >> 1) - addvalue;
int kh = jc + hand;
if (N_LRU <= kh) {
kh -= N_LRU;
if (N_MRU <= kh) {
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);
if (COND2(b,lastcall,ic,ic,ic-1)) {
@ -258,6 +290,7 @@ static int U(Filter *f)
else
f->noncalls++;
}
}
return 0;
}
#endif