| //go:build (amd64 || arm64) && !appengine && !noasm && gc |
| |
| package s2 |
| |
| import ( |
| "sync" |
| |
| "github.com/klauspost/compress/internal/race" |
| ) |
| |
| const hasAsm = true |
| |
| var encPools [4]sync.Pool |
| |
| // encodeBlock encodes a non-empty src to a guaranteed-large-enough dst. It |
| // assumes that the varint-encoded length of the decompressed bytes has already |
| // been written. |
| // |
| // It also assumes that: |
| // |
| // len(dst) >= MaxEncodedLen(len(src)) && |
| // minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize |
| func encodeBlock(dst, src []byte) (d int) { |
| race.ReadSlice(src) |
| race.WriteSlice(dst) |
| |
| const ( |
| // Use 12 bit table when less than... |
| limit12B = 16 << 10 |
| // Use 10 bit table when less than... |
| limit10B = 4 << 10 |
| // Use 8 bit table when less than... |
| limit8B = 512 |
| ) |
| |
| if len(src) >= 4<<20 { |
| const sz, pool = 65536, 0 |
| tmp, ok := encPools[pool].Get().(*[sz]byte) |
| if !ok { |
| tmp = &[sz]byte{} |
| } |
| race.WriteSlice(tmp[:]) |
| defer encPools[pool].Put(tmp) |
| return encodeBlockAsm(dst, src, tmp) |
| } |
| if len(src) >= limit12B { |
| const sz, pool = 65536, 0 |
| tmp, ok := encPools[pool].Get().(*[sz]byte) |
| if !ok { |
| tmp = &[sz]byte{} |
| } |
| race.WriteSlice(tmp[:]) |
| defer encPools[pool].Put(tmp) |
| return encodeBlockAsm4MB(dst, src, tmp) |
| } |
| if len(src) >= limit10B { |
| const sz, pool = 16384, 1 |
| tmp, ok := encPools[pool].Get().(*[sz]byte) |
| if !ok { |
| tmp = &[sz]byte{} |
| } |
| race.WriteSlice(tmp[:]) |
| defer encPools[pool].Put(tmp) |
| return encodeBlockAsm12B(dst, src, tmp) |
| } |
| if len(src) >= limit8B { |
| const sz, pool = 4096, 2 |
| tmp, ok := encPools[pool].Get().(*[sz]byte) |
| if !ok { |
| tmp = &[sz]byte{} |
| } |
| race.WriteSlice(tmp[:]) |
| defer encPools[pool].Put(tmp) |
| return encodeBlockAsm10B(dst, src, tmp) |
| } |
| if len(src) < minNonLiteralBlockSize { |
| return 0 |
| } |
| const sz, pool = 1024, 3 |
| tmp, ok := encPools[pool].Get().(*[sz]byte) |
| if !ok { |
| tmp = &[sz]byte{} |
| } |
| race.WriteSlice(tmp[:]) |
| defer encPools[pool].Put(tmp) |
| return encodeBlockAsm8B(dst, src, tmp) |
| } |
| |
| var encBetterPools [5]sync.Pool |
| |
| // encodeBlockBetter encodes a non-empty src to a guaranteed-large-enough dst. It |
| // assumes that the varint-encoded length of the decompressed bytes has already |
| // been written. |
| // |
| // It also assumes that: |
| // |
| // len(dst) >= MaxEncodedLen(len(src)) && |
| // minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize |
| func encodeBlockBetter(dst, src []byte) (d int) { |
| race.ReadSlice(src) |
| race.WriteSlice(dst) |
| |
| const ( |
| // Use 12 bit table when less than... |
| limit12B = 16 << 10 |
| // Use 10 bit table when less than... |
| limit10B = 4 << 10 |
| // Use 8 bit table when less than... |
| limit8B = 512 |
| ) |
| |
| if len(src) > 4<<20 { |
| const sz, pool = 589824, 0 |
| tmp, ok := encBetterPools[pool].Get().(*[sz]byte) |
| if !ok { |
| tmp = &[sz]byte{} |
| } |
| race.WriteSlice(tmp[:]) |
| defer encBetterPools[pool].Put(tmp) |
| return encodeBetterBlockAsm(dst, src, tmp) |
| } |
| if len(src) >= limit12B { |
| const sz, pool = 589824, 0 |
| tmp, ok := encBetterPools[pool].Get().(*[sz]byte) |
| if !ok { |
| tmp = &[sz]byte{} |
| } |
| race.WriteSlice(tmp[:]) |
| defer encBetterPools[pool].Put(tmp) |
| |
| return encodeBetterBlockAsm4MB(dst, src, tmp) |
| } |
| if len(src) >= limit10B { |
| const sz, pool = 81920, 0 |
| tmp, ok := encBetterPools[pool].Get().(*[sz]byte) |
| if !ok { |
| tmp = &[sz]byte{} |
| } |
| race.WriteSlice(tmp[:]) |
| defer encBetterPools[pool].Put(tmp) |
| |
| return encodeBetterBlockAsm12B(dst, src, tmp) |
| } |
| if len(src) >= limit8B { |
| const sz, pool = 20480, 1 |
| tmp, ok := encBetterPools[pool].Get().(*[sz]byte) |
| if !ok { |
| tmp = &[sz]byte{} |
| } |
| race.WriteSlice(tmp[:]) |
| defer encBetterPools[pool].Put(tmp) |
| return encodeBetterBlockAsm10B(dst, src, tmp) |
| } |
| if len(src) < minNonLiteralBlockSize { |
| return 0 |
| } |
| |
| const sz, pool = 5120, 2 |
| tmp, ok := encBetterPools[pool].Get().(*[sz]byte) |
| if !ok { |
| tmp = &[sz]byte{} |
| } |
| race.WriteSlice(tmp[:]) |
| defer encBetterPools[pool].Put(tmp) |
| return encodeBetterBlockAsm8B(dst, src, tmp) |
| } |
| |
| // encodeBlockSnappy encodes a non-empty src to a guaranteed-large-enough dst. It |
| // assumes that the varint-encoded length of the decompressed bytes has already |
| // been written. |
| // |
| // It also assumes that: |
| // |
| // len(dst) >= MaxEncodedLen(len(src)) && |
| // minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize |
| func encodeBlockSnappy(dst, src []byte) (d int) { |
| race.ReadSlice(src) |
| race.WriteSlice(dst) |
| |
| const ( |
| // Use 12 bit table when less than... |
| limit12B = 16 << 10 |
| // Use 10 bit table when less than... |
| limit10B = 4 << 10 |
| // Use 8 bit table when less than... |
| limit8B = 512 |
| ) |
| if len(src) > 65536 { |
| const sz, pool = 65536, 0 |
| tmp, ok := encPools[pool].Get().(*[sz]byte) |
| if !ok { |
| tmp = &[sz]byte{} |
| } |
| race.WriteSlice(tmp[:]) |
| defer encPools[pool].Put(tmp) |
| return encodeSnappyBlockAsm(dst, src, tmp) |
| } |
| if len(src) >= limit12B { |
| const sz, pool = 65536, 0 |
| tmp, ok := encPools[pool].Get().(*[sz]byte) |
| if !ok { |
| tmp = &[sz]byte{} |
| } |
| race.WriteSlice(tmp[:]) |
| defer encPools[pool].Put(tmp) |
| return encodeSnappyBlockAsm64K(dst, src, tmp) |
| } |
| if len(src) >= limit10B { |
| const sz, pool = 16384, 1 |
| tmp, ok := encPools[pool].Get().(*[sz]byte) |
| if !ok { |
| tmp = &[sz]byte{} |
| } |
| race.WriteSlice(tmp[:]) |
| defer encPools[pool].Put(tmp) |
| return encodeSnappyBlockAsm12B(dst, src, tmp) |
| } |
| if len(src) >= limit8B { |
| const sz, pool = 4096, 2 |
| tmp, ok := encPools[pool].Get().(*[sz]byte) |
| if !ok { |
| tmp = &[sz]byte{} |
| } |
| race.WriteSlice(tmp[:]) |
| defer encPools[pool].Put(tmp) |
| return encodeSnappyBlockAsm10B(dst, src, tmp) |
| } |
| if len(src) < minNonLiteralBlockSize { |
| return 0 |
| } |
| const sz, pool = 1024, 3 |
| tmp, ok := encPools[pool].Get().(*[sz]byte) |
| if !ok { |
| tmp = &[sz]byte{} |
| } |
| race.WriteSlice(tmp[:]) |
| defer encPools[pool].Put(tmp) |
| return encodeSnappyBlockAsm8B(dst, src, tmp) |
| } |
| |
| // encodeBlockSnappy encodes a non-empty src to a guaranteed-large-enough dst. It |
| // assumes that the varint-encoded length of the decompressed bytes has already |
| // been written. |
| // |
| // It also assumes that: |
| // |
| // len(dst) >= MaxEncodedLen(len(src)) && |
| // minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize |
| func encodeBlockBetterSnappy(dst, src []byte) (d int) { |
| race.ReadSlice(src) |
| race.WriteSlice(dst) |
| |
| const ( |
| // Use 12 bit table when less than... |
| limit12B = 16 << 10 |
| // Use 10 bit table when less than... |
| limit10B = 4 << 10 |
| // Use 8 bit table when less than... |
| limit8B = 512 |
| ) |
| if len(src) > 65536 { |
| const sz, pool = 589824, 0 |
| tmp, ok := encBetterPools[pool].Get().(*[sz]byte) |
| if !ok { |
| tmp = &[sz]byte{} |
| } |
| race.WriteSlice(tmp[:]) |
| defer encBetterPools[pool].Put(tmp) |
| return encodeSnappyBetterBlockAsm(dst, src, tmp) |
| } |
| |
| if len(src) >= limit12B { |
| const sz, pool = 294912, 4 |
| tmp, ok := encBetterPools[pool].Get().(*[sz]byte) |
| if !ok { |
| tmp = &[sz]byte{} |
| } |
| race.WriteSlice(tmp[:]) |
| defer encBetterPools[pool].Put(tmp) |
| |
| return encodeSnappyBetterBlockAsm64K(dst, src, tmp) |
| } |
| if len(src) >= limit10B { |
| const sz, pool = 81920, 0 |
| tmp, ok := encBetterPools[pool].Get().(*[sz]byte) |
| if !ok { |
| tmp = &[sz]byte{} |
| } |
| race.WriteSlice(tmp[:]) |
| defer encBetterPools[pool].Put(tmp) |
| |
| return encodeSnappyBetterBlockAsm12B(dst, src, tmp) |
| } |
| if len(src) >= limit8B { |
| const sz, pool = 20480, 1 |
| tmp, ok := encBetterPools[pool].Get().(*[sz]byte) |
| if !ok { |
| tmp = &[sz]byte{} |
| } |
| race.WriteSlice(tmp[:]) |
| defer encBetterPools[pool].Put(tmp) |
| return encodeSnappyBetterBlockAsm10B(dst, src, tmp) |
| } |
| if len(src) < minNonLiteralBlockSize { |
| return 0 |
| } |
| |
| const sz, pool = 5120, 2 |
| tmp, ok := encBetterPools[pool].Get().(*[sz]byte) |
| if !ok { |
| tmp = &[sz]byte{} |
| } |
| race.WriteSlice(tmp[:]) |
| defer encBetterPools[pool].Put(tmp) |
| return encodeSnappyBetterBlockAsm8B(dst, src, tmp) |
| } |