mirror of https://git.tukaani.org/xz.git
liblzma: LZMA decoder: Get rid of next_state[].
It's not completely obvious if this is better in the decoder. It should be good if compiler can avoid creating a branch (like using CMOV on x86). This also makes lzma_encoder.c use the new macros.
This commit is contained in:
parent
e0c0ee475c
commit
eb518446e5
|
@ -83,6 +83,20 @@ typedef enum {
|
||||||
? (state) - 3 \
|
? (state) - 3 \
|
||||||
: (state) - 6))
|
: (state) - 6))
|
||||||
|
|
||||||
|
/// Like update_literal(state) but when it is already known that
|
||||||
|
/// is_literal_state(state) is true.
|
||||||
|
#define update_literal_normal(state) \
|
||||||
|
state = ((state) <= STATE_SHORTREP_LIT_LIT \
|
||||||
|
? STATE_LIT_LIT \
|
||||||
|
: (state) - 3);
|
||||||
|
|
||||||
|
/// Like update_literal(state) but when it is already known that
|
||||||
|
/// is_literal_state(state) is false.
|
||||||
|
#define update_literal_matched(state) \
|
||||||
|
state = ((state) <= STATE_LIT_SHORTREP \
|
||||||
|
? (state) - 3 \
|
||||||
|
: (state) - 6);
|
||||||
|
|
||||||
/// Indicate that the latest state was a match.
|
/// Indicate that the latest state was a match.
|
||||||
#define update_match(state) \
|
#define update_match(state) \
|
||||||
state = ((state) < LIT_STATES ? STATE_LIT_MATCH : STATE_NONLIT_MATCH)
|
state = ((state) < LIT_STATES ? STATE_LIT_MATCH : STATE_NONLIT_MATCH)
|
||||||
|
|
|
@ -307,24 +307,6 @@ lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr,
|
||||||
might_finish_without_eopm = true;
|
might_finish_without_eopm = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lookup table used to update the literal state.
|
|
||||||
// Compared to other state updates, this would need two branches.
|
|
||||||
// The lookup table is used by both Resumable and Non-resumable modes.
|
|
||||||
static const lzma_lzma_state next_state[] = {
|
|
||||||
STATE_LIT_LIT,
|
|
||||||
STATE_LIT_LIT,
|
|
||||||
STATE_LIT_LIT,
|
|
||||||
STATE_LIT_LIT,
|
|
||||||
STATE_MATCH_LIT_LIT,
|
|
||||||
STATE_REP_LIT_LIT,
|
|
||||||
STATE_SHORTREP_LIT_LIT,
|
|
||||||
STATE_MATCH_LIT,
|
|
||||||
STATE_REP_LIT,
|
|
||||||
STATE_SHORTREP_LIT,
|
|
||||||
STATE_MATCH_LIT,
|
|
||||||
STATE_REP_LIT
|
|
||||||
};
|
|
||||||
|
|
||||||
// The main decoder loop. The "switch" is used to resume the decoder at
|
// The main decoder loop. The "switch" is used to resume the decoder at
|
||||||
// correct location. Once resumed, the "switch" is no longer used.
|
// correct location. Once resumed, the "switch" is no longer used.
|
||||||
// The decoder loops is split into two modes:
|
// The decoder loops is split into two modes:
|
||||||
|
@ -381,16 +363,18 @@ lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr,
|
||||||
dict.pos, dict_get(&dict, 0));
|
dict.pos, dict_get(&dict, 0));
|
||||||
|
|
||||||
if (is_literal_state(state)) {
|
if (is_literal_state(state)) {
|
||||||
|
update_literal_normal(state);
|
||||||
|
|
||||||
// Decode literal without match byte.
|
// Decode literal without match byte.
|
||||||
rc_bittree8(probs, 0);
|
rc_bittree8(probs, 0);
|
||||||
} else {
|
} else {
|
||||||
|
update_literal_matched(state);
|
||||||
|
|
||||||
// Decode literal with match byte.
|
// Decode literal with match byte.
|
||||||
rc_matched_literal(probs,
|
rc_matched_literal(probs,
|
||||||
dict_get(&dict, rep0));
|
dict_get(&dict, rep0));
|
||||||
}
|
}
|
||||||
|
|
||||||
state = next_state[state];
|
|
||||||
|
|
||||||
// Write decoded literal to dictionary
|
// Write decoded literal to dictionary
|
||||||
dict_put(&dict, symbol);
|
dict_put(&dict, symbol);
|
||||||
continue;
|
continue;
|
||||||
|
@ -705,6 +689,8 @@ slow:
|
||||||
symbol = 1;
|
symbol = 1;
|
||||||
|
|
||||||
if (is_literal_state(state)) {
|
if (is_literal_state(state)) {
|
||||||
|
update_literal_normal(state);
|
||||||
|
|
||||||
// Decode literal without match byte.
|
// Decode literal without match byte.
|
||||||
// The "slow" version does not unroll
|
// The "slow" version does not unroll
|
||||||
// the loop.
|
// the loop.
|
||||||
|
@ -714,6 +700,8 @@ slow:
|
||||||
SEQ_LITERAL);
|
SEQ_LITERAL);
|
||||||
} while (symbol < (1 << 8));
|
} while (symbol < (1 << 8));
|
||||||
} else {
|
} else {
|
||||||
|
update_literal_matched(state);
|
||||||
|
|
||||||
// Decode literal with match byte.
|
// Decode literal with match byte.
|
||||||
len = (uint32_t)(dict_get(&dict, rep0)) << 1;
|
len = (uint32_t)(dict_get(&dict, rep0)) << 1;
|
||||||
|
|
||||||
|
@ -742,8 +730,6 @@ slow:
|
||||||
} while (symbol < (1 << 8));
|
} while (symbol < (1 << 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
state = next_state[state];
|
|
||||||
|
|
||||||
case SEQ_LITERAL_WRITE:
|
case SEQ_LITERAL_WRITE:
|
||||||
if (dict_put_safe(&dict, symbol)) {
|
if (dict_put_safe(&dict, symbol)) {
|
||||||
coder->sequence = SEQ_LITERAL_WRITE;
|
coder->sequence = SEQ_LITERAL_WRITE;
|
||||||
|
|
|
@ -54,18 +54,18 @@ literal(lzma_lzma1_encoder *coder, lzma_mf *mf, uint32_t position)
|
||||||
if (is_literal_state(coder->state)) {
|
if (is_literal_state(coder->state)) {
|
||||||
// Previous LZMA-symbol was a literal. Encode a normal
|
// Previous LZMA-symbol was a literal. Encode a normal
|
||||||
// literal without a match byte.
|
// literal without a match byte.
|
||||||
|
update_literal_normal(coder->state);
|
||||||
rc_bittree(&coder->rc, subcoder, 8, cur_byte);
|
rc_bittree(&coder->rc, subcoder, 8, cur_byte);
|
||||||
} else {
|
} else {
|
||||||
// Previous LZMA-symbol was a match. Use the last byte of
|
// Previous LZMA-symbol was a match. Use the last byte of
|
||||||
// the match as a "match byte". That is, compare the bits
|
// the match as a "match byte". That is, compare the bits
|
||||||
// of the current literal and the match byte.
|
// of the current literal and the match byte.
|
||||||
|
update_literal_matched(coder->state);
|
||||||
const uint8_t match_byte = mf->buffer[
|
const uint8_t match_byte = mf->buffer[
|
||||||
mf->read_pos - coder->reps[0] - 1
|
mf->read_pos - coder->reps[0] - 1
|
||||||
- mf->read_ahead];
|
- mf->read_ahead];
|
||||||
literal_matched(&coder->rc, subcoder, match_byte, cur_byte);
|
literal_matched(&coder->rc, subcoder, match_byte, cur_byte);
|
||||||
}
|
}
|
||||||
|
|
||||||
update_literal(coder->state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue