Skip to content

Commit 91d6e0e

Browse files
njhillnormanmaurer
authored andcommitted
Simplify HpackHuffmanDecoder table decode logic (netty#9335)
Motivation The nice change made by @carl-mastrangelo in netty#9307 for lookup-table based HPACK Huffman decoding can be simplified a little to remove the separate flags field and eliminate some intermediate operations. Modification Simplify HpackHuffmanDecoder::decode logic including de-dup of the per-nibble part. Result Less code, possibly better performance though not noticeable in a quick benchmark.
1 parent db8dd66 commit 91d6e0e

File tree

1 file changed

+15
-23
lines changed

1 file changed

+15
-23
lines changed

codec-http2/src/main/java/io/netty/handler/codec/http2/HpackHuffmanDecoder.java

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ final class HpackHuffmanDecoder implements ByteProcessor {
4646
private static final byte HUFFMAN_EMIT_SYMBOL = 1 << 1;
4747
private static final byte HUFFMAN_FAIL = 1 << 2;
4848

49-
private static final int HUFFMAN_COMPLETE_SHIFT = 1 << 8;
50-
private static final int HUFFMAN_EMIT_SYMBOL_SHIFT = 1 << 9;
51-
private static final int HUFFMAN_FAIL_SHIFT = 1 << 10;
49+
private static final int HUFFMAN_COMPLETE_SHIFT = HUFFMAN_COMPLETE << 8;
50+
private static final int HUFFMAN_EMIT_SYMBOL_SHIFT = HUFFMAN_EMIT_SYMBOL << 8;
51+
private static final int HUFFMAN_FAIL_SHIFT = HUFFMAN_FAIL << 8;
5252

5353
/**
5454
* A table of byte tuples (state, flags, output). They are packed together as:
@@ -4672,7 +4672,6 @@ final class HpackHuffmanDecoder implements ByteProcessor {
46724672
private byte[] dest;
46734673
private int k;
46744674
private int state;
4675-
private int flags;
46764675

46774676
HpackHuffmanDecoder() { }
46784677

@@ -4696,7 +4695,7 @@ public AsciiString decode(ByteBuf buf, int length) throws Http2Exception {
46964695
if (endIndex == -1) {
46974696
// We did consume the requested length
46984697
buf.readerIndex(readerIndex + length);
4699-
if ((flags & HUFFMAN_COMPLETE_SHIFT) != HUFFMAN_COMPLETE_SHIFT) {
4698+
if ((state & HUFFMAN_COMPLETE_SHIFT) != HUFFMAN_COMPLETE_SHIFT) {
47004699
throw BAD_ENCODING;
47014700
}
47024701
return new AsciiString(dest, 0, k, false);
@@ -4710,7 +4709,6 @@ public AsciiString decode(ByteBuf buf, int length) throws Http2Exception {
47104709
dest = null;
47114710
k = 0;
47124711
state = 0;
4713-
flags = 0;
47144712
}
47154713
}
47164714

@@ -4719,27 +4717,21 @@ public AsciiString decode(ByteBuf buf, int length) throws Http2Exception {
47194717
*/
47204718
@Override
47214719
public boolean process(byte input) {
4722-
int index = (state << 4) | ((input & 0xFF) >>> 4);
4723-
int row = HUFFS[index];
4724-
flags = row & 0x00FF00;
4725-
if ((flags & HUFFMAN_FAIL_SHIFT) != 0) {
4726-
return false;
4727-
}
4728-
if ((flags & HUFFMAN_EMIT_SYMBOL_SHIFT) != 0) {
4729-
dest[k++] = (byte) (row & 0xFF);
4730-
}
4731-
state = row >> 16;
4720+
return processNibble(input >> 4) && processNibble(input);
4721+
}
47324722

4733-
index = (state << 4) | (input & 0x0F);
4734-
row = HUFFS[index];
4735-
flags = row & 0x00FF00;
4736-
if ((flags & HUFFMAN_FAIL_SHIFT) != 0) {
4723+
private boolean processNibble(int input) {
4724+
// The high nibble of the flags byte of each row is always zero
4725+
// (low nibble after shifting row by 12), since there are only 3 flag bits
4726+
int index = state >> 12 | (input & 0x0F);
4727+
state = HUFFS[index];
4728+
if ((state & HUFFMAN_FAIL_SHIFT) != 0) {
47374729
return false;
47384730
}
4739-
if ((flags & HUFFMAN_EMIT_SYMBOL_SHIFT) != 0) {
4740-
dest[k++] = (byte) (row & 0xFF);
4731+
if ((state & HUFFMAN_EMIT_SYMBOL_SHIFT) != 0) {
4732+
// state is always positive so can cast without mask here
4733+
dest[k++] = (byte) state;
47414734
}
4742-
state = row >> 16;
47434735
return true;
47444736
}
47454737
}

0 commit comments

Comments
 (0)