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:
+72
-39
@@ -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);
|
||||||
break;
|
update_mru(jc, kh, mru, hand, tail);
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
if (k == N_LRU) { // loop failed; jc is not in lru[]
|
}
|
||||||
set_be32(b+ic+1,((jc<<1)|1)+cto);
|
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
|
#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
|
||||||
|
|||||||
Reference in New Issue
Block a user