diff --git a/src/core/ext/transport/chttp2/transport/decode_huff.cc b/src/core/ext/transport/chttp2/transport/decode_huff.cc index 677016b092f..5cd4221cf27 100644 --- a/src/core/ext/transport/chttp2/transport/decode_huff.cc +++ b/src/core/ext/transport/chttp2/transport/decode_huff.cc @@ -100,13 +100,6 @@ const uint8_t HuffDecoderCommon::table1_0_outer_[256] = { 48, 49, 49, 50, 50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55, 56, 56, 57, 57, 58, 58, 59, 59, 60, 60, 61, 61, 62, 62, 63, 63, 64, 64, 65, 65, 66, 66, 67, 67, 68, 69, 70, 71, 72, 73, 74, 75}; -const uint8_t HuffDecoderCommon::table5_0_emit_[4] = {0x21, 0x22, 0x28, 0x29}; -const uint8_t HuffDecoderCommon::table5_0_inner_[4] = {0x02, 0x06, 0x0a, 0x0e}; -const uint8_t HuffDecoderCommon::table5_0_outer_[4] = {0, 1, 2, 3}; -const uint8_t HuffDecoderCommon::table7_0_emit_[1] = {0x3f}; -const uint8_t HuffDecoderCommon::table7_0_inner_[3] = {0x02, 0x01, 0x00}; -const uint8_t HuffDecoderCommon::table7_0_outer_[4] = {0, 1, 1, 2}; -const uint8_t HuffDecoderCommon::table8_0_emit_[4] = {0x3f, 0x27, 0x2b, 0x7c}; const uint8_t HuffDecoderCommon::table8_0_inner_[6] = {0x01, 0x02, 0x06, 0x0a, 0x0e, 0x00}; const uint8_t HuffDecoderCommon::table8_0_outer_[8] = {0, 1, 2, 3, 4, 0, 0, 5}; @@ -158,11 +151,8 @@ const uint8_t* const HuffDecoderCommon::table6_ops_[2] = { table6_0_ops_, table6_1_ops_, }; -const uint8_t HuffDecoderCommon::table13_0_emit_[3] = {0x5c, 0xc3, 0xd0}; const uint8_t HuffDecoderCommon::table13_0_inner_[5] = {0x02, 0x06, 0x0a, 0x01, 0x00}; -const uint8_t HuffDecoderCommon::table13_0_outer_[16] = { - 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4}; const uint8_t HuffDecoderCommon::table14_0_emit_[11] = { 0x5c, 0xc3, 0xd0, 0x80, 0x82, 0x83, 0xa2, 0xb8, 0xc2, 0xe0, 0xe2}; const uint8_t HuffDecoderCommon::table14_0_ops_[32] = { @@ -231,35 +221,16 @@ const uint8_t HuffDecoderCommon::table12_0_outer_[256] = { 46, 47, 47, 48, 48, 49, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89}; -const uint8_t HuffDecoderCommon::table17_0_emit_[2] = {0x09, 0x8e}; -const uint8_t HuffDecoderCommon::table17_0_inner_[2] = {0x01, 0x03}; -const uint8_t HuffDecoderCommon::table17_0_outer_[2] = {0, 1}; -const uint8_t HuffDecoderCommon::table18_0_emit_[2] = {0x90, 0x91}; -const uint8_t HuffDecoderCommon::table18_0_inner_[2] = {0x01, 0x03}; -const uint8_t HuffDecoderCommon::table18_0_outer_[2] = {0, 1}; -const uint8_t HuffDecoderCommon::table19_0_emit_[2] = {0x94, 0x9f}; -const uint8_t HuffDecoderCommon::table20_0_emit_[2] = {0xab, 0xce}; -const uint8_t HuffDecoderCommon::table21_0_emit_[2] = {0xd7, 0xe1}; -const uint8_t HuffDecoderCommon::table22_0_emit_[2] = {0xec, 0xed}; -const uint8_t HuffDecoderCommon::table23_0_emit_[4] = {0xc7, 0xcf, 0xea, 0xeb}; -const uint8_t HuffDecoderCommon::table23_0_outer_[4] = {0, 1, 2, 3}; const uint8_t HuffDecoderCommon::table24_0_emit_[8] = {0xc0, 0xc1, 0xc8, 0xc9, 0xca, 0xcd, 0xd2, 0xd5}; const uint8_t HuffDecoderCommon::table24_0_inner_[8] = {0x03, 0x07, 0x0b, 0x0f, 0x13, 0x17, 0x1b, 0x1f}; -const uint8_t HuffDecoderCommon::table24_0_outer_[8] = {0, 1, 2, 3, 4, 5, 6, 7}; const uint8_t HuffDecoderCommon::table25_0_emit_[16] = { 0xd3, 0xd4, 0xd6, 0xdd, 0xde, 0xdf, 0xf1, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xfa, 0xfb, 0xfc, 0xfd}; const uint8_t HuffDecoderCommon::table25_0_inner_[16] = { 0x04, 0x0c, 0x14, 0x1c, 0x24, 0x2c, 0x34, 0x3c, 0x44, 0x4c, 0x54, 0x5c, 0x64, 0x6c, 0x74, 0x7c}; -const uint8_t HuffDecoderCommon::table25_0_outer_[16] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; -const uint8_t HuffDecoderCommon::table27_0_emit_[1] = {0xfe}; -const uint8_t HuffDecoderCommon::table27_0_inner_[3] = {0x02, 0x01, 0x00}; -const uint8_t HuffDecoderCommon::table27_0_outer_[16] = { - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2}; const uint8_t HuffDecoderCommon::table26_0_emit_[30] = { 0xfe, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0b, 0x0c, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x17, 0x18, @@ -269,11 +240,6 @@ const uint16_t HuffDecoderCommon::table26_0_inner_[31] = { 0x0085, 0x0095, 0x00a5, 0x00b5, 0x00c5, 0x00d5, 0x00e5, 0x00f5, 0x0105, 0x0115, 0x0125, 0x0135, 0x0145, 0x0155, 0x0165, 0x0175, 0x0185, 0x0195, 0x01a5, 0x01b5, 0x01c5, 0x01d5, 0x000d}; -const uint8_t HuffDecoderCommon::table26_0_outer_[32] = { - 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30}; -const uint8_t HuffDecoderCommon::table28_0_emit_[3] = {0x0a, 0x0d, 0x16}; -const uint8_t HuffDecoderCommon::table28_0_inner_[4] = {0x02, 0x0a, 0x12, 0x06}; const uint8_t HuffDecoderCommon::table30_0_emit_[7] = {0xda, 0xdb, 0xee, 0xf0, 0xf2, 0xf3, 0xff}; const uint8_t HuffDecoderCommon::table30_0_inner_[8] = {0x02, 0x06, 0x0a, 0x0e, @@ -282,6 +248,4 @@ const uint8_t HuffDecoderCommon::table29_0_emit_[9] = { 0xda, 0xdb, 0xee, 0xf0, 0xf2, 0xf3, 0xff, 0xcb, 0xcc}; const uint8_t HuffDecoderCommon::table29_0_inner_[9] = { 0x03, 0x0b, 0x13, 0x1b, 0x23, 0x2b, 0x33, 0x3c, 0x44}; -const uint8_t HuffDecoderCommon::table29_0_outer_[16] = { - 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8}; } // namespace grpc_core diff --git a/src/core/ext/transport/chttp2/transport/decode_huff.h b/src/core/ext/transport/chttp2/transport/decode_huff.h index 6fb13efd297..ef8d7fd38fa 100644 --- a/src/core/ext/transport/chttp2/transport/decode_huff.h +++ b/src/core/ext/transport/chttp2/transport/decode_huff.h @@ -47,22 +47,24 @@ class HuffDecoderCommon { return table1_0_emit_[emit]; } static inline uint64_t GetOp5(size_t i) { - return table5_0_inner_[table5_0_outer_[i]]; + return (i < 2 ? (i ? 6 : 2) : ((i - 2) ? 14 : 10)); } static inline uint64_t GetEmit5(size_t, size_t emit) { - return table5_0_emit_[emit]; + return (emit < 2 ? (emit + 33) : ((emit - 2) + 40)); } static inline uint64_t GetOp7(size_t i) { - return table7_0_inner_[table7_0_outer_[i]]; + return ((i < 2 ? (i) : ((i - 2) + 1)) < 1 + ? (((void)(i < 2 ? (i) : ((i - 2) + 1)), 2)) + : (((i < 2 ? (i) : ((i - 2) + 1)) - 1) ? 0 : 1)); } static inline uint64_t GetEmit7(size_t, size_t emit) { - return table7_0_emit_[emit]; + return ((void)emit, 63); } static inline uint64_t GetOp8(size_t i) { return table8_0_inner_[table8_0_outer_[i]]; } static inline uint64_t GetEmit8(size_t, size_t emit) { - return table8_0_emit_[emit]; + return (emit < 2 ? (emit ? 39 : 63) : ((emit - 2) ? 124 : 43)); } static inline uint64_t GetOp9(size_t i) { return table9_0_inner_[table9_0_outer_[i]]; @@ -85,10 +87,10 @@ class HuffDecoderCommon { return table6_emit_[i >> 6][emit]; } static inline uint64_t GetOp13(size_t i) { - return table13_0_inner_[table13_0_outer_[i]]; + return table13_0_inner_[(i < 3 ? (i) : ((i - 3) / 12 + 3))]; } static inline uint64_t GetEmit13(size_t, size_t emit) { - return table13_0_emit_[emit]; + return (emit < 1 ? (((void)emit, 92)) : ((emit - 1) ? 208 : 195)); } static inline uint64_t GetOp14(size_t i) { return table14_0_ops_[i]; } static inline uint64_t GetEmit14(size_t, size_t emit) { @@ -108,86 +110,67 @@ class HuffDecoderCommon { static inline uint64_t GetEmit12(size_t, size_t emit) { return table12_0_emit_[emit]; } - static inline uint64_t GetOp17(size_t i) { - return table17_0_inner_[table17_0_outer_[i]]; - } + static inline uint64_t GetOp17(size_t i) { return i ? 3 : 1; } static inline uint64_t GetEmit17(size_t, size_t emit) { - return table17_0_emit_[emit]; - } - static inline uint64_t GetOp18(size_t i) { - return table18_0_inner_[table18_0_outer_[i]]; - } - static inline uint64_t GetEmit18(size_t, size_t emit) { - return table18_0_emit_[emit]; - } - static inline uint64_t GetOp19(size_t i) { - return table17_0_inner_[table18_0_outer_[i]]; + return emit ? 142 : 9; } + static inline uint64_t GetOp18(size_t i) { return i ? 3 : 1; } + static inline uint64_t GetEmit18(size_t, size_t emit) { return emit + 144; } + static inline uint64_t GetOp19(size_t i) { return i ? 3 : 1; } static inline uint64_t GetEmit19(size_t, size_t emit) { - return table19_0_emit_[emit]; - } - static inline uint64_t GetOp20(size_t i) { - return table17_0_inner_[table18_0_outer_[i]]; + return emit ? 159 : 148; } + static inline uint64_t GetOp20(size_t i) { return i ? 3 : 1; } static inline uint64_t GetEmit20(size_t, size_t emit) { - return table20_0_emit_[emit]; - } - static inline uint64_t GetOp21(size_t i) { - return table17_0_inner_[table18_0_outer_[i]]; + return emit ? 206 : 171; } + static inline uint64_t GetOp21(size_t i) { return i ? 3 : 1; } static inline uint64_t GetEmit21(size_t, size_t emit) { - return table21_0_emit_[emit]; - } - static inline uint64_t GetOp22(size_t i) { - return table17_0_inner_[table18_0_outer_[i]]; - } - static inline uint64_t GetEmit22(size_t, size_t emit) { - return table22_0_emit_[emit]; + return emit ? 225 : 215; } + static inline uint64_t GetOp22(size_t i) { return i ? 3 : 1; } + static inline uint64_t GetEmit22(size_t, size_t emit) { return emit + 236; } static inline uint64_t GetOp23(size_t i) { - return table5_0_inner_[table23_0_outer_[i]]; + return (i < 2 ? (i ? 6 : 2) : ((i - 2) ? 14 : 10)); } static inline uint64_t GetEmit23(size_t, size_t emit) { - return table23_0_emit_[emit]; - } - static inline uint64_t GetOp24(size_t i) { - return table24_0_inner_[table24_0_outer_[i]]; + return (emit < 2 ? (emit ? 207 : 199) : ((emit - 2) + 234)); } + static inline uint64_t GetOp24(size_t i) { return table24_0_inner_[i]; } static inline uint64_t GetEmit24(size_t, size_t emit) { return table24_0_emit_[emit]; } - static inline uint64_t GetOp25(size_t i) { - return table25_0_inner_[table25_0_outer_[i]]; - } + static inline uint64_t GetOp25(size_t i) { return table25_0_inner_[i]; } static inline uint64_t GetEmit25(size_t, size_t emit) { return table25_0_emit_[emit]; } static inline uint64_t GetOp27(size_t i) { - return table27_0_inner_[table27_0_outer_[i]]; + return ( + (i < 1 ? (((void)i, 0)) : ((i - 1) / 14 + 1)) < 1 + ? (((void)(i < 1 ? (((void)i, 0)) : ((i - 1) / 14 + 1)), 2)) + : (((i < 1 ? (((void)i, 0)) : ((i - 1) / 14 + 1)) - 1) ? 0 : 1)); } static inline uint64_t GetEmit27(size_t, size_t emit) { - return table27_0_emit_[emit]; + return ((void)emit, 254); } static inline uint64_t GetOp26(size_t i) { - return table26_0_inner_[table26_0_outer_[i]]; + return table26_0_inner_[(i < 1 ? (((void)i, 0)) : ((i - 1)))]; } static inline uint64_t GetEmit26(size_t, size_t emit) { return table26_0_emit_[emit]; } static inline uint64_t GetOp28(size_t i) { - return table28_0_inner_[table5_0_outer_[i]]; + return (i < 2 ? (i ? 10 : 2) : ((i - 2) ? 6 : 18)); } static inline uint64_t GetEmit28(size_t, size_t emit) { - return table28_0_emit_[emit]; - } - static inline uint64_t GetOp30(size_t i) { - return table30_0_inner_[table24_0_outer_[i]]; + return (emit < 1 ? (((void)emit, 10)) : ((emit - 1) ? 22 : 13)); } + static inline uint64_t GetOp30(size_t i) { return table30_0_inner_[i]; } static inline uint64_t GetEmit30(size_t, size_t emit) { return table30_0_emit_[emit]; } static inline uint64_t GetOp29(size_t i) { - return table29_0_inner_[table29_0_outer_[i]]; + return table29_0_inner_[(i < 13 ? (i / 2 + 0) : ((i - 13) + 6))]; } static inline uint64_t GetEmit29(size_t, size_t emit) { return table29_0_emit_[emit]; @@ -207,13 +190,6 @@ class HuffDecoderCommon { static const uint8_t table1_0_emit_[74]; static const uint16_t table1_0_inner_[76]; static const uint8_t table1_0_outer_[256]; - static const uint8_t table5_0_emit_[4]; - static const uint8_t table5_0_inner_[4]; - static const uint8_t table5_0_outer_[4]; - static const uint8_t table7_0_emit_[1]; - static const uint8_t table7_0_inner_[3]; - static const uint8_t table7_0_outer_[4]; - static const uint8_t table8_0_emit_[4]; static const uint8_t table8_0_inner_[6]; static const uint8_t table8_0_outer_[8]; static const uint8_t table9_0_emit_[6]; @@ -229,9 +205,7 @@ class HuffDecoderCommon { static const uint8_t table6_1_ops_[64]; static const uint8_t* const table6_emit_[2]; static const uint8_t* const table6_ops_[2]; - static const uint8_t table13_0_emit_[3]; static const uint8_t table13_0_inner_[5]; - static const uint8_t table13_0_outer_[16]; static const uint8_t table14_0_emit_[11]; static const uint8_t table14_0_ops_[32]; static const uint8_t table15_0_emit_[24]; @@ -241,37 +215,16 @@ class HuffDecoderCommon { static const uint8_t table12_0_emit_[79]; static const uint16_t table12_0_inner_[90]; static const uint8_t table12_0_outer_[256]; - static const uint8_t table17_0_emit_[2]; - static const uint8_t table17_0_inner_[2]; - static const uint8_t table17_0_outer_[2]; - static const uint8_t table18_0_emit_[2]; - static const uint8_t table18_0_inner_[2]; - static const uint8_t table18_0_outer_[2]; - static const uint8_t table19_0_emit_[2]; - static const uint8_t table20_0_emit_[2]; - static const uint8_t table21_0_emit_[2]; - static const uint8_t table22_0_emit_[2]; - static const uint8_t table23_0_emit_[4]; - static const uint8_t table23_0_outer_[4]; static const uint8_t table24_0_emit_[8]; static const uint8_t table24_0_inner_[8]; - static const uint8_t table24_0_outer_[8]; static const uint8_t table25_0_emit_[16]; static const uint8_t table25_0_inner_[16]; - static const uint8_t table25_0_outer_[16]; - static const uint8_t table27_0_emit_[1]; - static const uint8_t table27_0_inner_[3]; - static const uint8_t table27_0_outer_[16]; static const uint8_t table26_0_emit_[30]; static const uint16_t table26_0_inner_[31]; - static const uint8_t table26_0_outer_[32]; - static const uint8_t table28_0_emit_[3]; - static const uint8_t table28_0_inner_[4]; static const uint8_t table30_0_emit_[7]; static const uint8_t table30_0_inner_[8]; static const uint8_t table29_0_emit_[9]; static const uint8_t table29_0_inner_[9]; - static const uint8_t table29_0_outer_[16]; }; template class HuffDecoder : public HuffDecoderCommon { diff --git a/tools/codegen/core/gen_huffman_decompressor.cc b/tools/codegen/core/gen_huffman_decompressor.cc index 19d81d11fa5..77f527ab831 100644 --- a/tools/codegen/core/gen_huffman_decompressor.cc +++ b/tools/codegen/core/gen_huffman_decompressor.cc @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -46,14 +47,21 @@ struct Hash { bool operator<(const Hash& other) const { return memcmp(bytes, other.bytes, SHA256_DIGEST_LENGTH) < 0; } + std::string ToString() const { + std::string result; + for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) { + absl::StrAppend(&result, absl::Hex(bytes[i], absl::kZeroPad2)); + } + return result; + } }; // Given a vector of ints (T), return a Hash object with the sha256 template Hash HashVec(const std::vector& v) { Hash h; - SHA1(reinterpret_cast(v.data()), v.size() * sizeof(T), - h.bytes); + SHA256(reinterpret_cast(v.data()), v.size() * sizeof(T), + h.bytes); return h; } @@ -679,27 +687,29 @@ class TableBuilder { std::vector lines; const uint64_t max_inner = MaxInner(); const uint64_t max_outer = MaxOuter(); - std::vector emit_names; - std::vector inner_names; - std::vector outer_names; + std::vector> emit_names; + std::vector> inner_names; + std::vector> outer_names; for (size_t i = 0; i < slices.size(); i++) { emit_names.push_back(builder->GenArray( - absl::StrCat("table", id, "_", i, "_emit"), "uint8_t", - slices[i].emit, true, global_decls, global_values)); + slice_bits != 0, absl::StrCat("table", id, "_", i, "_emit"), + "uint8_t", slices[i].emit, true, global_decls, global_values)); inner_names.push_back(builder->GenArray( - absl::StrCat("table", id, "_", i, "_inner"), TypeForMax(max_inner), - slices[i].inner, true, global_decls, global_values)); + slice_bits != 0, absl::StrCat("table", id, "_", i, "_inner"), + TypeForMax(max_inner), slices[i].inner, true, global_decls, + global_values)); outer_names.push_back(builder->GenArray( - absl::StrCat("table", id, "_", i, "_outer"), TypeForMax(max_outer), - slices[i].outer, false, global_decls, global_values)); + slice_bits != 0, absl::StrCat("table", id, "_", i, "_outer"), + TypeForMax(max_outer), slices[i].outer, false, global_decls, + global_values)); } if (slice_bits == 0) { - global_fns->Add(absl::StrCat("static inline uint64_t GetOp", id, - "(size_t i) { return ", inner_names[0], - "[", outer_names[0], "[i]]; }")); + global_fns->Add(absl::StrCat( + "static inline uint64_t GetOp", id, "(size_t i) { return ", + inner_names[0]->Index(outer_names[0]->Index("i")), "; }")); global_fns->Add(absl::StrCat("static inline uint64_t GetEmit", id, "(size_t, size_t emit) { return ", - emit_names[0], "[emit]; }")); + emit_names[0]->Index("emit"), "; }")); } else { GenCompound(id, emit_names, "emit", "uint8_t", global_decls, global_values); @@ -765,23 +775,24 @@ class TableBuilder { Sink* const global_values = builder->ctx_->global_values(); uint64_t max_op = MaxOp(); const int id = builder->id_; - std::vector emit_names; - std::vector ops_names; + std::vector> emit_names; + std::vector> ops_names; for (size_t i = 0; i < slices.size(); i++) { emit_names.push_back(builder->GenArray( - absl::StrCat("table", id, "_", i, "_emit"), "uint8_t", - slices[i].emit, true, global_decls, global_values)); + slice_bits != 0, absl::StrCat("table", id, "_", i, "_emit"), + "uint8_t", slices[i].emit, true, global_decls, global_values)); ops_names.push_back(builder->GenArray( - absl::StrCat("table", id, "_", i, "_ops"), TypeForMax(max_op), - slices[i].ops, true, global_decls, global_values)); + slice_bits != 0, absl::StrCat("table", id, "_", i, "_ops"), + TypeForMax(max_op), slices[i].ops, true, global_decls, + global_values)); } if (slice_bits == 0) { global_fns->Add(absl::StrCat("static inline uint64_t GetOp", id, - "(size_t i) { return ", ops_names[0], - "[i]; }")); + "(size_t i) { return ", + ops_names[0]->Index("i"), "; }")); global_fns->Add(absl::StrCat("static inline uint64_t GetEmit", id, "(size_t, size_t emit) { return ", - emit_names[0], "[emit]; }")); + emit_names[0]->Index("emit"), "; }")); } else { GenCompound(id, emit_names, "emit", "uint8_t", global_decls, global_values); @@ -838,29 +849,221 @@ class TableBuilder { return table; } + class Array { + public: + virtual ~Array() = default; + virtual std::string Index(absl::string_view value) = 0; + virtual std::string ArrayName() = 0; + virtual int Cost() = 0; + }; + + class NamedArray : public Array { + public: + explicit NamedArray(std::string name) : name_(std::move(name)) {} + std::string Index(absl::string_view value) override { + return absl::StrCat(name_, "[", value, "]"); + } + std::string ArrayName() override { return name_; } + int Cost() override { abort(); } + + private: + std::string name_; + }; + + class IdentityArray : public Array { + public: + std::string Index(absl::string_view value) override { + return std::string(value); + } + std::string ArrayName() override { abort(); } + int Cost() override { return 0; } + }; + + class ConstantArray : public Array { + public: + explicit ConstantArray(std::string value) : value_(std::move(value)) {} + std::string Index(absl::string_view index) override { + return absl::StrCat("((void)", index, ", ", value_, ")"); + } + std::string ArrayName() override { abort(); } + int Cost() override { return 0; } + + private: + std::string value_; + }; + + class OffsetArray : public Array { + public: + explicit OffsetArray(int offset) : offset_(offset) {} + std::string Index(absl::string_view value) override { + return absl::StrCat(value, " + ", offset_); + } + std::string ArrayName() override { abort(); } + int Cost() override { return 10; } + + private: + int offset_; + }; + + class LinearDivideArray : public Array { + public: + LinearDivideArray(int offset, int divisor) + : offset_(offset), divisor_(divisor) {} + std::string Index(absl::string_view value) override { + return absl::StrCat(value, "/", divisor_, " + ", offset_); + } + std::string ArrayName() override { abort(); } + int Cost() override { return 20 + (offset_ != 0 ? 10 : 0); } + + private: + int offset_; + int divisor_; + }; + + class TwoElemArray : public Array { + public: + TwoElemArray(std::string value0, std::string value1) + : value0_(std::move(value0)), value1_(std::move(value1)) {} + std::string Index(absl::string_view value) override { + return absl::StrCat(value, " ? ", value1_, " : ", value0_); + } + std::string ArrayName() override { abort(); } + int Cost() override { return 40; } + + private: + std::string value0_; + std::string value1_; + }; + + class Composite2Array : public Array { + public: + Composite2Array(std::unique_ptr a, std::unique_ptr b, + int split) + : a_(std::move(a)), b_(std::move(b)), split_(split) {} + std::string Index(absl::string_view value) override { + return absl::StrCat( + "(", value, " < ", split_, " ? (", a_->Index(value), ") : (", + b_->Index(absl::StrCat("(", value, "-", split_, ")")), "))"); + } + std::string ArrayName() override { abort(); } + int Cost() override { return 40 + a_->Cost() + b_->Cost(); } + + private: + std::unique_ptr a_; + std::unique_ptr b_; + int split_; + }; + // Helper to generate a compound table (an array of arrays) - static void GenCompound(int id, std::vector names, + static void GenCompound(int id, + const std::vector>& arrays, std::string ext, std::string type, Sink* global_decls, Sink* global_values) { global_decls->Add(absl::StrCat("static const ", type, "* const table", id, - "_", ext, "_[", names.size(), "];")); + "_", ext, "_[", arrays.size(), "];")); global_values->Add(absl::StrCat("const ", type, "* const HuffDecoderCommon::table", id, "_", - ext, "_[", names.size(), "] = {")); - for (const std::string& name : names) { - global_values->Add(absl::StrCat(" ", name, ",")); + ext, "_[", arrays.size(), "] = {")); + for (const std::unique_ptr& array : arrays) { + global_values->Add(absl::StrCat(" ", array->ArrayName(), ",")); } global_values->Add("};"); } + // Try to create a simple function equivalent to a mapping implied by a set of + // values. + static const int kMaxArrayToFunctionRecursions = 1; + template + static std::unique_ptr ArrayToFunction( + const std::vector& values, + int recurse = kMaxArrayToFunctionRecursions) { + std::unique_ptr best = nullptr; + auto note_solution = [&best](std::unique_ptr a) { + if (best != nullptr && best->Cost() <= a->Cost()) return; + best = std::move(a); + }; + // constant => k,k,k,k,... + bool is_constant = true; + for (size_t i = 1; i < values.size(); i++) { + if (values[i] != values[0]) { + is_constant = false; + break; + } + } + if (is_constant) { + note_solution(std::make_unique(absl::StrCat(values[0]))); + } + // identity => 0,1,2,3,... + bool is_identity = true; + for (size_t i = 0; i < values.size(); i++) { + if (values[i] != i) { + is_identity = false; + break; + } + } + if (is_identity) { + note_solution(std::make_unique()); + } + // offset => k,k+1,k+2,k+3,... + bool is_offset = true; + for (size_t i = 1; i < values.size(); i++) { + if (values[i] - values[0] != i) { + is_offset = false; + break; + } + } + if (is_offset) { + note_solution(std::make_unique(values[0])); + } + // offset => k,k,k+1,k+1,... + for (int d = 2; d < 32; d++) { + bool is_linear = true; + for (size_t i = 1; i < values.size(); i++) { + if (values[i] - values[0] != (i / d)) { + is_linear = false; + break; + } + } + if (is_linear) { + note_solution(std::make_unique(values[0], d)); + } + } + // Two items can be resolved with a conditional + if (values.size() == 2) { + note_solution(std::make_unique(absl::StrCat(values[0]), + absl::StrCat(values[1]))); + } + if ((recurse > 0 && values.size() >= 6) || + (recurse == kMaxArrayToFunctionRecursions)) { + for (size_t i = 1; i < values.size() - 1; i++) { + std::vector left(values.begin(), values.begin() + i); + std::vector right(values.begin() + i, values.end()); + std::unique_ptr left_array = ArrayToFunction(left, recurse - 1); + std::unique_ptr right_array = + ArrayToFunction(right, recurse - 1); + if (left_array && right_array) { + note_solution(std::make_unique( + std::move(left_array), std::move(right_array), i)); + } + } + } + return best; + } + // Helper to generate an array of values template - std::string GenArray(std::string name, std::string type, - const std::vector& values, bool hex, - Sink* global_decls, Sink* global_values) const { + std::unique_ptr GenArray(bool force_array, std::string name, + std::string type, + const std::vector& values, bool hex, + Sink* global_decls, + Sink* global_values) const { + if (!force_array) { + auto fn = ArrayToFunction(values); + if (fn != nullptr) return fn; + } auto previous_name = ctx_->PreviousNameForArtifact(name, HashVec(values)); if (previous_name.has_value()) { - return absl::StrCat(*previous_name, "_"); + return std::make_unique(absl::StrCat(*previous_name, "_")); } std::vector elems; elems.reserve(values.size()); @@ -884,7 +1087,7 @@ class TableBuilder { name, "_[", values.size(), "] = {")); global_values->Add(absl::StrCat(" ", data)); global_values->Add("};"); - return absl::StrCat(name, "_"); + return std::make_unique(absl::StrCat(name, "_")); } // Choose an encoding for this set of tables.