forked from mirror/go-json
Compare commits
7 Commits
master
...
feature/si
Author | SHA1 | Date |
---|---|---|
Masaaki Goshima | 68c500590e | |
Masaaki Goshima | e736de7070 | |
Masaaki Goshima | f2e0e6edea | |
Masaaki Goshima | 118663d59f | |
Masaaki Goshima | 4019c11e82 | |
Masaaki Goshima | 390aa2d0ea | |
Masaaki Goshima | 38b316a540 |
2
Makefile
2
Makefile
|
@ -36,4 +36,4 @@ golangci-lint: | $(BIN_DIR)
|
||||||
|
|
||||||
.PHONY: generate
|
.PHONY: generate
|
||||||
generate:
|
generate:
|
||||||
go generate ./internal/...
|
cd internal/cmd/generator && go generate .
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
*.s
|
|
@ -0,0 +1,30 @@
|
||||||
|
FROM golang:1.16
|
||||||
|
|
||||||
|
RUN apt-get update; \
|
||||||
|
apt-get install -y build-essential clang yasm
|
||||||
|
|
||||||
|
WORKDIR /work
|
||||||
|
|
||||||
|
COPY ./go.* ./
|
||||||
|
RUN go install \
|
||||||
|
github.com/minio/asm2plan9s \
|
||||||
|
github.com/minio/c2goasm \
|
||||||
|
github.com/klauspost/asmfmt/cmd/asmfmt
|
||||||
|
|
||||||
|
COPY ./simd/string.c ./string.c
|
||||||
|
|
||||||
|
RUN clang -S \
|
||||||
|
-O2 \
|
||||||
|
-mavx2 \
|
||||||
|
-masm=intel \
|
||||||
|
-mno-red-zone \
|
||||||
|
-mstackrealign \
|
||||||
|
-mllvm \
|
||||||
|
-inline-threshold=1000 \
|
||||||
|
-fno-asynchronous-unwind-tables \
|
||||||
|
-fno-exceptions \
|
||||||
|
-fno-rtti \
|
||||||
|
-c string.c
|
||||||
|
|
||||||
|
COPY ./simd/string_avx.go ./string_avx.go
|
||||||
|
RUN c2goasm -a -f ./string.s ./string_avx.s
|
|
@ -0,0 +1,8 @@
|
||||||
|
.PHONY: asm
|
||||||
|
asm:
|
||||||
|
clang -Wall -S -O2 -mavx2 -masm=intel -mno-red-zone -mstackrealign -mllvm -inline-threshold=1000 -fno-asynchronous-unwind-tables -fno-exceptions -fno-rtti -c ./simd/string.c
|
||||||
|
|
||||||
|
.PHONY: generate
|
||||||
|
generate:
|
||||||
|
docker build -f Dockerfile.simd -t go-json-simd .
|
||||||
|
docker run --rm -v "$(CURDIR)/simd:/tmp" go-json-simd bash -c "cp /work/string_avx.s /tmp/string_avx.s"
|
|
@ -0,0 +1,9 @@
|
||||||
|
module github.com/goccy/go-json/internal/cmd/generator
|
||||||
|
|
||||||
|
go 1.17
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/klauspost/asmfmt v1.3.1
|
||||||
|
github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8
|
||||||
|
github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3
|
||||||
|
)
|
|
@ -0,0 +1,6 @@
|
||||||
|
github.com/klauspost/asmfmt v1.3.1 h1:7xZi1N7s9gTLbqiM8KUv8TLyysavbTRGBT5/ly0bRtw=
|
||||||
|
github.com/klauspost/asmfmt v1.3.1/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE=
|
||||||
|
github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8 h1:AMFGa4R4MiIpspGNG7Z948v4n35fFGB3RR3G/ry4FWs=
|
||||||
|
github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY=
|
||||||
|
github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3 h1:+n/aFZefKZp7spd8DFdX7uMikMLXX4oubIzJF4kv/wI=
|
||||||
|
github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE=
|
|
@ -8,6 +8,9 @@ import (
|
||||||
"go/printer"
|
"go/printer"
|
||||||
"go/token"
|
"go/token"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -302,6 +305,32 @@ func generateVM() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func generateSIMDSources() error {
|
||||||
|
root := repoRoot()
|
||||||
|
genCmd := exec.Command("make", "generate")
|
||||||
|
genCmd.Stdout = os.Stdout
|
||||||
|
genCmd.Stderr = os.Stderr
|
||||||
|
if err := genCmd.Run(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, srcName := range []string{
|
||||||
|
"string_avx.s",
|
||||||
|
"string_avx.go",
|
||||||
|
} {
|
||||||
|
srcFile := filepath.Join(root, "internal", "cmd", "generator", "simd", srcName)
|
||||||
|
dstFile := filepath.Join(root, "internal", "encoder", srcName)
|
||||||
|
log.Printf("copy %s to %s", srcFile, dstFile)
|
||||||
|
src, err := os.ReadFile(srcFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := os.WriteFile(dstFile, src, 0o600); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func repoRoot() string {
|
func repoRoot() string {
|
||||||
_, file, _, _ := runtime.Caller(0)
|
_, file, _, _ := runtime.Caller(0)
|
||||||
relativePathFromRepoRoot := filepath.Join("internal", "cmd", "generator")
|
relativePathFromRepoRoot := filepath.Join("internal", "cmd", "generator")
|
||||||
|
@ -310,6 +339,9 @@ func repoRoot() string {
|
||||||
|
|
||||||
//go:generate go run main.go
|
//go:generate go run main.go
|
||||||
func main() {
|
func main() {
|
||||||
|
if err := generateSIMDSources(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
if err := generateVM(); err != nil {
|
if err := generateVM(); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,266 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <immintrin.h>
|
||||||
|
|
||||||
|
static const bool needEscape[256] = {
|
||||||
|
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00-0x0F
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10-0x1F
|
||||||
|
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x20-0x2F
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x30-0x3F
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x40-0x4F
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, // 0x50-0x5F
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x60-0x6F
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x70-0x7F
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80-0x8F
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90-0x9F
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xA0-0xAF
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xB0-0xBF
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xC0-0xCF
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xD0-0xDF
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xE0-0xEF
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xF0-0xFF
|
||||||
|
};
|
||||||
|
|
||||||
|
uint64_t findHTMLEscapeIndex64(char *buf, int len) {
|
||||||
|
static const uint64_t lsb = 0x0101010101010101;
|
||||||
|
static const uint64_t msb = 0x8080808080808080;
|
||||||
|
|
||||||
|
static const uint64_t space = lsb * 0x20;
|
||||||
|
static const uint64_t quote = lsb * '"';
|
||||||
|
static const uint64_t escape = lsb * '\\';
|
||||||
|
static const uint64_t lt = lsb * '<';
|
||||||
|
static const uint64_t gt = lsb * '>';
|
||||||
|
static const uint64_t amp = lsb * '&';
|
||||||
|
|
||||||
|
char *sp = buf;
|
||||||
|
size_t chunkLen = len / 8;
|
||||||
|
int chunkIdx = 0;
|
||||||
|
for (; chunkIdx < chunkLen; chunkIdx++) {
|
||||||
|
uint64_t n = *(uint64_t *)sp;
|
||||||
|
uint64_t mask = n | (n - space) | ((n ^ quote) - lsb) | ((n ^ escape) - lsb) | ((n ^ lt) - lsb) | ((n ^ gt) - lsb) | ((n ^ amp) - lsb);
|
||||||
|
uint64_t masked = mask & msb;
|
||||||
|
if (masked != 0) {
|
||||||
|
return __builtin_ctz(masked) / 8;
|
||||||
|
}
|
||||||
|
sp += 8;
|
||||||
|
}
|
||||||
|
return chunkIdx * 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t findHTMLEscapeIndex128(char *buf, int len) {
|
||||||
|
static const uint64_t lsb = 0x0101010101010101;
|
||||||
|
static const uint64_t msb = 0x8080808080808080;
|
||||||
|
|
||||||
|
static const __m64 space = (__m64)(lsb * 0x20);
|
||||||
|
static const __m64 quote = (__m64)(lsb * '"');
|
||||||
|
static const __m64 escape = (__m64)(lsb * '\\');
|
||||||
|
static const __m64 lt = (__m64)(lsb * '<');
|
||||||
|
static const __m64 gt = (__m64)(lsb * '>');
|
||||||
|
static const __m64 amp = (__m64)(lsb * '&');
|
||||||
|
|
||||||
|
__m128i msbV = _mm_set_epi64((__m64)(msb), (__m64)(msb));
|
||||||
|
__m128i lsbV = _mm_set_epi64((__m64)(lsb), (__m64)(lsb));
|
||||||
|
__m128i spaceV = _mm_set_epi64(space, space);
|
||||||
|
__m128i quoteV = _mm_set_epi64(quote, quote);
|
||||||
|
__m128i escapeV = _mm_set_epi64(escape, escape);
|
||||||
|
__m128i ltV = _mm_set_epi64(lt, lt);
|
||||||
|
__m128i gtV = _mm_set_epi64(gt, gt);
|
||||||
|
__m128i ampV = _mm_set_epi64(amp, amp);
|
||||||
|
|
||||||
|
char *sp = buf;
|
||||||
|
size_t chunkLen = len / 16;
|
||||||
|
int chunkIdx = 0;
|
||||||
|
for (; chunkIdx < chunkLen; chunkIdx++) {
|
||||||
|
__m128i n = _mm_loadu_si128((const void *)sp);
|
||||||
|
__m128i spaceN = _mm_sub_epi64(n, spaceV);
|
||||||
|
__m128i quoteN = _mm_sub_epi64(_mm_xor_si128(n, quoteV), lsbV);
|
||||||
|
__m128i escapeN = _mm_sub_epi64(_mm_xor_si128(n, escapeV), lsbV);
|
||||||
|
__m128i ltN = _mm_sub_epi64(_mm_xor_si128(n, ltV), lsbV);
|
||||||
|
__m128i gtN = _mm_sub_epi64(_mm_xor_si128(n, gtV), lsbV);
|
||||||
|
__m128i ampN = _mm_sub_epi64(_mm_xor_si128(n, ampV), lsbV);
|
||||||
|
|
||||||
|
__m128i mask = _mm_or_si128(_mm_or_si128(_mm_or_si128(_mm_or_si128(_mm_or_si128(_mm_or_si128(n, spaceN), quoteN), escapeN), ltN), gtN), ampN);
|
||||||
|
int movemask = _mm_movemask_epi8(_mm_and_si128(mask, msbV));
|
||||||
|
if (movemask != 0) {
|
||||||
|
return __builtin_ctz(movemask);
|
||||||
|
}
|
||||||
|
sp += 16;
|
||||||
|
}
|
||||||
|
int idx = 16 * chunkLen;
|
||||||
|
if (len - idx >= 8) {
|
||||||
|
return idx + findHTMLEscapeIndex64(sp, len - idx);
|
||||||
|
}
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t findHTMLEscapeIndex256(char *buf, int len) {
|
||||||
|
static const uint64_t lsb = 0x0101010101010101;
|
||||||
|
static const uint64_t msb = 0x8080808080808080;
|
||||||
|
|
||||||
|
static const __m64 space = (__m64)(lsb * 0x20);
|
||||||
|
static const __m64 quote = (__m64)(lsb * '"');
|
||||||
|
static const __m64 escape = (__m64)(lsb * '\\');
|
||||||
|
static const __m64 lt = (__m64)(lsb * '<');
|
||||||
|
static const __m64 gt = (__m64)(lsb * '>');
|
||||||
|
static const __m64 amp = (__m64)(lsb * '&');
|
||||||
|
|
||||||
|
__m256i msbV = _mm256_set1_epi64x(msb);
|
||||||
|
__m256i lsbV = _mm256_set1_epi64x(lsb);
|
||||||
|
__m256i spaceV = _mm256_set1_epi64x(space);
|
||||||
|
__m256i quoteV = _mm256_set1_epi64x(quote);
|
||||||
|
__m256i escapeV = _mm256_set1_epi64x(escape);
|
||||||
|
__m256i ltV = _mm256_set1_epi64x(lt);
|
||||||
|
__m256i gtV = _mm256_set1_epi64x(gt);
|
||||||
|
__m256i ampV = _mm256_set1_epi64x(amp);
|
||||||
|
|
||||||
|
char *sp = buf;
|
||||||
|
size_t chunkLen = len / 32;
|
||||||
|
int chunkIdx = 0;
|
||||||
|
for (; chunkIdx < chunkLen; chunkIdx++) {
|
||||||
|
__m256i n = _mm256_loadu_si256((const void *)sp);
|
||||||
|
__m256i spaceN = _mm256_sub_epi64(n, spaceV);
|
||||||
|
__m256i quoteN = _mm256_sub_epi64(_mm256_xor_si256(n, quoteV), lsbV);
|
||||||
|
__m256i escapeN = _mm256_sub_epi64(_mm256_xor_si256(n, escapeV), lsbV);
|
||||||
|
__m256i ltN = _mm256_sub_epi64(_mm256_xor_si256(n, ltV), lsbV);
|
||||||
|
__m256i gtN = _mm256_sub_epi64(_mm256_xor_si256(n, gtV), lsbV);
|
||||||
|
__m256i ampN = _mm256_sub_epi64(_mm256_xor_si256(n, ampV), lsbV);
|
||||||
|
|
||||||
|
__m256i mask = _mm256_or_si256(_mm256_or_si256(_mm256_or_si256(_mm256_or_si256(_mm256_or_si256(_mm256_or_si256(n, spaceN), quoteN), escapeN), ltN), gtN), ampN);
|
||||||
|
int movemask = _mm256_movemask_epi8(_mm256_and_si256(mask, msbV));
|
||||||
|
if (movemask != 0) {
|
||||||
|
return __builtin_ctz(movemask);
|
||||||
|
}
|
||||||
|
sp += 32;
|
||||||
|
}
|
||||||
|
int idx = 32 * chunkLen;
|
||||||
|
int remainLen = len - idx;
|
||||||
|
if (remainLen >= 16) {
|
||||||
|
return idx + findHTMLEscapeIndex128(sp, remainLen);
|
||||||
|
} else if (remainLen >= 8) {
|
||||||
|
return idx + findHTMLEscapeIndex64(sp, remainLen);
|
||||||
|
}
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t findEscapeIndex64(char *buf, int len) {
|
||||||
|
static const uint64_t lsb = 0x0101010101010101;
|
||||||
|
static const uint64_t msb = 0x8080808080808080;
|
||||||
|
|
||||||
|
static const uint64_t space = lsb * 0x20;
|
||||||
|
static const uint64_t quote = lsb * '"';
|
||||||
|
static const uint64_t escape = lsb * '\\';
|
||||||
|
|
||||||
|
char *sp = buf;
|
||||||
|
size_t chunkLen = len / 8;
|
||||||
|
int chunkIdx = 0;
|
||||||
|
for (; chunkIdx < chunkLen; chunkIdx++) {
|
||||||
|
uint64_t n = *(uint64_t *)sp;
|
||||||
|
uint64_t mask = n | (n - space) | ((n ^ quote) - lsb) | ((n ^ escape) - lsb);
|
||||||
|
uint64_t masked = mask & msb;
|
||||||
|
if (masked != 0) {
|
||||||
|
return __builtin_ctz(masked) / 8;
|
||||||
|
}
|
||||||
|
sp += 8;
|
||||||
|
}
|
||||||
|
int idx = 8 * chunkLen;
|
||||||
|
bool *needEscape = needEscape;
|
||||||
|
for ( ;idx < len; idx++) {
|
||||||
|
if (needEscape[buf[idx]] != 0) {
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t findEscapeIndex128(char *buf, int len) {
|
||||||
|
static const uint64_t lsb = 0x0101010101010101;
|
||||||
|
static const uint64_t msb = 0x8080808080808080;
|
||||||
|
|
||||||
|
static const __m64 space = (__m64)(lsb * 0x20);
|
||||||
|
static const __m64 quote = (__m64)(lsb * '"');
|
||||||
|
static const __m64 escape = (__m64)(lsb * '\\');
|
||||||
|
|
||||||
|
__m128i msbV = _mm_set_epi64((__m64)(msb), (__m64)(msb));
|
||||||
|
__m128i lsbV = _mm_set_epi64((__m64)(lsb), (__m64)(lsb));
|
||||||
|
__m128i spaceV = _mm_set_epi64(space, space);
|
||||||
|
__m128i quoteV = _mm_set_epi64(quote, quote);
|
||||||
|
__m128i escapeV = _mm_set_epi64(escape, escape);
|
||||||
|
|
||||||
|
char *sp = buf;
|
||||||
|
size_t chunkLen = len / 16;
|
||||||
|
int chunkIdx = 0;
|
||||||
|
for (; chunkIdx < chunkLen; chunkIdx++) {
|
||||||
|
__m128i n = _mm_loadu_si128((const void *)sp);
|
||||||
|
__m128i spaceN = _mm_sub_epi64(n, spaceV);
|
||||||
|
__m128i quoteN = _mm_sub_epi64(_mm_xor_si128(n, quoteV), lsbV);
|
||||||
|
__m128i escapeN = _mm_sub_epi64(_mm_xor_si128(n, escapeV), lsbV);
|
||||||
|
|
||||||
|
__m128i mask = _mm_or_si128(_mm_or_si128(_mm_or_si128(n, spaceN), quoteN), escapeN);
|
||||||
|
int movemask = _mm_movemask_epi8(_mm_and_si128(mask, msbV));
|
||||||
|
if (movemask != 0) {
|
||||||
|
return __builtin_ctz(movemask);
|
||||||
|
}
|
||||||
|
sp += 16;
|
||||||
|
}
|
||||||
|
int idx = 16 * chunkLen;
|
||||||
|
int remainLen = len - idx;
|
||||||
|
if (remainLen >= 8) {
|
||||||
|
return idx + findEscapeIndex64(sp, remainLen);
|
||||||
|
}
|
||||||
|
bool *needEscape = needEscape;
|
||||||
|
for (; idx < len; idx++) {
|
||||||
|
if (needEscape[buf[idx]] != 0) {
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t findEscapeIndex256(char *buf, int len) {
|
||||||
|
static const uint64_t lsb = 0x0101010101010101;
|
||||||
|
static const uint64_t msb = 0x8080808080808080;
|
||||||
|
|
||||||
|
static const __m64 space = (__m64)(lsb * 0x20);
|
||||||
|
static const __m64 quote = (__m64)(lsb * '"');
|
||||||
|
static const __m64 escape = (__m64)(lsb * '\\');
|
||||||
|
|
||||||
|
__m256i msbV = _mm256_set1_epi64x(msb);
|
||||||
|
__m256i lsbV = _mm256_set1_epi64x(lsb);
|
||||||
|
__m256i spaceV = _mm256_set1_epi64x(space);
|
||||||
|
__m256i quoteV = _mm256_set1_epi64x(quote);
|
||||||
|
__m256i escapeV = _mm256_set1_epi64x(escape);
|
||||||
|
|
||||||
|
char *sp = buf;
|
||||||
|
size_t chunkLen = len / 32;
|
||||||
|
int chunkIdx = 0;
|
||||||
|
for (; chunkIdx < chunkLen; chunkIdx++) {
|
||||||
|
__m256i n = _mm256_loadu_si256((const void *)sp);
|
||||||
|
__m256i spaceN = _mm256_sub_epi64(n, spaceV);
|
||||||
|
__m256i quoteN = _mm256_sub_epi64(_mm256_xor_si256(n, quoteV), lsbV);
|
||||||
|
__m256i escapeN = _mm256_sub_epi64(_mm256_xor_si256(n, escapeV), lsbV);
|
||||||
|
|
||||||
|
__m256i mask = _mm256_or_si256(_mm256_or_si256(_mm256_or_si256(n, spaceN), quoteN), escapeN);
|
||||||
|
int movemask = _mm256_movemask_epi8(_mm256_and_si256(mask, msbV));
|
||||||
|
if (movemask != 0) {
|
||||||
|
return __builtin_ctz(movemask) + chunkIdx * 32;
|
||||||
|
}
|
||||||
|
sp += 32;
|
||||||
|
}
|
||||||
|
int idx = 32 * chunkLen;
|
||||||
|
int remainLen = len - idx;
|
||||||
|
if (remainLen >= 16) {
|
||||||
|
return idx + findEscapeIndex128(sp, remainLen);
|
||||||
|
} else if (remainLen >= 8) {
|
||||||
|
return idx + findEscapeIndex64(sp, remainLen);
|
||||||
|
}
|
||||||
|
bool *needEscape = needEscape;
|
||||||
|
for (; idx < len; idx++) {
|
||||||
|
if (needEscape[buf[idx]] != 0) {
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package encoder
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
//go:nosplit
|
||||||
|
//go:noescape
|
||||||
|
func _findHTMLEscapeIndex64(buf unsafe.Pointer, len int) (ret int)
|
||||||
|
|
||||||
|
//go:nosplit
|
||||||
|
//go:noescape
|
||||||
|
func _findHTMLEscapeIndex128(buf unsafe.Pointer, len int) (ret int)
|
||||||
|
|
||||||
|
//go:nosplit
|
||||||
|
//go:noescape
|
||||||
|
func _findHTMLEscapeIndex256(buf unsafe.Pointer, len int) (ret int)
|
||||||
|
|
||||||
|
//go:nosplit
|
||||||
|
//go:noescape
|
||||||
|
func _findEscapeIndex64(buf unsafe.Pointer, len int) (ret int)
|
||||||
|
|
||||||
|
//go:nosplit
|
||||||
|
//go:noescape
|
||||||
|
func _findEscapeIndex128(buf unsafe.Pointer, len int) (ret int)
|
||||||
|
|
||||||
|
//go:nosplit
|
||||||
|
//go:noescape
|
||||||
|
func _findEscapeIndex256(buf unsafe.Pointer, len int) (ret int)
|
|
@ -0,0 +1,7 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "github.com/klauspost/asmfmt/cmd/asmfmt"
|
||||||
|
_ "github.com/minio/asm2plan9s"
|
||||||
|
_ "github.com/minio/c2goasm"
|
||||||
|
)
|
|
@ -402,12 +402,13 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
code = code.End.Next
|
code = code.End.Next
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
b = appendStructHead(ctx, b)
|
unorderedMap := (ctx.Option.Flag & encoder.UnorderedMapOption) != 0
|
||||||
mapCtx := encoder.NewMapContext(mlen)
|
mapCtx := encoder.NewMapContext(mlen, unorderedMap)
|
||||||
mapiterinit(code.Type, uptr, &mapCtx.Iter)
|
mapiterinit(code.Type, uptr, &mapCtx.Iter)
|
||||||
store(ctxptr, code.Idx, uintptr(unsafe.Pointer(mapCtx)))
|
store(ctxptr, code.Idx, uintptr(unsafe.Pointer(mapCtx)))
|
||||||
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx))
|
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx))
|
||||||
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
b = appendStructHead(ctx, b)
|
||||||
|
if unorderedMap {
|
||||||
b = appendMapKeyIndent(ctx, code.Next, b)
|
b = appendMapKeyIndent(ctx, code.Next, b)
|
||||||
} else {
|
} else {
|
||||||
mapCtx.Start = len(b)
|
mapCtx.Start = len(b)
|
||||||
|
|
|
@ -44,13 +44,6 @@ var first = [256]uint8{
|
||||||
s5, s6, s6, s6, s7, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xF0-0xFF
|
s5, s6, s6, s6, s7, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xF0-0xFF
|
||||||
}
|
}
|
||||||
|
|
||||||
// acceptRange gives the range of valid values for the second byte in a UTF-8
|
|
||||||
// sequence.
|
|
||||||
type acceptRange struct {
|
|
||||||
lo uint8 // lowest value for second byte.
|
|
||||||
hi uint8 // highest value for second byte.
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
lineSep = byte(168) //'\u2028'
|
lineSep = byte(168) //'\u2028'
|
||||||
paragraphSep = byte(169) //'\u2029'
|
paragraphSep = byte(169) //'\u2029'
|
||||||
|
@ -80,25 +73,31 @@ func decodeRuneInString(s string) (decodeRuneState, int) {
|
||||||
return validUTF8State, 1
|
return validUTF8State, 1
|
||||||
}
|
}
|
||||||
sz := int(x & 7)
|
sz := int(x & 7)
|
||||||
var accept acceptRange
|
|
||||||
switch x >> 4 {
|
|
||||||
case 0:
|
|
||||||
accept = acceptRange{locb, hicb}
|
|
||||||
case 1:
|
|
||||||
accept = acceptRange{0xA0, hicb}
|
|
||||||
case 2:
|
|
||||||
accept = acceptRange{locb, 0x9F}
|
|
||||||
case 3:
|
|
||||||
accept = acceptRange{0x90, hicb}
|
|
||||||
case 4:
|
|
||||||
accept = acceptRange{locb, 0x8F}
|
|
||||||
}
|
|
||||||
if n < sz {
|
if n < sz {
|
||||||
return runeErrorState, 1
|
return runeErrorState, 1
|
||||||
}
|
}
|
||||||
s1 := s[1]
|
s1 := s[1]
|
||||||
if s1 < accept.lo || accept.hi < s1 {
|
switch x >> 4 {
|
||||||
return runeErrorState, 1
|
case 0:
|
||||||
|
if s1 < locb || hicb < s1 {
|
||||||
|
return runeErrorState, 1
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
if s1 < 0xA0 || hicb < s1 {
|
||||||
|
return runeErrorState, 1
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
if s1 < locb || 0x9F < s1 {
|
||||||
|
return runeErrorState, 1
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
if s1 < 0x90 || hicb < s1 {
|
||||||
|
return runeErrorState, 1
|
||||||
|
}
|
||||||
|
case 4:
|
||||||
|
if s1 < locb || 0x8F < s1 {
|
||||||
|
return runeErrorState, 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if sz <= 2 {
|
if sz <= 2 {
|
||||||
return validUTF8State, 2
|
return validUTF8State, 2
|
||||||
|
|
|
@ -259,12 +259,14 @@ var mapContextPool = sync.Pool{
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMapContext(mapLen int) *MapContext {
|
func NewMapContext(mapLen int, unorderedMap bool) *MapContext {
|
||||||
ctx := mapContextPool.Get().(*MapContext)
|
ctx := mapContextPool.Get().(*MapContext)
|
||||||
if len(ctx.Slice.Items) < mapLen {
|
if !unorderedMap {
|
||||||
ctx.Slice.Items = make([]MapItem, mapLen)
|
if len(ctx.Slice.Items) < mapLen {
|
||||||
} else {
|
ctx.Slice.Items = make([]MapItem, mapLen)
|
||||||
ctx.Slice.Items = ctx.Slice.Items[:mapLen]
|
} else {
|
||||||
|
ctx.Slice.Items = ctx.Slice.Items[:mapLen]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ctx.Buf = ctx.Buf[:0]
|
ctx.Buf = ctx.Buf[:0]
|
||||||
ctx.Iter = mapIter{}
|
ctx.Iter = mapIter{}
|
||||||
|
|
|
@ -4,6 +4,8 @@ import (
|
||||||
"math/bits"
|
"math/bits"
|
||||||
"reflect"
|
"reflect"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goccy/go-json/internal/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -369,42 +371,166 @@ func AppendString(ctx *RuntimeContext, buf []byte, s string) []byte {
|
||||||
var (
|
var (
|
||||||
i, j int
|
i, j int
|
||||||
)
|
)
|
||||||
if valLen >= 8 {
|
orgLen := valLen
|
||||||
chunks := stringToUint64Slice(s)
|
base := (*runtime.SliceHeader)(unsafe.Pointer(&s)).Data
|
||||||
for _, n := range chunks {
|
for {
|
||||||
// combine masks before checking for the MSB of each byte. We include
|
valLen = len(s) - j
|
||||||
// `n` in the mask to check whether any of the *input* byte MSBs were
|
if valLen <= 0 {
|
||||||
// set (i.e. the byte was outside the ASCII range).
|
return append(append(buf, s[i:]...), '"')
|
||||||
mask := n | (n - (lsb * 0x20)) |
|
|
||||||
((n ^ (lsb * '"')) - lsb) |
|
|
||||||
((n ^ (lsb * '\\')) - lsb) |
|
|
||||||
((n ^ (lsb * '<')) - lsb) |
|
|
||||||
((n ^ (lsb * '>')) - lsb) |
|
|
||||||
((n ^ (lsb * '&')) - lsb)
|
|
||||||
if (mask & msb) != 0 {
|
|
||||||
j = bits.TrailingZeros64(mask&msb) / 8
|
|
||||||
goto ESCAPE_END
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for i := len(chunks) * 8; i < valLen; i++ {
|
data := unsafe.Pointer(uintptr(base) + uintptr(j))
|
||||||
if needEscapeWithHTML[s[i]] {
|
switch valLen {
|
||||||
j = i
|
case 1:
|
||||||
goto ESCAPE_END
|
if needEscapeWithHTML[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
}
|
}
|
||||||
|
return append(append(buf, s[i:]...), '"')
|
||||||
|
case 2:
|
||||||
|
if needEscapeWithHTML[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscapeWithHTML[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
return append(append(buf, s[i:]...), '"')
|
||||||
|
case 3:
|
||||||
|
if needEscapeWithHTML[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscapeWithHTML[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscapeWithHTML[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
return append(append(buf, s[i:]...), '"')
|
||||||
|
case 4:
|
||||||
|
if needEscapeWithHTML[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscapeWithHTML[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscapeWithHTML[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscapeWithHTML[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
return append(append(buf, s[i:]...), '"')
|
||||||
|
case 5:
|
||||||
|
if needEscapeWithHTML[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscapeWithHTML[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscapeWithHTML[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscapeWithHTML[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscapeWithHTML[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
return append(append(buf, s[i:]...), '"')
|
||||||
|
case 6:
|
||||||
|
if needEscapeWithHTML[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscapeWithHTML[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscapeWithHTML[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscapeWithHTML[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscapeWithHTML[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscapeWithHTML[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
return append(append(buf, s[i:]...), '"')
|
||||||
|
case 7:
|
||||||
|
if needEscapeWithHTML[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscapeWithHTML[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscapeWithHTML[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscapeWithHTML[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscapeWithHTML[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscapeWithHTML[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscapeWithHTML[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
return append(append(buf, s[i:]...), '"')
|
||||||
|
case 8, 9, 10, 11, 12, 13, 14, 15:
|
||||||
|
chunks := stringToUint64Slice(s[j:])
|
||||||
|
for _, n := range chunks {
|
||||||
|
// combine masks before checking for the MSB of each byte. We include
|
||||||
|
// `n` in the mask to check whether any of the *input* byte MSBs were
|
||||||
|
// set (i.e. the byte was outside the ASCII range).
|
||||||
|
mask := n | (n - (lsb * 0x20)) |
|
||||||
|
((n ^ (lsb * '"')) - lsb) |
|
||||||
|
((n ^ (lsb * '\\')) - lsb) |
|
||||||
|
((n ^ (lsb * '<')) - lsb) |
|
||||||
|
((n ^ (lsb * '>')) - lsb) |
|
||||||
|
((n ^ (lsb * '&')) - lsb)
|
||||||
|
if (mask & msb) != 0 {
|
||||||
|
j += bits.TrailingZeros64(mask&msb) / 8
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
j += len(chunks) * 8
|
||||||
|
case 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31:
|
||||||
|
j += _findHTMLEscapeIndex128(data, valLen)
|
||||||
|
default:
|
||||||
|
j += _findHTMLEscapeIndex256(data, valLen)
|
||||||
}
|
}
|
||||||
// no found any escape characters.
|
if j >= orgLen {
|
||||||
return append(append(buf, s...), '"')
|
return append(append(buf, s[i:]...), '"')
|
||||||
}
|
}
|
||||||
ESCAPE_END:
|
ESCAPE:
|
||||||
for j < valLen {
|
|
||||||
c := s[j]
|
c := s[j]
|
||||||
|
|
||||||
if !needEscapeWithHTML[c] {
|
if !needEscapeWithHTML[c] {
|
||||||
// fast path: most of the time, printable ascii characters are used
|
|
||||||
j++
|
j++
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
switch c {
|
switch c {
|
||||||
case '\\', '"':
|
case '\\', '"':
|
||||||
buf = append(buf, s[i:j]...)
|
buf = append(buf, s[i:j]...)
|
||||||
|
@ -451,7 +577,6 @@ ESCAPE_END:
|
||||||
j = j + 1
|
j = j + 1
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
state, size := decodeRuneInString(s[j:])
|
state, size := decodeRuneInString(s[j:])
|
||||||
switch state {
|
switch state {
|
||||||
case runeErrorState:
|
case runeErrorState:
|
||||||
|
@ -482,8 +607,6 @@ ESCAPE_END:
|
||||||
}
|
}
|
||||||
j += size
|
j += size
|
||||||
}
|
}
|
||||||
|
|
||||||
return append(append(buf, s[i:]...), '"')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func appendString(buf []byte, s string) []byte {
|
func appendString(buf []byte, s string) []byte {
|
||||||
|
@ -495,39 +618,146 @@ func appendString(buf []byte, s string) []byte {
|
||||||
var (
|
var (
|
||||||
i, j int
|
i, j int
|
||||||
)
|
)
|
||||||
if valLen >= 8 {
|
base := (*runtime.SliceHeader)(unsafe.Pointer(&s)).Data
|
||||||
chunks := stringToUint64Slice(s)
|
orgLen := valLen
|
||||||
for _, n := range chunks {
|
for {
|
||||||
// combine masks before checking for the MSB of each byte. We include
|
valLen = len(s) - j
|
||||||
// `n` in the mask to check whether any of the *input* byte MSBs were
|
if valLen <= 0 {
|
||||||
// set (i.e. the byte was outside the ASCII range).
|
return append(append(buf, s[i:]...), '"')
|
||||||
mask := n | (n - (lsb * 0x20)) |
|
|
||||||
((n ^ (lsb * '"')) - lsb) |
|
|
||||||
((n ^ (lsb * '\\')) - lsb)
|
|
||||||
if (mask & msb) != 0 {
|
|
||||||
j = bits.TrailingZeros64(mask&msb) / 8
|
|
||||||
goto ESCAPE_END
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
valLen := len(s)
|
data := unsafe.Pointer(uintptr(base) + uintptr(j))
|
||||||
for i := len(chunks) * 8; i < valLen; i++ {
|
switch valLen {
|
||||||
if needEscape[s[i]] {
|
case 1:
|
||||||
j = i
|
if needEscape[s[j]] {
|
||||||
goto ESCAPE_END
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
return append(buf, s[i], '"')
|
||||||
|
case 2:
|
||||||
|
if needEscape[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return append(append(buf, s...), '"')
|
|
||||||
}
|
|
||||||
ESCAPE_END:
|
|
||||||
for j < valLen {
|
|
||||||
c := s[j]
|
|
||||||
|
|
||||||
if !needEscape[c] {
|
|
||||||
// fast path: most of the time, printable ascii characters are used
|
|
||||||
j++
|
j++
|
||||||
continue
|
if needEscape[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
return append(append(buf, s[i:]...), '"')
|
||||||
|
case 3:
|
||||||
|
if needEscape[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscape[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscape[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
return append(append(buf, s[i:]...), '"')
|
||||||
|
case 4:
|
||||||
|
if needEscape[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscape[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscape[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscape[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
return append(append(buf, s[i:]...), '"')
|
||||||
|
case 5:
|
||||||
|
if needEscape[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscape[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscape[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscape[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscape[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
return append(append(buf, s[i:]...), '"')
|
||||||
|
case 6:
|
||||||
|
if needEscape[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscape[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscape[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscape[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscape[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscape[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
return append(append(buf, s[i:]...), '"')
|
||||||
|
case 7:
|
||||||
|
if needEscape[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscape[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscape[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscape[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscape[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscape[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if needEscape[s[j]] {
|
||||||
|
goto ESCAPE
|
||||||
|
}
|
||||||
|
return append(append(buf, s[i:]...), '"')
|
||||||
|
case 8, 9, 10, 11, 12, 13, 14, 15:
|
||||||
|
j += _findEscapeIndex64(data, valLen)
|
||||||
|
case 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31:
|
||||||
|
j += _findEscapeIndex128(data, valLen)
|
||||||
|
default:
|
||||||
|
j += _findEscapeIndex256(data, valLen)
|
||||||
}
|
}
|
||||||
|
if j == orgLen {
|
||||||
|
return append(append(buf, s[i:]...), '"')
|
||||||
|
}
|
||||||
|
ESCAPE:
|
||||||
|
c := s[j]
|
||||||
switch c {
|
switch c {
|
||||||
case '\\', '"':
|
case '\\', '"':
|
||||||
buf = append(buf, s[i:j]...)
|
buf = append(buf, s[i:j]...)
|
||||||
|
@ -557,14 +787,6 @@ ESCAPE_END:
|
||||||
j = j + 1
|
j = j + 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
case '<', '>', '&':
|
|
||||||
buf = append(buf, s[i:j]...)
|
|
||||||
buf = append(buf, `\u00`...)
|
|
||||||
buf = append(buf, hex[c>>4], hex[c&0xF])
|
|
||||||
i = j + 1
|
|
||||||
j = j + 1
|
|
||||||
continue
|
|
||||||
|
|
||||||
case 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0B, 0x0C, 0x0E, 0x0F, // 0x00-0x0F
|
case 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0B, 0x0C, 0x0E, 0x0F, // 0x00-0x0F
|
||||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F: // 0x10-0x1F
|
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F: // 0x10-0x1F
|
||||||
buf = append(buf, s[i:j]...)
|
buf = append(buf, s[i:j]...)
|
||||||
|
@ -574,7 +796,6 @@ ESCAPE_END:
|
||||||
j = j + 1
|
j = j + 1
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
state, size := decodeRuneInString(s[j:])
|
state, size := decodeRuneInString(s[j:])
|
||||||
switch state {
|
switch state {
|
||||||
case runeErrorState:
|
case runeErrorState:
|
||||||
|
@ -605,6 +826,4 @@ ESCAPE_END:
|
||||||
}
|
}
|
||||||
j += size
|
j += size
|
||||||
}
|
}
|
||||||
|
|
||||||
return append(append(buf, s[i:]...), '"')
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
package encoder
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
//go:nosplit
|
||||||
|
//go:noescape
|
||||||
|
func _findHTMLEscapeIndex64(buf unsafe.Pointer, len int) (ret int)
|
||||||
|
|
||||||
|
//go:nosplit
|
||||||
|
//go:noescape
|
||||||
|
func _findHTMLEscapeIndex128(buf unsafe.Pointer, len int) (ret int)
|
||||||
|
|
||||||
|
//go:nosplit
|
||||||
|
//go:noescape
|
||||||
|
func _findHTMLEscapeIndex256(buf unsafe.Pointer, len int) (ret int)
|
||||||
|
|
||||||
|
//go:nosplit
|
||||||
|
//go:noescape
|
||||||
|
func _findEscapeIndex64(buf unsafe.Pointer, len int) (ret int)
|
||||||
|
|
||||||
|
//go:nosplit
|
||||||
|
//go:noescape
|
||||||
|
func _findEscapeIndex128(buf unsafe.Pointer, len int) (ret int)
|
||||||
|
|
||||||
|
//go:nosplit
|
||||||
|
//go:noescape
|
||||||
|
func _findEscapeIndex256(buf unsafe.Pointer, len int) (ret int)
|
|
@ -0,0 +1,818 @@
|
||||||
|
//+build !noasm !appengine
|
||||||
|
// AUTO-GENERATED BY C2GOASM -- DO NOT EDIT
|
||||||
|
|
||||||
|
TEXT ·_findHTMLEscapeIndex64(SB), $0-24
|
||||||
|
|
||||||
|
MOVQ buf+0(FP), DI
|
||||||
|
MOVQ len+8(FP), SI
|
||||||
|
|
||||||
|
WORD $0xf089 // mov eax, esi
|
||||||
|
WORD $0xf8c1; BYTE $0x1f // sar eax, 31
|
||||||
|
WORD $0xe8c1; BYTE $0x1d // shr eax, 29
|
||||||
|
WORD $0xf001 // add eax, esi
|
||||||
|
WORD $0xf8c1; BYTE $0x03 // sar eax, 3
|
||||||
|
WORD $0x9848 // cdqe
|
||||||
|
WORD $0xc683; BYTE $0x07 // add esi, 7
|
||||||
|
WORD $0xfe83; BYTE $0x0f // cmp esi, 15
|
||||||
|
JB LBB0_5
|
||||||
|
QUAD $0xfefefefefeffbd49; WORD $0xfefe // mov r13, -72340172838076673
|
||||||
|
WORD $0xd231 // xor edx, edx
|
||||||
|
QUAD $0x222222222222b949; WORD $0x2222 // mov r9, 2459565876494606882
|
||||||
|
QUAD $0x5c5c5c5c5c5cba49; WORD $0x5c5c // mov r10, 6655295901103053916
|
||||||
|
QUAD $0x3c3c3c3c3c3cbb49; WORD $0x3c3c // mov r11, 4340410370284600380
|
||||||
|
QUAD $0x3e3e3e3e3e3ebe49; WORD $0x3e3e // mov r14, 4485090715960753726
|
||||||
|
QUAD $0x262626262626bf49; WORD $0x2626 // mov r15, 2748926567846913574
|
||||||
|
QUAD $0x808080808080bc49; WORD $0x8080 // mov r12, -9187201950435737472
|
||||||
|
|
||||||
|
LBB0_2:
|
||||||
|
LONG $0xd71c8b48 // mov rbx, qword [rdi + 8*rdx]
|
||||||
|
QUAD $0xdfdfdfdfdfe0b948; WORD $0xdfdf // mov rcx, -2314885530818453536
|
||||||
|
LONG $0x0b348d48 // lea rsi, [rbx + rcx]
|
||||||
|
WORD $0x0948; BYTE $0xde // or rsi, rbx
|
||||||
|
WORD $0x8948; BYTE $0xd9 // mov rcx, rbx
|
||||||
|
WORD $0x314c; BYTE $0xc9 // xor rcx, r9
|
||||||
|
WORD $0x014c; BYTE $0xe9 // add rcx, r13
|
||||||
|
WORD $0x0948; BYTE $0xf1 // or rcx, rsi
|
||||||
|
WORD $0x8948; BYTE $0xde // mov rsi, rbx
|
||||||
|
WORD $0x314c; BYTE $0xd6 // xor rsi, r10
|
||||||
|
WORD $0x014c; BYTE $0xee // add rsi, r13
|
||||||
|
WORD $0x8949; BYTE $0xd8 // mov r8, rbx
|
||||||
|
WORD $0x314d; BYTE $0xd8 // xor r8, r11
|
||||||
|
WORD $0x014d; BYTE $0xe8 // add r8, r13
|
||||||
|
WORD $0x0949; BYTE $0xf0 // or r8, rsi
|
||||||
|
WORD $0x0949; BYTE $0xc8 // or r8, rcx
|
||||||
|
WORD $0x8948; BYTE $0xd9 // mov rcx, rbx
|
||||||
|
WORD $0x314c; BYTE $0xf1 // xor rcx, r14
|
||||||
|
WORD $0x014c; BYTE $0xe9 // add rcx, r13
|
||||||
|
WORD $0x314c; BYTE $0xfb // xor rbx, r15
|
||||||
|
WORD $0x014c; BYTE $0xeb // add rbx, r13
|
||||||
|
WORD $0x0948; BYTE $0xcb // or rbx, rcx
|
||||||
|
WORD $0x094c; BYTE $0xc3 // or rbx, r8
|
||||||
|
WORD $0x214c; BYTE $0xe3 // and rbx, r12
|
||||||
|
JNE LBB0_3
|
||||||
|
LONG $0x01c28348 // add rdx, 1
|
||||||
|
WORD $0x3948; BYTE $0xc2 // cmp rdx, rax
|
||||||
|
JB LBB0_2
|
||||||
|
|
||||||
|
LBB0_5:
|
||||||
|
LONG $0x03e0c148 // shl rax, 3
|
||||||
|
JMP LBB0_6
|
||||||
|
|
||||||
|
LBB0_3:
|
||||||
|
WORD $0xbc0f; BYTE $0xc3 // bsf eax, ebx
|
||||||
|
WORD $0xe8c1; BYTE $0x03 // shr eax, 3
|
||||||
|
|
||||||
|
LBB0_6:
|
||||||
|
MOVQ AX, ret+16(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
DATA LCDATA1<>+0x000(SB)/8, $0xdfdfdfdfdfdfdfe0
|
||||||
|
DATA LCDATA1<>+0x008(SB)/8, $0xdfdfdfdfdfdfdfe0
|
||||||
|
DATA LCDATA1<>+0x010(SB)/8, $0x2222222222222222
|
||||||
|
DATA LCDATA1<>+0x018(SB)/8, $0x2222222222222222
|
||||||
|
DATA LCDATA1<>+0x020(SB)/8, $0xfefefefefefefeff
|
||||||
|
DATA LCDATA1<>+0x028(SB)/8, $0xfefefefefefefeff
|
||||||
|
DATA LCDATA1<>+0x030(SB)/8, $0x5c5c5c5c5c5c5c5c
|
||||||
|
DATA LCDATA1<>+0x038(SB)/8, $0x5c5c5c5c5c5c5c5c
|
||||||
|
DATA LCDATA1<>+0x040(SB)/8, $0x3c3c3c3c3c3c3c3c
|
||||||
|
DATA LCDATA1<>+0x048(SB)/8, $0x3c3c3c3c3c3c3c3c
|
||||||
|
DATA LCDATA1<>+0x050(SB)/8, $0x3e3e3e3e3e3e3e3e
|
||||||
|
DATA LCDATA1<>+0x058(SB)/8, $0x3e3e3e3e3e3e3e3e
|
||||||
|
DATA LCDATA1<>+0x060(SB)/8, $0x2626262626262626
|
||||||
|
DATA LCDATA1<>+0x068(SB)/8, $0x2626262626262626
|
||||||
|
DATA LCDATA1<>+0x070(SB)/8, $0x8080808080808080
|
||||||
|
DATA LCDATA1<>+0x078(SB)/8, $0x8080808080808080
|
||||||
|
GLOBL LCDATA1<>(SB), 8, $128
|
||||||
|
|
||||||
|
TEXT ·_findHTMLEscapeIndex128(SB), $16-24
|
||||||
|
|
||||||
|
MOVQ buf+0(FP), DI
|
||||||
|
MOVQ len+8(FP), SI
|
||||||
|
ADDQ $8, SP
|
||||||
|
LEAQ LCDATA1<>(SB), BP
|
||||||
|
|
||||||
|
WORD $0xf089 // mov eax, esi
|
||||||
|
WORD $0xf8c1; BYTE $0x1f // sar eax, 31
|
||||||
|
WORD $0xe8c1; BYTE $0x1c // shr eax, 28
|
||||||
|
WORD $0xf001 // add eax, esi
|
||||||
|
WORD $0xf8c1; BYTE $0x04 // sar eax, 4
|
||||||
|
WORD $0x4e8d; BYTE $0x0f // lea ecx, [rsi + 15]
|
||||||
|
WORD $0xf983; BYTE $0x1f // cmp ecx, 31
|
||||||
|
JB LBB1_5
|
||||||
|
WORD $0x6348; BYTE $0xc8 // movsxd rcx, eax
|
||||||
|
WORD $0xd231 // xor edx, edx
|
||||||
|
LONG $0x456f79c5; BYTE $0x00 // vmovdqa xmm8, oword 0[rbp] /* [rip + .LCPI1_0] */
|
||||||
|
LONG $0x4d6f79c5; BYTE $0x10 // vmovdqa xmm9, oword 16[rbp] /* [rip + .LCPI1_1] */
|
||||||
|
LONG $0x556ff9c5; BYTE $0x20 // vmovdqa xmm2, oword 32[rbp] /* [rip + .LCPI1_2] */
|
||||||
|
LONG $0x556f79c5; BYTE $0x30 // vmovdqa xmm10, oword 48[rbp] /* [rip + .LCPI1_3] */
|
||||||
|
LONG $0x5d6f79c5; BYTE $0x40 // vmovdqa xmm11, oword 64[rbp] /* [rip + .LCPI1_4] */
|
||||||
|
LONG $0x656f79c5; BYTE $0x50 // vmovdqa xmm12, oword 80[rbp] /* [rip + .LCPI1_5] */
|
||||||
|
LONG $0x6d6f79c5; BYTE $0x60 // vmovdqa xmm13, oword 96[rbp] /* [rip + .LCPI1_6] */
|
||||||
|
LONG $0x7d6ff9c5; BYTE $0x70 // vmovdqa xmm7, oword 112[rbp] /* [rip + .LCPI1_7] */
|
||||||
|
|
||||||
|
LBB1_2:
|
||||||
|
LONG $0x076ffac5 // vmovdqu xmm0, oword [rdi]
|
||||||
|
LONG $0xd479c1c4; BYTE $0xc8 // vpaddq xmm1, xmm0, xmm8
|
||||||
|
LONG $0xef79c1c4; BYTE $0xd9 // vpxor xmm3, xmm0, xmm9
|
||||||
|
LONG $0xdad4e1c5 // vpaddq xmm3, xmm3, xmm2
|
||||||
|
LONG $0xef79c1c4; BYTE $0xe2 // vpxor xmm4, xmm0, xmm10
|
||||||
|
LONG $0xe2d4d9c5 // vpaddq xmm4, xmm4, xmm2
|
||||||
|
LONG $0xef79c1c4; BYTE $0xeb // vpxor xmm5, xmm0, xmm11
|
||||||
|
LONG $0xead4d1c5 // vpaddq xmm5, xmm5, xmm2
|
||||||
|
LONG $0xe5ebd9c5 // vpor xmm4, xmm4, xmm5
|
||||||
|
LONG $0xef79c1c4; BYTE $0xec // vpxor xmm5, xmm0, xmm12
|
||||||
|
LONG $0xead4d1c5 // vpaddq xmm5, xmm5, xmm2
|
||||||
|
LONG $0xef79c1c4; BYTE $0xf5 // vpxor xmm6, xmm0, xmm13
|
||||||
|
LONG $0xf2d4c9c5 // vpaddq xmm6, xmm6, xmm2
|
||||||
|
LONG $0xeeebd1c5 // vpor xmm5, xmm5, xmm6
|
||||||
|
LONG $0xc0ebf1c5 // vpor xmm0, xmm1, xmm0
|
||||||
|
LONG $0xc3ebf9c5 // vpor xmm0, xmm0, xmm3
|
||||||
|
LONG $0xc4ebf9c5 // vpor xmm0, xmm0, xmm4
|
||||||
|
LONG $0xc5ebf9c5 // vpor xmm0, xmm0, xmm5
|
||||||
|
LONG $0xc7dbf9c5 // vpand xmm0, xmm0, xmm7
|
||||||
|
LONG $0xd8d7f9c5 // vpmovmskb ebx, xmm0
|
||||||
|
WORD $0xdb85 // test ebx, ebx
|
||||||
|
JNE LBB1_3
|
||||||
|
LONG $0x10c78348 // add rdi, 16
|
||||||
|
LONG $0x01c28348 // add rdx, 1
|
||||||
|
WORD $0x3948; BYTE $0xca // cmp rdx, rcx
|
||||||
|
JB LBB1_2
|
||||||
|
|
||||||
|
LBB1_5:
|
||||||
|
WORD $0xe0c1; BYTE $0x04 // shl eax, 4
|
||||||
|
WORD $0xc629 // sub esi, eax
|
||||||
|
WORD $0x9848 // cdqe
|
||||||
|
WORD $0xfe83; BYTE $0x08 // cmp esi, 8
|
||||||
|
JL LBB1_12
|
||||||
|
LONG $0x24048948 // mov qword [rsp], rax
|
||||||
|
QUAD $0xfefefefefeffba49; WORD $0xfefe // mov r10, -72340172838076673
|
||||||
|
WORD $0x8941; BYTE $0xf0 // mov r8d, esi
|
||||||
|
LONG $0x03e8c141 // shr r8d, 3
|
||||||
|
WORD $0x3145; BYTE $0xdb // xor r11d, r11d
|
||||||
|
QUAD $0x3c3c3c3c3c3cbe49; WORD $0x3c3c // mov r14, 4340410370284600380
|
||||||
|
QUAD $0x3e3e3e3e3e3ebf49; WORD $0x3e3e // mov r15, 4485090715960753726
|
||||||
|
QUAD $0x262626262626bc49; WORD $0x2626 // mov r12, 2748926567846913574
|
||||||
|
QUAD $0x808080808080bd49; WORD $0x8080 // mov r13, -9187201950435737472
|
||||||
|
|
||||||
|
LBB1_7:
|
||||||
|
LONG $0xdf1c8b4a // mov rbx, qword [rdi + 8*r11]
|
||||||
|
QUAD $0xdfdfdfdfdfe0b848; WORD $0xdfdf // mov rax, -2314885530818453536
|
||||||
|
LONG $0x030c8d4c // lea r9, [rbx + rax]
|
||||||
|
WORD $0x0949; BYTE $0xd9 // or r9, rbx
|
||||||
|
WORD $0x8948; BYTE $0xd8 // mov rax, rbx
|
||||||
|
QUAD $0x222222222222b948; WORD $0x2222 // mov rcx, 2459565876494606882
|
||||||
|
WORD $0x3148; BYTE $0xc8 // xor rax, rcx
|
||||||
|
WORD $0x014c; BYTE $0xd0 // add rax, r10
|
||||||
|
WORD $0x094c; BYTE $0xc8 // or rax, r9
|
||||||
|
WORD $0x8948; BYTE $0xd9 // mov rcx, rbx
|
||||||
|
QUAD $0x5c5c5c5c5c5cba48; WORD $0x5c5c // mov rdx, 6655295901103053916
|
||||||
|
WORD $0x3148; BYTE $0xd1 // xor rcx, rdx
|
||||||
|
WORD $0x014c; BYTE $0xd1 // add rcx, r10
|
||||||
|
WORD $0x8948; BYTE $0xda // mov rdx, rbx
|
||||||
|
WORD $0x314c; BYTE $0xf2 // xor rdx, r14
|
||||||
|
WORD $0x014c; BYTE $0xd2 // add rdx, r10
|
||||||
|
WORD $0x0948; BYTE $0xca // or rdx, rcx
|
||||||
|
WORD $0x0948; BYTE $0xc2 // or rdx, rax
|
||||||
|
WORD $0x8948; BYTE $0xd8 // mov rax, rbx
|
||||||
|
WORD $0x314c; BYTE $0xf8 // xor rax, r15
|
||||||
|
WORD $0x014c; BYTE $0xd0 // add rax, r10
|
||||||
|
WORD $0x314c; BYTE $0xe3 // xor rbx, r12
|
||||||
|
WORD $0x014c; BYTE $0xd3 // add rbx, r10
|
||||||
|
WORD $0x0948; BYTE $0xc3 // or rbx, rax
|
||||||
|
WORD $0x0948; BYTE $0xd3 // or rbx, rdx
|
||||||
|
WORD $0x214c; BYTE $0xeb // and rbx, r13
|
||||||
|
JNE LBB1_8
|
||||||
|
LONG $0x01c38349 // add r11, 1
|
||||||
|
WORD $0x394d; BYTE $0xc3 // cmp r11, r8
|
||||||
|
JB LBB1_7
|
||||||
|
WORD $0xe683; BYTE $0xf8 // and esi, -8
|
||||||
|
JMP LBB1_11
|
||||||
|
|
||||||
|
LBB1_3:
|
||||||
|
WORD $0xbc0f; BYTE $0xc3 // bsf eax, ebx
|
||||||
|
JMP LBB1_12
|
||||||
|
|
||||||
|
LBB1_8:
|
||||||
|
WORD $0xbc0f; BYTE $0xf3 // bsf esi, ebx
|
||||||
|
WORD $0xeec1; BYTE $0x03 // shr esi, 3
|
||||||
|
|
||||||
|
LBB1_11:
|
||||||
|
WORD $0xf089 // mov eax, esi
|
||||||
|
LONG $0x240c8b48 // mov rcx, qword [rsp]
|
||||||
|
WORD $0x0148; BYTE $0xc1 // add rcx, rax
|
||||||
|
WORD $0x8948; BYTE $0xc8 // mov rax, rcx
|
||||||
|
|
||||||
|
LBB1_12:
|
||||||
|
SUBQ $8, SP
|
||||||
|
MOVQ AX, ret+16(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
DATA LCDATA2<>+0x000(SB)/8, $0xdfdfdfdfdfdfdfe0
|
||||||
|
DATA LCDATA2<>+0x008(SB)/8, $0x2222222222222222
|
||||||
|
DATA LCDATA2<>+0x010(SB)/8, $0xfefefefefefefeff
|
||||||
|
DATA LCDATA2<>+0x018(SB)/8, $0x5c5c5c5c5c5c5c5c
|
||||||
|
DATA LCDATA2<>+0x020(SB)/8, $0x3c3c3c3c3c3c3c3c
|
||||||
|
DATA LCDATA2<>+0x028(SB)/8, $0x3e3e3e3e3e3e3e3e
|
||||||
|
DATA LCDATA2<>+0x030(SB)/8, $0x2626262626262626
|
||||||
|
DATA LCDATA2<>+0x038(SB)/8, $0x0000000000000000
|
||||||
|
DATA LCDATA2<>+0x040(SB)/8, $0x8080808080808080
|
||||||
|
DATA LCDATA2<>+0x048(SB)/8, $0x8080808080808080
|
||||||
|
DATA LCDATA2<>+0x050(SB)/8, $0x8080808080808080
|
||||||
|
DATA LCDATA2<>+0x058(SB)/8, $0x8080808080808080
|
||||||
|
DATA LCDATA2<>+0x060(SB)/8, $0xdfdfdfdfdfdfdfe0
|
||||||
|
DATA LCDATA2<>+0x068(SB)/8, $0xdfdfdfdfdfdfdfe0
|
||||||
|
DATA LCDATA2<>+0x070(SB)/8, $0x2222222222222222
|
||||||
|
DATA LCDATA2<>+0x078(SB)/8, $0x2222222222222222
|
||||||
|
DATA LCDATA2<>+0x080(SB)/8, $0xfefefefefefefeff
|
||||||
|
DATA LCDATA2<>+0x088(SB)/8, $0xfefefefefefefeff
|
||||||
|
DATA LCDATA2<>+0x090(SB)/8, $0x5c5c5c5c5c5c5c5c
|
||||||
|
DATA LCDATA2<>+0x098(SB)/8, $0x5c5c5c5c5c5c5c5c
|
||||||
|
DATA LCDATA2<>+0x0a0(SB)/8, $0x3c3c3c3c3c3c3c3c
|
||||||
|
DATA LCDATA2<>+0x0a8(SB)/8, $0x3c3c3c3c3c3c3c3c
|
||||||
|
DATA LCDATA2<>+0x0b0(SB)/8, $0x3e3e3e3e3e3e3e3e
|
||||||
|
DATA LCDATA2<>+0x0b8(SB)/8, $0x3e3e3e3e3e3e3e3e
|
||||||
|
DATA LCDATA2<>+0x0c0(SB)/8, $0x2626262626262626
|
||||||
|
DATA LCDATA2<>+0x0c8(SB)/8, $0x2626262626262626
|
||||||
|
DATA LCDATA2<>+0x0d0(SB)/8, $0x8080808080808080
|
||||||
|
DATA LCDATA2<>+0x0d8(SB)/8, $0x8080808080808080
|
||||||
|
GLOBL LCDATA2<>(SB), 8, $224
|
||||||
|
|
||||||
|
TEXT ·_findHTMLEscapeIndex256(SB), $16-24
|
||||||
|
|
||||||
|
MOVQ buf+0(FP), DI
|
||||||
|
MOVQ len+8(FP), SI
|
||||||
|
ADDQ $8, SP
|
||||||
|
LEAQ LCDATA2<>(SB), BP
|
||||||
|
|
||||||
|
WORD $0xf089 // mov eax, esi
|
||||||
|
WORD $0xf8c1; BYTE $0x1f // sar eax, 31
|
||||||
|
WORD $0xe8c1; BYTE $0x1b // shr eax, 27
|
||||||
|
WORD $0xf001 // add eax, esi
|
||||||
|
WORD $0xf8c1; BYTE $0x05 // sar eax, 5
|
||||||
|
WORD $0x4e8d; BYTE $0x1f // lea ecx, [rsi + 31]
|
||||||
|
WORD $0xf983; BYTE $0x3f // cmp ecx, 63
|
||||||
|
JB LBB2_4
|
||||||
|
WORD $0x6348; BYTE $0xc8 // movsxd rcx, eax
|
||||||
|
LONG $0x597de2c4; WORD $0x0045 // vpbroadcastq ymm0, qword 0[rbp] /* [rip + .LCPI2_0] */
|
||||||
|
LONG $0x597de2c4; WORD $0x084d // vpbroadcastq ymm1, qword 8[rbp] /* [rip + .LCPI2_1] */
|
||||||
|
LONG $0x597de2c4; WORD $0x1055 // vpbroadcastq ymm2, qword 16[rbp] /* [rip + .LCPI2_2] */
|
||||||
|
LONG $0x597de2c4; WORD $0x185d // vpbroadcastq ymm3, qword 24[rbp] /* [rip + .LCPI2_3] */
|
||||||
|
LONG $0x597de2c4; WORD $0x2065 // vpbroadcastq ymm4, qword 32[rbp] /* [rip + .LCPI2_4] */
|
||||||
|
LONG $0x597de2c4; WORD $0x286d // vpbroadcastq ymm5, qword 40[rbp] /* [rip + .LCPI2_5] */
|
||||||
|
WORD $0xd231 // xor edx, edx
|
||||||
|
LONG $0x597de2c4; WORD $0x3075 // vpbroadcastq ymm6, qword 48[rbp] /* [rip + .LCPI2_6] */
|
||||||
|
LONG $0x7d6ffdc5; BYTE $0x40 // vmovdqa ymm7, yword 64[rbp] /* [rip + .LCPI2_7] */
|
||||||
|
|
||||||
|
LBB2_2:
|
||||||
|
LONG $0x076f7ec5 // vmovdqu ymm8, yword [rdi]
|
||||||
|
LONG $0xc8d43dc5 // vpaddq ymm9, ymm8, ymm0
|
||||||
|
LONG $0xd1ef3dc5 // vpxor ymm10, ymm8, ymm1
|
||||||
|
LONG $0xd2d42dc5 // vpaddq ymm10, ymm10, ymm2
|
||||||
|
LONG $0xdbef3dc5 // vpxor ymm11, ymm8, ymm3
|
||||||
|
LONG $0xdad425c5 // vpaddq ymm11, ymm11, ymm2
|
||||||
|
LONG $0xe4ef3dc5 // vpxor ymm12, ymm8, ymm4
|
||||||
|
LONG $0xe2d41dc5 // vpaddq ymm12, ymm12, ymm2
|
||||||
|
LONG $0xeb2541c4; BYTE $0xdc // vpor ymm11, ymm11, ymm12
|
||||||
|
LONG $0xe5ef3dc5 // vpxor ymm12, ymm8, ymm5
|
||||||
|
LONG $0xe2d41dc5 // vpaddq ymm12, ymm12, ymm2
|
||||||
|
LONG $0xeeef3dc5 // vpxor ymm13, ymm8, ymm6
|
||||||
|
LONG $0xead415c5 // vpaddq ymm13, ymm13, ymm2
|
||||||
|
LONG $0xeb1d41c4; BYTE $0xe5 // vpor ymm12, ymm12, ymm13
|
||||||
|
LONG $0xeb3541c4; BYTE $0xc0 // vpor ymm8, ymm9, ymm8
|
||||||
|
LONG $0xeb3d41c4; BYTE $0xc2 // vpor ymm8, ymm8, ymm10
|
||||||
|
LONG $0xeb3d41c4; BYTE $0xc3 // vpor ymm8, ymm8, ymm11
|
||||||
|
LONG $0xeb3d41c4; BYTE $0xc4 // vpor ymm8, ymm8, ymm12
|
||||||
|
LONG $0xc7db3dc5 // vpand ymm8, ymm8, ymm7
|
||||||
|
LONG $0xd77dc1c4; BYTE $0xd8 // vpmovmskb ebx, ymm8
|
||||||
|
WORD $0xdb85 // test ebx, ebx
|
||||||
|
JNE LBB2_18
|
||||||
|
LONG $0x20c78348 // add rdi, 32
|
||||||
|
LONG $0x01c28348 // add rdx, 1
|
||||||
|
WORD $0x3948; BYTE $0xca // cmp rdx, rcx
|
||||||
|
JB LBB2_2
|
||||||
|
|
||||||
|
LBB2_4:
|
||||||
|
WORD $0xe0c1; BYTE $0x05 // shl eax, 5
|
||||||
|
WORD $0xc629 // sub esi, eax
|
||||||
|
WORD $0xfe83; BYTE $0x10 // cmp esi, 16
|
||||||
|
JL LBB2_13
|
||||||
|
WORD $0x6348; BYTE $0xd8 // movsxd rbx, eax
|
||||||
|
WORD $0xf089 // mov eax, esi
|
||||||
|
WORD $0xe8c1; BYTE $0x04 // shr eax, 4
|
||||||
|
WORD $0xc931 // xor ecx, ecx
|
||||||
|
LONG $0x456f79c5; BYTE $0x60 // vmovdqa xmm8, oword 96[rbp] /* [rip + .LCPI2_8] */
|
||||||
|
LONG $0x4d6f79c5; BYTE $0x70 // vmovdqa xmm9, oword 112[rbp] /* [rip + .LCPI2_9] */
|
||||||
|
QUAD $0x00000080956ff9c5 // vmovdqa xmm2, oword 128[rbp] /* [rip + .LCPI2_10] */
|
||||||
|
QUAD $0x00000090956f79c5 // vmovdqa xmm10, oword 144[rbp] /* [rip + .LCPI2_11] */
|
||||||
|
QUAD $0x000000a09d6f79c5 // vmovdqa xmm11, oword 160[rbp] /* [rip + .LCPI2_12] */
|
||||||
|
QUAD $0x000000b0a56f79c5 // vmovdqa xmm12, oword 176[rbp] /* [rip + .LCPI2_13] */
|
||||||
|
QUAD $0x000000c0ad6f79c5 // vmovdqa xmm13, oword 192[rbp] /* [rip + .LCPI2_14] */
|
||||||
|
QUAD $0x000000d0bd6ff9c5 // vmovdqa xmm7, oword 208[rbp] /* [rip + .LCPI2_15] */
|
||||||
|
|
||||||
|
LBB2_6:
|
||||||
|
LONG $0x076ffac5 // vmovdqu xmm0, oword [rdi]
|
||||||
|
LONG $0xd479c1c4; BYTE $0xc8 // vpaddq xmm1, xmm0, xmm8
|
||||||
|
LONG $0xef79c1c4; BYTE $0xd9 // vpxor xmm3, xmm0, xmm9
|
||||||
|
LONG $0xdad4e1c5 // vpaddq xmm3, xmm3, xmm2
|
||||||
|
LONG $0xef79c1c4; BYTE $0xe2 // vpxor xmm4, xmm0, xmm10
|
||||||
|
LONG $0xe2d4d9c5 // vpaddq xmm4, xmm4, xmm2
|
||||||
|
LONG $0xef79c1c4; BYTE $0xeb // vpxor xmm5, xmm0, xmm11
|
||||||
|
LONG $0xead4d1c5 // vpaddq xmm5, xmm5, xmm2
|
||||||
|
LONG $0xe5ebd9c5 // vpor xmm4, xmm4, xmm5
|
||||||
|
LONG $0xef79c1c4; BYTE $0xec // vpxor xmm5, xmm0, xmm12
|
||||||
|
LONG $0xead4d1c5 // vpaddq xmm5, xmm5, xmm2
|
||||||
|
LONG $0xef79c1c4; BYTE $0xf5 // vpxor xmm6, xmm0, xmm13
|
||||||
|
LONG $0xf2d4c9c5 // vpaddq xmm6, xmm6, xmm2
|
||||||
|
LONG $0xeeebd1c5 // vpor xmm5, xmm5, xmm6
|
||||||
|
LONG $0xc0ebf1c5 // vpor xmm0, xmm1, xmm0
|
||||||
|
LONG $0xc3ebf9c5 // vpor xmm0, xmm0, xmm3
|
||||||
|
LONG $0xc4ebf9c5 // vpor xmm0, xmm0, xmm4
|
||||||
|
LONG $0xc5ebf9c5 // vpor xmm0, xmm0, xmm5
|
||||||
|
LONG $0xc7dbf9c5 // vpand xmm0, xmm0, xmm7
|
||||||
|
LONG $0xd0d7f9c5 // vpmovmskb edx, xmm0
|
||||||
|
WORD $0xd285 // test edx, edx
|
||||||
|
JNE LBB2_19
|
||||||
|
LONG $0x10c78348 // add rdi, 16
|
||||||
|
LONG $0x01c18348 // add rcx, 1
|
||||||
|
WORD $0x3948; BYTE $0xc1 // cmp rcx, rax
|
||||||
|
JB LBB2_6
|
||||||
|
WORD $0xf089 // mov eax, esi
|
||||||
|
WORD $0xe083; BYTE $0xf0 // and eax, -16
|
||||||
|
WORD $0xc629 // sub esi, eax
|
||||||
|
WORD $0x9848 // cdqe
|
||||||
|
WORD $0xfe83; BYTE $0x08 // cmp esi, 8
|
||||||
|
JL LBB2_24
|
||||||
|
LONG $0x241c8948 // mov qword [rsp], rbx
|
||||||
|
QUAD $0xfefefefefeffbe49; WORD $0xfefe // mov r14, -72340172838076673
|
||||||
|
QUAD $0x262626262626bc49; WORD $0x2626 // mov r12, 2748926567846913574
|
||||||
|
QUAD $0x222222222222bd49; WORD $0x2222 // mov r13, 2459565876494606882
|
||||||
|
WORD $0x8941; BYTE $0xf3 // mov r11d, esi
|
||||||
|
LONG $0x03ebc141 // shr r11d, 3
|
||||||
|
WORD $0x3145; BYTE $0xff // xor r15d, r15d
|
||||||
|
|
||||||
|
LBB2_10:
|
||||||
|
LONG $0xff048b4e // mov r8, qword [rdi + 8*r15]
|
||||||
|
QUAD $0xdfdfdfdfdfe0b948; WORD $0xdfdf // mov rcx, -2314885530818453536
|
||||||
|
LONG $0x080c8d4d // lea r9, [r8 + rcx]
|
||||||
|
WORD $0x094d; BYTE $0xc1 // or r9, r8
|
||||||
|
WORD $0x894d; BYTE $0xc2 // mov r10, r8
|
||||||
|
WORD $0x314d; BYTE $0xea // xor r10, r13
|
||||||
|
WORD $0x014d; BYTE $0xf2 // add r10, r14
|
||||||
|
WORD $0x094d; BYTE $0xca // or r10, r9
|
||||||
|
WORD $0x894c; BYTE $0xc1 // mov rcx, r8
|
||||||
|
QUAD $0x5c5c5c5c5c5cba48; WORD $0x5c5c // mov rdx, 6655295901103053916
|
||||||
|
WORD $0x3148; BYTE $0xd1 // xor rcx, rdx
|
||||||
|
WORD $0x014c; BYTE $0xf1 // add rcx, r14
|
||||||
|
WORD $0x894c; BYTE $0xc2 // mov rdx, r8
|
||||||
|
QUAD $0x3c3c3c3c3c3cbb48; WORD $0x3c3c // mov rbx, 4340410370284600380
|
||||||
|
WORD $0x3148; BYTE $0xda // xor rdx, rbx
|
||||||
|
WORD $0x014c; BYTE $0xf2 // add rdx, r14
|
||||||
|
WORD $0x0948; BYTE $0xca // or rdx, rcx
|
||||||
|
WORD $0x094c; BYTE $0xd2 // or rdx, r10
|
||||||
|
WORD $0x894c; BYTE $0xc1 // mov rcx, r8
|
||||||
|
QUAD $0x3e3e3e3e3e3ebb48; WORD $0x3e3e // mov rbx, 4485090715960753726
|
||||||
|
WORD $0x3148; BYTE $0xd9 // xor rcx, rbx
|
||||||
|
WORD $0x014c; BYTE $0xf1 // add rcx, r14
|
||||||
|
WORD $0x314d; BYTE $0xe0 // xor r8, r12
|
||||||
|
WORD $0x014d; BYTE $0xf0 // add r8, r14
|
||||||
|
WORD $0x0949; BYTE $0xc8 // or r8, rcx
|
||||||
|
WORD $0x0949; BYTE $0xd0 // or r8, rdx
|
||||||
|
QUAD $0x808080808080b948; WORD $0x8080 // mov rcx, -9187201950435737472
|
||||||
|
WORD $0x2149; BYTE $0xc8 // and r8, rcx
|
||||||
|
JNE LBB2_22
|
||||||
|
LONG $0x01c78349 // add r15, 1
|
||||||
|
WORD $0x394d; BYTE $0xdf // cmp r15, r11
|
||||||
|
JB LBB2_10
|
||||||
|
WORD $0xe683; BYTE $0xf8 // and esi, -8
|
||||||
|
JMP LBB2_23
|
||||||
|
|
||||||
|
LBB2_13:
|
||||||
|
WORD $0x9848 // cdqe
|
||||||
|
WORD $0xfe83; BYTE $0x08 // cmp esi, 8
|
||||||
|
JL LBB2_25
|
||||||
|
LONG $0x24048948 // mov qword [rsp], rax
|
||||||
|
QUAD $0xfefefefefeffbd49; WORD $0xfefe // mov r13, -72340172838076673
|
||||||
|
QUAD $0x808080808080b949; WORD $0x8080 // mov r9, -9187201950435737472
|
||||||
|
QUAD $0x5c5c5c5c5c5cba49; WORD $0x5c5c // mov r10, 6655295901103053916
|
||||||
|
QUAD $0x3e3e3e3e3e3ebb49; WORD $0x3e3e // mov r11, 4485090715960753726
|
||||||
|
QUAD $0x3c3c3c3c3c3cbe49; WORD $0x3c3c // mov r14, 4340410370284600380
|
||||||
|
QUAD $0x262626262626bf49; WORD $0x2626 // mov r15, 2748926567846913574
|
||||||
|
QUAD $0x222222222222bc49; WORD $0x2222 // mov r12, 2459565876494606882
|
||||||
|
WORD $0xeec1; BYTE $0x03 // shr esi, 3
|
||||||
|
WORD $0xe683; BYTE $0x1f // and esi, 31
|
||||||
|
WORD $0xdb31 // xor ebx, ebx
|
||||||
|
|
||||||
|
LBB2_15:
|
||||||
|
LONG $0xdf148b48 // mov rdx, qword [rdi + 8*rbx]
|
||||||
|
QUAD $0xdfdfdfdfdfe0b848; WORD $0xdfdf // mov rax, -2314885530818453536
|
||||||
|
LONG $0x020c8d48 // lea rcx, [rdx + rax]
|
||||||
|
WORD $0x0948; BYTE $0xd1 // or rcx, rdx
|
||||||
|
WORD $0x8949; BYTE $0xd0 // mov r8, rdx
|
||||||
|
WORD $0x314d; BYTE $0xe0 // xor r8, r12
|
||||||
|
WORD $0x014d; BYTE $0xe8 // add r8, r13
|
||||||
|
WORD $0x0949; BYTE $0xc8 // or r8, rcx
|
||||||
|
WORD $0x8948; BYTE $0xd1 // mov rcx, rdx
|
||||||
|
WORD $0x314c; BYTE $0xd1 // xor rcx, r10
|
||||||
|
WORD $0x014c; BYTE $0xe9 // add rcx, r13
|
||||||
|
WORD $0x8948; BYTE $0xd0 // mov rax, rdx
|
||||||
|
WORD $0x314c; BYTE $0xf0 // xor rax, r14
|
||||||
|
WORD $0x014c; BYTE $0xe8 // add rax, r13
|
||||||
|
WORD $0x0948; BYTE $0xc8 // or rax, rcx
|
||||||
|
WORD $0x094c; BYTE $0xc0 // or rax, r8
|
||||||
|
WORD $0x8948; BYTE $0xd1 // mov rcx, rdx
|
||||||
|
WORD $0x314c; BYTE $0xd9 // xor rcx, r11
|
||||||
|
WORD $0x014c; BYTE $0xe9 // add rcx, r13
|
||||||
|
WORD $0x314c; BYTE $0xfa // xor rdx, r15
|
||||||
|
WORD $0x014c; BYTE $0xea // add rdx, r13
|
||||||
|
WORD $0x0948; BYTE $0xca // or rdx, rcx
|
||||||
|
WORD $0x0948; BYTE $0xc2 // or rdx, rax
|
||||||
|
WORD $0x214c; BYTE $0xca // and rdx, r9
|
||||||
|
JNE LBB2_20
|
||||||
|
LONG $0x01c38348 // add rbx, 1
|
||||||
|
WORD $0x3948; BYTE $0xf3 // cmp rbx, rsi
|
||||||
|
JB LBB2_15
|
||||||
|
WORD $0xe6c1; BYTE $0x03 // shl esi, 3
|
||||||
|
JMP LBB2_21
|
||||||
|
|
||||||
|
LBB2_18:
|
||||||
|
WORD $0xbc0f; BYTE $0xc3 // bsf eax, ebx
|
||||||
|
JMP LBB2_25
|
||||||
|
|
||||||
|
LBB2_19:
|
||||||
|
WORD $0xbc0f; BYTE $0xc2 // bsf eax, edx
|
||||||
|
JMP LBB2_24
|
||||||
|
|
||||||
|
LBB2_20:
|
||||||
|
WORD $0xbc0f; BYTE $0xf2 // bsf esi, edx
|
||||||
|
WORD $0xeec1; BYTE $0x03 // shr esi, 3
|
||||||
|
|
||||||
|
LBB2_21:
|
||||||
|
WORD $0xf089 // mov eax, esi
|
||||||
|
LONG $0x240c8b48 // mov rcx, qword [rsp]
|
||||||
|
WORD $0x0148; BYTE $0xc1 // add rcx, rax
|
||||||
|
WORD $0x8948; BYTE $0xc8 // mov rax, rcx
|
||||||
|
JMP LBB2_25
|
||||||
|
|
||||||
|
LBB2_22:
|
||||||
|
LONG $0xf0bc0f41 // bsf esi, r8d
|
||||||
|
WORD $0xeec1; BYTE $0x03 // shr esi, 3
|
||||||
|
|
||||||
|
LBB2_23:
|
||||||
|
WORD $0xf189 // mov ecx, esi
|
||||||
|
WORD $0x0148; BYTE $0xc8 // add rax, rcx
|
||||||
|
LONG $0x241c8b48 // mov rbx, qword [rsp]
|
||||||
|
|
||||||
|
LBB2_24:
|
||||||
|
WORD $0x0148; BYTE $0xd8 // add rax, rbx
|
||||||
|
|
||||||
|
LBB2_25:
|
||||||
|
SUBQ $8, SP
|
||||||
|
VZEROUPPER
|
||||||
|
MOVQ AX, ret+16(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·_findEscapeIndex64(SB), $0-24
|
||||||
|
|
||||||
|
MOVQ buf+0(FP), DI
|
||||||
|
MOVQ len+8(FP), SI
|
||||||
|
|
||||||
|
WORD $0xf089 // mov eax, esi
|
||||||
|
WORD $0xf8c1; BYTE $0x1f // sar eax, 31
|
||||||
|
WORD $0xe8c1; BYTE $0x1d // shr eax, 29
|
||||||
|
WORD $0xf001 // add eax, esi
|
||||||
|
WORD $0xf8c1; BYTE $0x03 // sar eax, 3
|
||||||
|
WORD $0x9848 // cdqe
|
||||||
|
WORD $0xc683; BYTE $0x07 // add esi, 7
|
||||||
|
WORD $0xfe83; BYTE $0x0f // cmp esi, 15
|
||||||
|
JB LBB3_5
|
||||||
|
QUAD $0xfefefefefeffbe49; WORD $0xfefe // mov r14, -72340172838076673
|
||||||
|
WORD $0xd231 // xor edx, edx
|
||||||
|
QUAD $0xdfdfdfdfdfe0b849; WORD $0xdfdf // mov r8, -2314885530818453536
|
||||||
|
QUAD $0x222222222222b949; WORD $0x2222 // mov r9, 2459565876494606882
|
||||||
|
QUAD $0x5c5c5c5c5c5cba49; WORD $0x5c5c // mov r10, 6655295901103053916
|
||||||
|
QUAD $0x808080808080bb49; WORD $0x8080 // mov r11, -9187201950435737472
|
||||||
|
|
||||||
|
LBB3_2:
|
||||||
|
LONG $0xd7348b48 // mov rsi, qword [rdi + 8*rdx]
|
||||||
|
LONG $0x061c8d4a // lea rbx, [rsi + r8]
|
||||||
|
WORD $0x0948; BYTE $0xf3 // or rbx, rsi
|
||||||
|
WORD $0x8948; BYTE $0xf1 // mov rcx, rsi
|
||||||
|
WORD $0x314c; BYTE $0xc9 // xor rcx, r9
|
||||||
|
WORD $0x014c; BYTE $0xf1 // add rcx, r14
|
||||||
|
WORD $0x0948; BYTE $0xd9 // or rcx, rbx
|
||||||
|
WORD $0x314c; BYTE $0xd6 // xor rsi, r10
|
||||||
|
WORD $0x014c; BYTE $0xf6 // add rsi, r14
|
||||||
|
WORD $0x0948; BYTE $0xce // or rsi, rcx
|
||||||
|
WORD $0x214c; BYTE $0xde // and rsi, r11
|
||||||
|
JNE LBB3_3
|
||||||
|
LONG $0x01c28348 // add rdx, 1
|
||||||
|
WORD $0x3948; BYTE $0xc2 // cmp rdx, rax
|
||||||
|
JB LBB3_2
|
||||||
|
|
||||||
|
LBB3_5:
|
||||||
|
LONG $0x03e0c148 // shl rax, 3
|
||||||
|
JMP LBB3_6
|
||||||
|
|
||||||
|
LBB3_3:
|
||||||
|
WORD $0xbc0f; BYTE $0xc6 // bsf eax, esi
|
||||||
|
WORD $0xe8c1; BYTE $0x03 // shr eax, 3
|
||||||
|
|
||||||
|
LBB3_6:
|
||||||
|
MOVQ AX, ret+16(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
DATA LCDATA3<>+0x000(SB)/8, $0xdfdfdfdfdfdfdfe0
|
||||||
|
DATA LCDATA3<>+0x008(SB)/8, $0xdfdfdfdfdfdfdfe0
|
||||||
|
DATA LCDATA3<>+0x010(SB)/8, $0x2222222222222222
|
||||||
|
DATA LCDATA3<>+0x018(SB)/8, $0x2222222222222222
|
||||||
|
DATA LCDATA3<>+0x020(SB)/8, $0xfefefefefefefeff
|
||||||
|
DATA LCDATA3<>+0x028(SB)/8, $0xfefefefefefefeff
|
||||||
|
DATA LCDATA3<>+0x030(SB)/8, $0x5c5c5c5c5c5c5c5c
|
||||||
|
DATA LCDATA3<>+0x038(SB)/8, $0x5c5c5c5c5c5c5c5c
|
||||||
|
DATA LCDATA3<>+0x040(SB)/8, $0x8080808080808080
|
||||||
|
DATA LCDATA3<>+0x048(SB)/8, $0x8080808080808080
|
||||||
|
GLOBL LCDATA3<>(SB), 8, $80
|
||||||
|
|
||||||
|
TEXT ·_findEscapeIndex128(SB), $0-24
|
||||||
|
|
||||||
|
MOVQ buf+0(FP), DI
|
||||||
|
MOVQ len+8(FP), SI
|
||||||
|
LEAQ LCDATA3<>(SB), BP
|
||||||
|
|
||||||
|
WORD $0xf089 // mov eax, esi
|
||||||
|
WORD $0xf8c1; BYTE $0x1f // sar eax, 31
|
||||||
|
WORD $0xe8c1; BYTE $0x1c // shr eax, 28
|
||||||
|
WORD $0xf001 // add eax, esi
|
||||||
|
WORD $0xf8c1; BYTE $0x04 // sar eax, 4
|
||||||
|
WORD $0x4e8d; BYTE $0x0f // lea ecx, [rsi + 15]
|
||||||
|
WORD $0xf983; BYTE $0x1f // cmp ecx, 31
|
||||||
|
JB LBB4_5
|
||||||
|
WORD $0x6348; BYTE $0xc8 // movsxd rcx, eax
|
||||||
|
WORD $0xd231 // xor edx, edx
|
||||||
|
LONG $0x456f79c5; BYTE $0x00 // vmovdqa xmm8, oword 0[rbp] /* [rip + .LCPI4_0] */
|
||||||
|
LONG $0x4d6ff9c5; BYTE $0x10 // vmovdqa xmm1, oword 16[rbp] /* [rip + .LCPI4_1] */
|
||||||
|
LONG $0x556ff9c5; BYTE $0x20 // vmovdqa xmm2, oword 32[rbp] /* [rip + .LCPI4_2] */
|
||||||
|
LONG $0x5d6ff9c5; BYTE $0x30 // vmovdqa xmm3, oword 48[rbp] /* [rip + .LCPI4_3] */
|
||||||
|
LONG $0x656ff9c5; BYTE $0x40 // vmovdqa xmm4, oword 64[rbp] /* [rip + .LCPI4_4] */
|
||||||
|
|
||||||
|
LBB4_2:
|
||||||
|
LONG $0x2f6ffac5 // vmovdqu xmm5, oword [rdi]
|
||||||
|
LONG $0xd451c1c4; BYTE $0xf0 // vpaddq xmm6, xmm5, xmm8
|
||||||
|
LONG $0xf9efd1c5 // vpxor xmm7, xmm5, xmm1
|
||||||
|
LONG $0xfad4c1c5 // vpaddq xmm7, xmm7, xmm2
|
||||||
|
LONG $0xc3efd1c5 // vpxor xmm0, xmm5, xmm3
|
||||||
|
LONG $0xc2d4f9c5 // vpaddq xmm0, xmm0, xmm2
|
||||||
|
LONG $0xedebc9c5 // vpor xmm5, xmm6, xmm5
|
||||||
|
LONG $0xefebd1c5 // vpor xmm5, xmm5, xmm7
|
||||||
|
LONG $0xc0ebd1c5 // vpor xmm0, xmm5, xmm0
|
||||||
|
LONG $0xc4dbf9c5 // vpand xmm0, xmm0, xmm4
|
||||||
|
LONG $0xd8d7f9c5 // vpmovmskb ebx, xmm0
|
||||||
|
WORD $0xdb85 // test ebx, ebx
|
||||||
|
JNE LBB4_3
|
||||||
|
LONG $0x10c78348 // add rdi, 16
|
||||||
|
LONG $0x01c28348 // add rdx, 1
|
||||||
|
WORD $0x3948; BYTE $0xca // cmp rdx, rcx
|
||||||
|
JB LBB4_2
|
||||||
|
|
||||||
|
LBB4_5:
|
||||||
|
WORD $0xe0c1; BYTE $0x04 // shl eax, 4
|
||||||
|
WORD $0xc629 // sub esi, eax
|
||||||
|
WORD $0x9848 // cdqe
|
||||||
|
WORD $0xfe83; BYTE $0x08 // cmp esi, 8
|
||||||
|
JL LBB4_12
|
||||||
|
QUAD $0xfefefefefeffb849; WORD $0xfefe // mov r8, -72340172838076673
|
||||||
|
WORD $0x8941; BYTE $0xf7 // mov r15d, esi
|
||||||
|
LONG $0x03efc141 // shr r15d, 3
|
||||||
|
WORD $0xc931 // xor ecx, ecx
|
||||||
|
QUAD $0xdfdfdfdfdfe0b949; WORD $0xdfdf // mov r9, -2314885530818453536
|
||||||
|
QUAD $0x222222222222ba49; WORD $0x2222 // mov r10, 2459565876494606882
|
||||||
|
QUAD $0x5c5c5c5c5c5cbb49; WORD $0x5c5c // mov r11, 6655295901103053916
|
||||||
|
QUAD $0x808080808080be49; WORD $0x8080 // mov r14, -9187201950435737472
|
||||||
|
|
||||||
|
LBB4_7:
|
||||||
|
LONG $0xcf1c8b48 // mov rbx, qword [rdi + 8*rcx]
|
||||||
|
LONG $0x0b248d4e // lea r12, [rbx + r9]
|
||||||
|
WORD $0x0949; BYTE $0xdc // or r12, rbx
|
||||||
|
WORD $0x8948; BYTE $0xda // mov rdx, rbx
|
||||||
|
WORD $0x314c; BYTE $0xd2 // xor rdx, r10
|
||||||
|
WORD $0x014c; BYTE $0xc2 // add rdx, r8
|
||||||
|
WORD $0x094c; BYTE $0xe2 // or rdx, r12
|
||||||
|
WORD $0x314c; BYTE $0xdb // xor rbx, r11
|
||||||
|
WORD $0x014c; BYTE $0xc3 // add rbx, r8
|
||||||
|
WORD $0x0948; BYTE $0xd3 // or rbx, rdx
|
||||||
|
WORD $0x214c; BYTE $0xf3 // and rbx, r14
|
||||||
|
JNE LBB4_8
|
||||||
|
LONG $0x01c18348 // add rcx, 1
|
||||||
|
WORD $0x394c; BYTE $0xf9 // cmp rcx, r15
|
||||||
|
JB LBB4_7
|
||||||
|
WORD $0xe683; BYTE $0xf8 // and esi, -8
|
||||||
|
JMP LBB4_11
|
||||||
|
|
||||||
|
LBB4_3:
|
||||||
|
WORD $0xbc0f; BYTE $0xc3 // bsf eax, ebx
|
||||||
|
JMP LBB4_12
|
||||||
|
|
||||||
|
LBB4_8:
|
||||||
|
WORD $0xbc0f; BYTE $0xf3 // bsf esi, ebx
|
||||||
|
WORD $0xeec1; BYTE $0x03 // shr esi, 3
|
||||||
|
|
||||||
|
LBB4_11:
|
||||||
|
WORD $0xf189 // mov ecx, esi
|
||||||
|
WORD $0x0148; BYTE $0xc8 // add rax, rcx
|
||||||
|
|
||||||
|
LBB4_12:
|
||||||
|
MOVQ AX, ret+16(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
DATA LCDATA4<>+0x000(SB)/8, $0xdfdfdfdfdfdfdfe0
|
||||||
|
DATA LCDATA4<>+0x008(SB)/8, $0x2222222222222222
|
||||||
|
DATA LCDATA4<>+0x010(SB)/8, $0xfefefefefefefeff
|
||||||
|
DATA LCDATA4<>+0x018(SB)/8, $0x5c5c5c5c5c5c5c5c
|
||||||
|
DATA LCDATA4<>+0x020(SB)/8, $0x8080808080808080
|
||||||
|
DATA LCDATA4<>+0x028(SB)/8, $0x8080808080808080
|
||||||
|
DATA LCDATA4<>+0x030(SB)/8, $0x8080808080808080
|
||||||
|
DATA LCDATA4<>+0x038(SB)/8, $0x8080808080808080
|
||||||
|
DATA LCDATA4<>+0x040(SB)/8, $0xdfdfdfdfdfdfdfe0
|
||||||
|
DATA LCDATA4<>+0x048(SB)/8, $0xdfdfdfdfdfdfdfe0
|
||||||
|
DATA LCDATA4<>+0x050(SB)/8, $0x2222222222222222
|
||||||
|
DATA LCDATA4<>+0x058(SB)/8, $0x2222222222222222
|
||||||
|
DATA LCDATA4<>+0x060(SB)/8, $0xfefefefefefefeff
|
||||||
|
DATA LCDATA4<>+0x068(SB)/8, $0xfefefefefefefeff
|
||||||
|
DATA LCDATA4<>+0x070(SB)/8, $0x5c5c5c5c5c5c5c5c
|
||||||
|
DATA LCDATA4<>+0x078(SB)/8, $0x5c5c5c5c5c5c5c5c
|
||||||
|
DATA LCDATA4<>+0x080(SB)/8, $0x8080808080808080
|
||||||
|
DATA LCDATA4<>+0x088(SB)/8, $0x8080808080808080
|
||||||
|
GLOBL LCDATA4<>(SB), 8, $144
|
||||||
|
|
||||||
|
TEXT ·_findEscapeIndex256(SB), $0-24
|
||||||
|
|
||||||
|
MOVQ buf+0(FP), DI
|
||||||
|
MOVQ len+8(FP), SI
|
||||||
|
LEAQ LCDATA4<>(SB), BP
|
||||||
|
|
||||||
|
WORD $0xf089 // mov eax, esi
|
||||||
|
WORD $0xf8c1; BYTE $0x1f // sar eax, 31
|
||||||
|
WORD $0xe8c1; BYTE $0x1b // shr eax, 27
|
||||||
|
WORD $0xf001 // add eax, esi
|
||||||
|
WORD $0xf8c1; BYTE $0x05 // sar eax, 5
|
||||||
|
WORD $0x4e8d; BYTE $0x1f // lea ecx, [rsi + 31]
|
||||||
|
WORD $0xf983; BYTE $0x3f // cmp ecx, 63
|
||||||
|
JB LBB5_4
|
||||||
|
WORD $0x6348; BYTE $0xc8 // movsxd rcx, eax
|
||||||
|
LONG $0x597de2c4; WORD $0x0045 // vpbroadcastq ymm0, qword 0[rbp] /* [rip + .LCPI5_0] */
|
||||||
|
LONG $0x597de2c4; WORD $0x084d // vpbroadcastq ymm1, qword 8[rbp] /* [rip + .LCPI5_1] */
|
||||||
|
LONG $0x597de2c4; WORD $0x1055 // vpbroadcastq ymm2, qword 16[rbp] /* [rip + .LCPI5_2] */
|
||||||
|
WORD $0xd231 // xor edx, edx
|
||||||
|
LONG $0x597de2c4; WORD $0x185d // vpbroadcastq ymm3, qword 24[rbp] /* [rip + .LCPI5_3] */
|
||||||
|
LONG $0x656ffdc5; BYTE $0x20 // vmovdqa ymm4, yword 32[rbp] /* [rip + .LCPI5_4] */
|
||||||
|
|
||||||
|
LBB5_2:
|
||||||
|
LONG $0x2f6ffec5 // vmovdqu ymm5, yword [rdi]
|
||||||
|
LONG $0xf0d4d5c5 // vpaddq ymm6, ymm5, ymm0
|
||||||
|
LONG $0xf9efd5c5 // vpxor ymm7, ymm5, ymm1
|
||||||
|
LONG $0xfad4c5c5 // vpaddq ymm7, ymm7, ymm2
|
||||||
|
LONG $0xc3ef55c5 // vpxor ymm8, ymm5, ymm3
|
||||||
|
LONG $0xc2d43dc5 // vpaddq ymm8, ymm8, ymm2
|
||||||
|
LONG $0xedebcdc5 // vpor ymm5, ymm6, ymm5
|
||||||
|
LONG $0xefebd5c5 // vpor ymm5, ymm5, ymm7
|
||||||
|
LONG $0xeb55c1c4; BYTE $0xe8 // vpor ymm5, ymm5, ymm8
|
||||||
|
LONG $0xecdbd5c5 // vpand ymm5, ymm5, ymm4
|
||||||
|
LONG $0xddd7fdc5 // vpmovmskb ebx, ymm5
|
||||||
|
WORD $0xdb85 // test ebx, ebx
|
||||||
|
JNE LBB5_18
|
||||||
|
LONG $0x20c78348 // add rdi, 32
|
||||||
|
LONG $0x01c28348 // add rdx, 1
|
||||||
|
WORD $0x3948; BYTE $0xca // cmp rdx, rcx
|
||||||
|
JB LBB5_2
|
||||||
|
|
||||||
|
LBB5_4:
|
||||||
|
WORD $0xe0c1; BYTE $0x05 // shl eax, 5
|
||||||
|
WORD $0xc629 // sub esi, eax
|
||||||
|
WORD $0xfe83; BYTE $0x10 // cmp esi, 16
|
||||||
|
JL LBB5_13
|
||||||
|
WORD $0x634c; BYTE $0xc0 // movsxd r8, eax
|
||||||
|
WORD $0xf089 // mov eax, esi
|
||||||
|
WORD $0xe8c1; BYTE $0x04 // shr eax, 4
|
||||||
|
WORD $0xc931 // xor ecx, ecx
|
||||||
|
LONG $0x456f79c5; BYTE $0x40 // vmovdqa xmm8, oword 64[rbp] /* [rip + .LCPI5_5] */
|
||||||
|
LONG $0x4d6ff9c5; BYTE $0x50 // vmovdqa xmm1, oword 80[rbp] /* [rip + .LCPI5_6] */
|
||||||
|
LONG $0x556ff9c5; BYTE $0x60 // vmovdqa xmm2, oword 96[rbp] /* [rip + .LCPI5_7] */
|
||||||
|
LONG $0x5d6ff9c5; BYTE $0x70 // vmovdqa xmm3, oword 112[rbp] /* [rip + .LCPI5_8] */
|
||||||
|
QUAD $0x00000080a56ff9c5 // vmovdqa xmm4, oword 128[rbp] /* [rip + .LCPI5_9] */
|
||||||
|
|
||||||
|
LBB5_6:
|
||||||
|
LONG $0x2f6ffac5 // vmovdqu xmm5, oword [rdi]
|
||||||
|
LONG $0xd451c1c4; BYTE $0xf0 // vpaddq xmm6, xmm5, xmm8
|
||||||
|
LONG $0xf9efd1c5 // vpxor xmm7, xmm5, xmm1
|
||||||
|
LONG $0xfad4c1c5 // vpaddq xmm7, xmm7, xmm2
|
||||||
|
LONG $0xc3efd1c5 // vpxor xmm0, xmm5, xmm3
|
||||||
|
LONG $0xc2d4f9c5 // vpaddq xmm0, xmm0, xmm2
|
||||||
|
LONG $0xedebc9c5 // vpor xmm5, xmm6, xmm5
|
||||||
|
LONG $0xefebd1c5 // vpor xmm5, xmm5, xmm7
|
||||||
|
LONG $0xc0ebd1c5 // vpor xmm0, xmm5, xmm0
|
||||||
|
LONG $0xc4dbf9c5 // vpand xmm0, xmm0, xmm4
|
||||||
|
LONG $0xd0d7f9c5 // vpmovmskb edx, xmm0
|
||||||
|
WORD $0xd285 // test edx, edx
|
||||||
|
JNE LBB5_19
|
||||||
|
LONG $0x10c78348 // add rdi, 16
|
||||||
|
LONG $0x01c18348 // add rcx, 1
|
||||||
|
WORD $0x3948; BYTE $0xc1 // cmp rcx, rax
|
||||||
|
JB LBB5_6
|
||||||
|
WORD $0xf089 // mov eax, esi
|
||||||
|
WORD $0xe083; BYTE $0xf0 // and eax, -16
|
||||||
|
WORD $0xc629 // sub esi, eax
|
||||||
|
WORD $0x9848 // cdqe
|
||||||
|
WORD $0xfe83; BYTE $0x08 // cmp esi, 8
|
||||||
|
JL LBB5_24
|
||||||
|
QUAD $0xfefefefefeffbf49; WORD $0xfefe // mov r15, -72340172838076673
|
||||||
|
QUAD $0xdfdfdfdfdfe0b949; WORD $0xdfdf // mov r9, -2314885530818453536
|
||||||
|
QUAD $0x808080808080ba49; WORD $0x8080 // mov r10, -9187201950435737472
|
||||||
|
QUAD $0x5c5c5c5c5c5cbb49; WORD $0x5c5c // mov r11, 6655295901103053916
|
||||||
|
QUAD $0x222222222222be49; WORD $0x2222 // mov r14, 2459565876494606882
|
||||||
|
WORD $0x8941; BYTE $0xf4 // mov r12d, esi
|
||||||
|
LONG $0x03ecc141 // shr r12d, 3
|
||||||
|
WORD $0xc931 // xor ecx, ecx
|
||||||
|
|
||||||
|
LBB5_10:
|
||||||
|
LONG $0xcf148b48 // mov rdx, qword [rdi + 8*rcx]
|
||||||
|
LONG $0x0a2c8d4e // lea r13, [rdx + r9]
|
||||||
|
WORD $0x0949; BYTE $0xd5 // or r13, rdx
|
||||||
|
WORD $0x8948; BYTE $0xd3 // mov rbx, rdx
|
||||||
|
WORD $0x314c; BYTE $0xf3 // xor rbx, r14
|
||||||
|
WORD $0x014c; BYTE $0xfb // add rbx, r15
|
||||||
|
WORD $0x094c; BYTE $0xeb // or rbx, r13
|
||||||
|
WORD $0x314c; BYTE $0xda // xor rdx, r11
|
||||||
|
WORD $0x014c; BYTE $0xfa // add rdx, r15
|
||||||
|
WORD $0x0948; BYTE $0xda // or rdx, rbx
|
||||||
|
WORD $0x214c; BYTE $0xd2 // and rdx, r10
|
||||||
|
JNE LBB5_22
|
||||||
|
LONG $0x01c18348 // add rcx, 1
|
||||||
|
WORD $0x394c; BYTE $0xe1 // cmp rcx, r12
|
||||||
|
JB LBB5_10
|
||||||
|
WORD $0xe683; BYTE $0xf8 // and esi, -8
|
||||||
|
JMP LBB5_23
|
||||||
|
|
||||||
|
LBB5_13:
|
||||||
|
WORD $0x9848 // cdqe
|
||||||
|
WORD $0xfe83; BYTE $0x08 // cmp esi, 8
|
||||||
|
JL LBB5_25
|
||||||
|
QUAD $0xfefefefefeffbe49; WORD $0xfefe // mov r14, -72340172838076673
|
||||||
|
QUAD $0xdfdfdfdfdfe0b849; WORD $0xdfdf // mov r8, -2314885530818453536
|
||||||
|
QUAD $0x808080808080b949; WORD $0x8080 // mov r9, -9187201950435737472
|
||||||
|
QUAD $0x5c5c5c5c5c5cba49; WORD $0x5c5c // mov r10, 6655295901103053916
|
||||||
|
QUAD $0x222222222222bb49; WORD $0x2222 // mov r11, 2459565876494606882
|
||||||
|
WORD $0xeec1; BYTE $0x03 // shr esi, 3
|
||||||
|
WORD $0xe683; BYTE $0x1f // and esi, 31
|
||||||
|
WORD $0xdb31 // xor ebx, ebx
|
||||||
|
|
||||||
|
LBB5_15:
|
||||||
|
LONG $0xdf148b48 // mov rdx, qword [rdi + 8*rbx]
|
||||||
|
LONG $0x023c8d4e // lea r15, [rdx + r8]
|
||||||
|
WORD $0x0949; BYTE $0xd7 // or r15, rdx
|
||||||
|
WORD $0x8948; BYTE $0xd1 // mov rcx, rdx
|
||||||
|
WORD $0x314c; BYTE $0xd9 // xor rcx, r11
|
||||||
|
WORD $0x014c; BYTE $0xf1 // add rcx, r14
|
||||||
|
WORD $0x094c; BYTE $0xf9 // or rcx, r15
|
||||||
|
WORD $0x314c; BYTE $0xd2 // xor rdx, r10
|
||||||
|
WORD $0x014c; BYTE $0xf2 // add rdx, r14
|
||||||
|
WORD $0x0948; BYTE $0xca // or rdx, rcx
|
||||||
|
WORD $0x214c; BYTE $0xca // and rdx, r9
|
||||||
|
JNE LBB5_20
|
||||||
|
LONG $0x01c38348 // add rbx, 1
|
||||||
|
WORD $0x3948; BYTE $0xf3 // cmp rbx, rsi
|
||||||
|
JB LBB5_15
|
||||||
|
WORD $0xe6c1; BYTE $0x03 // shl esi, 3
|
||||||
|
JMP LBB5_21
|
||||||
|
|
||||||
|
LBB5_18:
|
||||||
|
WORD $0xbc0f; BYTE $0xc3 // bsf eax, ebx
|
||||||
|
JMP LBB5_25
|
||||||
|
|
||||||
|
LBB5_19:
|
||||||
|
WORD $0xbc0f; BYTE $0xc2 // bsf eax, edx
|
||||||
|
JMP LBB5_24
|
||||||
|
|
||||||
|
LBB5_20:
|
||||||
|
WORD $0xbc0f; BYTE $0xf2 // bsf esi, edx
|
||||||
|
WORD $0xeec1; BYTE $0x03 // shr esi, 3
|
||||||
|
|
||||||
|
LBB5_21:
|
||||||
|
WORD $0xf189 // mov ecx, esi
|
||||||
|
WORD $0x0148; BYTE $0xc8 // add rax, rcx
|
||||||
|
JMP LBB5_25
|
||||||
|
|
||||||
|
LBB5_22:
|
||||||
|
WORD $0xbc0f; BYTE $0xf2 // bsf esi, edx
|
||||||
|
WORD $0xeec1; BYTE $0x03 // shr esi, 3
|
||||||
|
|
||||||
|
LBB5_23:
|
||||||
|
WORD $0xf189 // mov ecx, esi
|
||||||
|
WORD $0x0148; BYTE $0xc8 // add rax, rcx
|
||||||
|
|
||||||
|
LBB5_24:
|
||||||
|
WORD $0x014c; BYTE $0xc0 // add rax, r8
|
||||||
|
|
||||||
|
LBB5_25:
|
||||||
|
VZEROUPPER
|
||||||
|
MOVQ AX, ret+16(FP)
|
||||||
|
RET
|
|
@ -402,12 +402,13 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
code = code.End.Next
|
code = code.End.Next
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
b = appendStructHead(ctx, b)
|
unorderedMap := (ctx.Option.Flag & encoder.UnorderedMapOption) != 0
|
||||||
mapCtx := encoder.NewMapContext(mlen)
|
mapCtx := encoder.NewMapContext(mlen, unorderedMap)
|
||||||
mapiterinit(code.Type, uptr, &mapCtx.Iter)
|
mapiterinit(code.Type, uptr, &mapCtx.Iter)
|
||||||
store(ctxptr, code.Idx, uintptr(unsafe.Pointer(mapCtx)))
|
store(ctxptr, code.Idx, uintptr(unsafe.Pointer(mapCtx)))
|
||||||
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx))
|
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx))
|
||||||
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
b = appendStructHead(ctx, b)
|
||||||
|
if unorderedMap {
|
||||||
b = appendMapKeyIndent(ctx, code.Next, b)
|
b = appendMapKeyIndent(ctx, code.Next, b)
|
||||||
} else {
|
} else {
|
||||||
mapCtx.Start = len(b)
|
mapCtx.Start = len(b)
|
||||||
|
|
|
@ -402,12 +402,13 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
code = code.End.Next
|
code = code.End.Next
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
b = appendStructHead(ctx, b)
|
unorderedMap := (ctx.Option.Flag & encoder.UnorderedMapOption) != 0
|
||||||
mapCtx := encoder.NewMapContext(mlen)
|
mapCtx := encoder.NewMapContext(mlen, unorderedMap)
|
||||||
mapiterinit(code.Type, uptr, &mapCtx.Iter)
|
mapiterinit(code.Type, uptr, &mapCtx.Iter)
|
||||||
store(ctxptr, code.Idx, uintptr(unsafe.Pointer(mapCtx)))
|
store(ctxptr, code.Idx, uintptr(unsafe.Pointer(mapCtx)))
|
||||||
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx))
|
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx))
|
||||||
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
b = appendStructHead(ctx, b)
|
||||||
|
if unorderedMap {
|
||||||
b = appendMapKeyIndent(ctx, code.Next, b)
|
b = appendMapKeyIndent(ctx, code.Next, b)
|
||||||
} else {
|
} else {
|
||||||
mapCtx.Start = len(b)
|
mapCtx.Start = len(b)
|
||||||
|
|
|
@ -402,12 +402,13 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
code = code.End.Next
|
code = code.End.Next
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
b = appendStructHead(ctx, b)
|
unorderedMap := (ctx.Option.Flag & encoder.UnorderedMapOption) != 0
|
||||||
mapCtx := encoder.NewMapContext(mlen)
|
mapCtx := encoder.NewMapContext(mlen, unorderedMap)
|
||||||
mapiterinit(code.Type, uptr, &mapCtx.Iter)
|
mapiterinit(code.Type, uptr, &mapCtx.Iter)
|
||||||
store(ctxptr, code.Idx, uintptr(unsafe.Pointer(mapCtx)))
|
store(ctxptr, code.Idx, uintptr(unsafe.Pointer(mapCtx)))
|
||||||
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx))
|
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx))
|
||||||
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
b = appendStructHead(ctx, b)
|
||||||
|
if unorderedMap {
|
||||||
b = appendMapKeyIndent(ctx, code.Next, b)
|
b = appendMapKeyIndent(ctx, code.Next, b)
|
||||||
} else {
|
} else {
|
||||||
mapCtx.Start = len(b)
|
mapCtx.Start = len(b)
|
||||||
|
|
|
@ -402,12 +402,13 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
code = code.End.Next
|
code = code.End.Next
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
b = appendStructHead(ctx, b)
|
unorderedMap := (ctx.Option.Flag & encoder.UnorderedMapOption) != 0
|
||||||
mapCtx := encoder.NewMapContext(mlen)
|
mapCtx := encoder.NewMapContext(mlen, unorderedMap)
|
||||||
mapiterinit(code.Type, uptr, &mapCtx.Iter)
|
mapiterinit(code.Type, uptr, &mapCtx.Iter)
|
||||||
store(ctxptr, code.Idx, uintptr(unsafe.Pointer(mapCtx)))
|
store(ctxptr, code.Idx, uintptr(unsafe.Pointer(mapCtx)))
|
||||||
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx))
|
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx))
|
||||||
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
b = appendStructHead(ctx, b)
|
||||||
|
if unorderedMap {
|
||||||
b = appendMapKeyIndent(ctx, code.Next, b)
|
b = appendMapKeyIndent(ctx, code.Next, b)
|
||||||
} else {
|
} else {
|
||||||
mapCtx.Start = len(b)
|
mapCtx.Start = len(b)
|
||||||
|
|
|
@ -15,6 +15,12 @@ func UnorderedMap() EncodeOptionFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DisableHTMLEscape() EncodeOptionFunc {
|
||||||
|
return func(opt *EncodeOption) {
|
||||||
|
opt.Flag &= ^encoder.HTMLEscapeOption
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Debug outputs debug information when panic occurs during encoding.
|
// Debug outputs debug information when panic occurs during encoding.
|
||||||
func Debug() EncodeOptionFunc {
|
func Debug() EncodeOptionFunc {
|
||||||
return func(opt *EncodeOption) {
|
return func(opt *EncodeOption) {
|
||||||
|
|
Loading…
Reference in New Issue