- update vendor

master
李光春 10 months ago
parent 6e49867d6f
commit dc3bc54468

@ -6,16 +6,16 @@ require (
github.com/MercuryEngineering/CookieMonster v0.0.0-20180304172713-1584578b3403
github.com/aliyun/aliyun-oss-go-sdk v2.2.7+incompatible
github.com/allegro/bigcache/v3 v3.1.0
github.com/baidubce/bce-sdk-go v0.9.151
github.com/baidubce/bce-sdk-go v0.9.153
github.com/basgys/goxml2json v1.1.0
github.com/bytedance/sonic v1.9.2
github.com/bytedance/sonic v1.10.0-rc2
github.com/gin-gonic/gin v1.9.1
github.com/go-playground/locales v0.14.1
github.com/go-playground/universal-translator v0.18.1
github.com/go-playground/validator/v10 v10.14.1
github.com/go-sql-driver/mysql v1.7.1
github.com/goccy/go-json v0.10.2
github.com/gogf/gf/v2 v2.4.4
github.com/gogf/gf/v2 v2.5.0
github.com/json-iterator/go v1.1.12
github.com/lib/pq v1.10.9
github.com/mitchellh/mapstructure v1.5.0
@ -32,13 +32,13 @@ require (
go.mongodb.org/mongo-driver v1.12.0
go.uber.org/zap v1.24.0
golang.org/x/crypto v0.11.0
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df
golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1
golang.org/x/text v0.11.0
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
gorm.io/datatypes v1.2.0
gorm.io/driver/mysql v1.5.1
gorm.io/driver/postgres v1.5.2
gorm.io/gen v0.3.22
gorm.io/gen v0.3.23
gorm.io/gorm v1.25.2
xorm.io/builder v0.3.12
xorm.io/xorm v1.3.2
@ -47,7 +47,8 @@ require (
require (
github.com/bitly/go-simplejson v0.5.0 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
github.com/chenzhuoyu/iasm v0.9.0 // indirect
github.com/clbanning/mxj v1.8.4 // indirect
github.com/clbanning/mxj/v2 v2.5.7 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
@ -62,7 +63,7 @@ require (
github.com/google/go-querystring v1.1.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/pgx/v5 v5.4.1 // indirect
github.com/jackc/pgx/v5 v5.4.2 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/klauspost/compress v1.16.7 // indirect
@ -76,7 +77,7 @@ require (
github.com/montanaflynn/stats v0.7.1 // indirect
github.com/mozillazg/go-httpheader v0.4.0 // indirect
github.com/oschwald/maxminddb-golang v1.11.0 // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
github.com/pelletier/go-toml/v2 v2.0.9 // indirect
github.com/rogpeppe/go-internal v1.8.1 // indirect
github.com/saracen/go7z-fixtures v0.0.0-20190623165746-aa6b8fba1d2f // indirect
github.com/saracen/solidblock v0.0.0-20190426153529-45df20abab6f // indirect

@ -32,8 +32,8 @@ github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6l
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
github.com/baidubce/bce-sdk-go v0.9.151 h1:AWCcndmlt29ti2iJ9Re1pInOOnAplY2KGMAsN3LCTjw=
github.com/baidubce/bce-sdk-go v0.9.151/go.mod h1:zbYJMQwE4IZuyrJiFO8tO8NbtYiKTFTbwh4eIsqjVdg=
github.com/baidubce/bce-sdk-go v0.9.153 h1:h5l2EXehe4C4/bdlAPBaULrbnEDgIu5HOYgniN7bjGM=
github.com/baidubce/bce-sdk-go v0.9.153/go.mod h1:zbYJMQwE4IZuyrJiFO8tO8NbtYiKTFTbwh4eIsqjVdg=
github.com/basgys/goxml2json v1.1.0 h1:4ln5i4rseYfXNd86lGEB+Vi652IsIXIvggKM/BhUKVw=
github.com/basgys/goxml2json v1.1.0/go.mod h1:wH7a5Np/Q4QoECFIU8zTQlZwZkrilY0itPfecMw41Dw=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
@ -46,8 +46,9 @@ github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngE
github.com/bsm/ginkgo/v2 v2.7.0 h1:ItPMPH90RbmZJt5GtkcNvIRuGEdwlBItdNVoyzaNQao=
github.com/bsm/gomega v1.26.0 h1:LhQm+AFcgV2M0WyKroMASzAzCAJVpAxQXv4SaI9a69Y=
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
github.com/bytedance/sonic v1.9.2 h1:GDaNjuWSGu09guE9Oql0MSTNhNCLlWwO8y/xM5BzcbM=
github.com/bytedance/sonic v1.9.2/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM=
github.com/bytedance/sonic v1.10.0-rc2 h1:oDfRZ+4m6AYCOC0GFeOCeYqvBmucy1isvouS2K0cPzo=
github.com/bytedance/sonic v1.10.0-rc2/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
@ -55,8 +56,11 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0=
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA=
github.com/chenzhuoyu/iasm v0.9.0 h1:9fhXjVzq5hUy2gkhhgHl95zG2cEAhw9OSGs8toWWAwo=
github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
github.com/clbanning/mxj v1.8.4 h1:HuhwZtbyvyOw+3Z1AowPkU87JkJUSv751ELWaiTpj8I=
github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng=
github.com/clbanning/mxj/v2 v2.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
@ -146,8 +150,8 @@ github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogf/gf/v2 v2.4.4 h1:+s7PKxd4LJKjJn5ODZvYcbXMM5e+88Ww1W3GdOarLE8=
github.com/gogf/gf/v2 v2.4.4/go.mod h1:tsbmtwcAl2chcYoq/fP9W2FZf06aw4i89X34nbSHo9Y=
github.com/gogf/gf/v2 v2.5.0 h1:dFZbIOq/3TmHNWTodSxHbAluuyh274hTvqoNe67pAbE=
github.com/gogf/gf/v2 v2.5.0/go.mod h1:tsbmtwcAl2chcYoq/fP9W2FZf06aw4i89X34nbSHo9Y=
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
@ -268,8 +272,8 @@ github.com/jackc/pgx/v4 v4.6.1-0.20200510190926-94ba730bb1e9/go.mod h1:t3/cdRQl6
github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904/go.mod h1:ZDaNWkt9sW1JMiNn0kdYBaLelIhw7Pg4qd+Vk6tw7Hg=
github.com/jackc/pgx/v4 v4.11.0/go.mod h1:i62xJgdrtVDsnL3U8ekyrQXEwGNTRoG7/8r+CIdYfcc=
github.com/jackc/pgx/v4 v4.12.0/go.mod h1:fE547h6VulLPA3kySjfnSG/e2D861g/50JlVUa/ub60=
github.com/jackc/pgx/v5 v5.4.1 h1:oKfB/FhuVtit1bBM3zNRRsZ925ZkMN3HXL+LgLUM9lE=
github.com/jackc/pgx/v5 v5.4.1/go.mod h1:q6iHT8uDNXWiFNOlRqJzBTaSH3+2xCXkokxHZC5qWFY=
github.com/jackc/pgx/v5 v5.4.2 h1:u1gmGDwbdRUZiwisBm/Ky2M14uQyUP65bG8+20nnyrg=
github.com/jackc/pgx/v5 v5.4.2/go.mod h1:q6iHT8uDNXWiFNOlRqJzBTaSH3+2xCXkokxHZC5qWFY=
github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
@ -299,6 +303,7 @@ github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQs
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
@ -416,8 +421,8 @@ github.com/oschwald/maxminddb-golang v1.11.0/go.mod h1:YmVI+H0zh3ySFR3w+oz8PCfgl
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
github.com/pelletier/go-toml/v2 v2.0.9 h1:uH2qQXheeefCCkuBBSLi7jCiSmj3VRh2+Goq2N7Xxu0=
github.com/pelletier/go-toml/v2 v2.0.9/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
@ -511,8 +516,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.563/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y=
@ -612,8 +617,8 @@ golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw
golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME=
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw=
golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@ -817,8 +822,8 @@ gorm.io/driver/postgres v1.5.2/go.mod h1:fmpX0m2I1PKuR7mKZiEluwrP3hbs+ps7JIGMUBp
gorm.io/driver/sqlite v1.5.0 h1:zKYbzRCpBrT1bNijRnxLDJWPjVfImGEn0lSnUY5gZ+c=
gorm.io/driver/sqlite v1.5.0/go.mod h1:kDMDfntV9u/vuMmz8APHtHF0b4nyBB7sfCieC6G8k8I=
gorm.io/driver/sqlserver v1.4.1 h1:t4r4r6Jam5E6ejqP7N82qAJIJAht27EGT41HyPfXRw0=
gorm.io/gen v0.3.22 h1:K7u5tCyaZfe1cbQFD8N2xrTqUuqximNFSRl7zOFPq+M=
gorm.io/gen v0.3.22/go.mod h1:dQcELeF/7Kf82M6AQF+O/rKT5r1sjv49TlGz0cerPn4=
gorm.io/gen v0.3.23 h1:TL+q3bXvOzeIXBRp9vqIaD4/iaEzdU1Kgy5QSHsxDEQ=
gorm.io/gen v0.3.23/go.mod h1:G9uxGfkfNFxPoOrV5P6KQxRMgZsQSCyp9vJP8xiKTGg=
gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
gorm.io/gorm v1.24.3/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA=
gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
@ -943,6 +948,7 @@ modernc.org/tcl v1.8.13/go.mod h1:V+q/Ef0IJaNUSECieLU4o+8IScapxnMyFV6i/7uQlAY=
modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk=
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
modernc.org/z v1.2.19/go.mod h1:+ZpP0pc4zz97eukOzW3xagV/lS82IpPN9NGG5pNF9vY=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=

@ -1,5 +1,5 @@
package go_library
func Version() string {
return "1.0.155"
return "1.0.156"
}

@ -155,6 +155,11 @@ func (c *BceClient) SendRequest(req *BceRequest, resp *BceResponse) error {
log.Infof("receive http response: status: %s, debugId: %s, requestId: %s, elapsed: %v",
resp.StatusText(), resp.DebugId(), resp.RequestId(), resp.ElapsedTime())
if resp.ElapsedTime().Milliseconds() > DEFAULT_WARN_LOG_TIMEOUT_IN_MILLS {
log.Warnf("request time more than 5 second, debugId: %s, requestId: %s, elapsed: %v",
resp.DebugId(), resp.RequestId(), resp.ElapsedTime())
}
for k, v := range resp.Headers() {
log.Debugf("%s=%s", k, v)
}

@ -26,13 +26,14 @@ import (
// Constants and default values for the package bce
const (
SDK_VERSION = "0.9.151"
SDK_VERSION = "0.9.153"
URI_PREFIX = "/" // now support uri without prefix "v1" so just set root path
DEFAULT_DOMAIN = "baidubce.com"
DEFAULT_PROTOCOL = "http"
DEFAULT_REGION = "bj"
DEFAULT_CONTENT_TYPE = "application/json;charset=utf-8"
DEFAULT_CONNECTION_TIMEOUT_IN_MILLIS = 1200 * 1000
DEFAULT_WARN_LOG_TIMEOUT_IN_MILLS = 5 * 1000
)
var (

@ -271,6 +271,7 @@ type CopyObjectArgs struct {
IfModifiedSince string
IfUnmodifiedSince string
TrafficLimit int64
CannedAcl string
}
type MultiCopyObjectArgs struct {

@ -194,6 +194,10 @@ func CopyObject(cli bce.Client, bucket, object, source string,
req.SetHeader(http.BCE_TRAFFIC_LIMIT, fmt.Sprintf("%d", args.TrafficLimit))
}
if validCannedAcl(args.CannedAcl) {
req.SetHeader(http.BCE_ACL, args.CannedAcl)
}
if err := setUserMetadata(req, args.UserMeta); err != nil {
return nil, err
}

@ -919,6 +919,7 @@ func (c *Client) PutObjectFromStream(bucket, object string, reader io.Reader,
return api.PutObject(c, bucket, object, body, args)
}
// CopyObject - copy a remote object to another one
//
// PARAMS:
@ -2128,7 +2129,7 @@ func (c *Client) parallelPartCopy(srcMeta api.GetObjectMetaResult, source string
var err error
size := srcMeta.ContentLength
partSize := int64(DEFAULT_MULTIPART_SIZE)
if partSize * MAX_PART_NUMBER < size {
if partSize*MAX_PART_NUMBER < size {
lowerLimit := int64(math.Ceil(float64(size) / MAX_PART_NUMBER))
partSize = int64(math.Ceil(float64(lowerLimit)/float64(partSize))) * partSize
}
@ -2250,4 +2251,4 @@ func (c *Client) GetBucketMirror(bucket string) (*api.PutBucketMirrorArgs, error
func (c *Client) DeleteBucketMirror(bucket string) error {
return api.DeleteBucketMirror(c, bucket)
}
}

@ -23,23 +23,25 @@ CPU_avx := amd64
CPU_avx2 := amd64
CPU_sse := amd64
TMPL_avx := fastint_amd64_test fastfloat_amd64_test native_amd64_test native_export_amd64
TMPL_avx2 := fastint_amd64_test fastfloat_amd64_test native_amd64_test native_export_amd64
TMPL_sse := fastint_amd64_test fastfloat_amd64_test native_amd64_test native_export_amd64
CFLAGS_avx := -msse -mssse3 -mno-sse4 -mavx -mpclmul -mno-avx2 -DUSE_AVX=1 -DUSE_AVX2=0
CFLAGS_avx2 := -msse -mssse3 -mno-sse4 -mavx -mpclmul -mavx2 -DUSE_AVX=1 -DUSE_AVX2=1
CFLAGS_sse := -msse -mssse3 -mno-sse4 -mno-avx -mno-avx2 -mpclmul
TARGETFLAGS := -target x86_64-apple-macos11 -nostdlib -fno-builtin -fno-asynchronous-unwind-tables
TMPL_avx := fastint_amd64_test fastfloat_amd64_test native_amd64_test recover_amd64_test
TMPL_avx2 := fastint_amd64_test fastfloat_amd64_test native_amd64_test recover_amd64_test
TMPL_sse := fastint_amd64_test fastfloat_amd64_test native_amd64_test recover_amd64_test
CFLAGS_avx := -msse -mno-sse4 -mavx -mpclmul -mno-avx2 -mstack-alignment=0 -DUSE_AVX=1 -DUSE_AVX2=0
CFLAGS_avx2 := -msse -mno-sse4 -mavx -mpclmul -mavx2 -mstack-alignment=0 -DUSE_AVX=1 -DUSE_AVX2=1
CFLAGS_sse := -msse -mno-sse4 -mno-avx -mno-avx2 -mpclmul
CC_amd64 := clang
ASM2ASM_amd64 := tools/asm2asm/asm2asm.py
CFLAGS := -mno-red-zone
CFLAGS += -target x86_64-apple-macos11
CFLAGS += -fno-asynchronous-unwind-tables
CFLAGS += -fno-builtin
CFLAGS += -fno-exceptions
CFLAGS += -fno-rtti
CFLAGS += -fno-stack-protector
CFLAGS += -nostdlib
CFLAGS += -O3
CFLAGS += -Wall -Werror
@ -64,7 +66,7 @@ define build_arch
$(eval @cpu := $(value CPU_$(1)))
$(eval @deps := $(foreach tmpl,$(value TMPL_$(1)),${OUT_DIR}/$(1)/${tmpl}.go))
$(eval @asmin := ${TMP_DIR}/$(1)/native.s)
$(eval @asmout := ${OUT_DIR}/$(1)/native_${@cpu}.s)
$(eval @asmout := ${OUT_DIR}/$(1)/native_text_${@cpu}.go)
$(eval @stubin := ${OUT_DIR}/native_${@cpu}.tmpl)
$(eval @stubout := ${OUT_DIR}/$(1)/native_${@cpu}.go)
@ -72,14 +74,8 @@ $(1): ${@asmout} ${@deps}
${@asmout}: ${@stubout} ${NATIVE_SRC}
mkdir -p ${TMP_DIR}/$(1)
$${CC_${@cpu}} $${CFLAGS} $${CFLAGS_$(1)} ${TARGETFLAGS} -S -o ${TMP_DIR}/$(1)/native.s ${SRC_FILE}
$(foreach file,
$(wildcard native/unittest/*),
$${CC_${@cpu}} $${CFLAGS} $${CFLAGS_$(1)} -I./native -o ${TMP_DIR}/$(1)/test $(file)
./${TMP_DIR}/$(1)/test
)
python3 $${ASM2ASM_${@cpu}} ${@asmout} ${TMP_DIR}/$(1)/native.s
asmfmt -w ${@asmout}
$${CC_${@cpu}} $${CFLAGS} $${CFLAGS_$(1)} -S -o ${TMP_DIR}/$(1)/native.s ${SRC_FILE}
python3 $${ASM2ASM_${@cpu}} -r ${@stubout} ${TMP_DIR}/$(1)/native.s
$(eval $(call \
build_tmpl, \
@ -113,4 +109,3 @@ $(foreach \
${ARCH}, \
$(eval $(call build_arch,${arch})) \
)

@ -5,8 +5,8 @@ English | [中文](README_ZH_CN.md)
A blazingly fast JSON serializing &amp; deserializing library, accelerated by JIT (just-in-time compiling) and SIMD (single-instruction-multiple-data).
## Requirement
- Go 1.15~1.20
- Linux/MacOS/Windows
- Go 1.16~1.20
- Linux / MacOS / Windows(need go1.17 above)
- Amd64 ARCH
## Features
@ -76,6 +76,10 @@ BenchmarkSetOne_Jsoniter-16 79475 ns/op 163.8
BenchmarkSetOne_Parallel_Sonic-16 850.9 ns/op 15305.31 MB/s 1584 B/op 17 allocs/op
BenchmarkSetOne_Parallel_Sjson-16 18194 ns/op 715.77 MB/s 52247 B/op 9 allocs/op
BenchmarkSetOne_Parallel_Jsoniter-16 33560 ns/op 388.05 MB/s 45892 B/op 964 allocs/op
BenchmarkLoadNode/LoadAll()-16 11384 ns/op 1143.93 MB/s 6307 B/op 25 allocs/op
BenchmarkLoadNode_Parallel/LoadAll()-16 5493 ns/op 2370.68 MB/s 7145 B/op 25 allocs/op
BenchmarkLoadNode/Interface()-16 17722 ns/op 734.85 MB/s 13323 B/op 88 allocs/op
BenchmarkLoadNode_Parallel/Interface()-16 10330 ns/op 1260.70 MB/s 15178 B/op 88 allocs/op
```
- [Small](https://github.com/bytedance/sonic/blob/main/testdata/small.go) (400B, 11 keys, 3 layers)
![small benchmarks](./docs/imgs/bench-small.png)
@ -282,6 +286,42 @@ println(string(buf) == string(exp)) // true
- iteration: `Values()`, `Properties()`, `ForEach()`, `SortKeys()`
- modification: `Set()`, `SetByIndex()`, `Add()`
### Ast.Visitor
Sonic provides an advanced API for fully parsing JSON into non-standard types (neither `struct` not `map[string]interface{}`) without using any intermediate representation (`ast.Node` or `interface{}`). For example, you might have the following types which are like `interface{}` but actually not `interface{}`:
```go
type UserNode interface {}
// the following types implement the UserNode interface.
type (
UserNull struct{}
UserBool struct{ Value bool }
UserInt64 struct{ Value int64 }
UserFloat64 struct{ Value float64 }
UserString struct{ Value string }
UserObject struct{ Value map[string]UserNode }
UserArray struct{ Value []UserNode }
)
```
Sonic provides the following API to return **the preorder traversal of a JSON AST**. The `ast.Visitor` is a SAX style interface which is used in some C++ JSON library. You should implement `ast.Visitor` by yourself and pass it to `ast.Preorder()` method. In your visitor you can make your custom types to represent JSON values. There may be an O(n) space container (such as stack) in your visitor to record the object / array hierarchy.
```go
func Preorder(str string, visitor Visitor, opts *VisitorOptions) error
type Visitor interface {
OnNull() error
OnBool(v bool) error
OnString(v string) error
OnInt64(v int64, n json.Number) error
OnFloat64(v float64, n json.Number) error
OnObjectBegin(capacity int) error
OnObjectKey(key string) error
OnObjectEnd() error
OnArrayBegin(capacity int) error
OnArrayEnd() error
}
```
See [ast/visitor.go](https://github.com/bytedance/sonic/blob/main/ast/visitor.go) for detailed usage. We also implement a demo visitor for `UserNode` in [ast/visitor_test.go](https://github.com/bytedance/sonic/blob/main/ast/visitor_test.go).
## Compatibility
Sonic **DOES NOT** ensure to support all environments, due to the difficulty of developing high-performance codes. For developers who use sonic to build their applications in different environments, we have the following suggestions:
@ -311,7 +351,7 @@ func init() {
err := sonic.Pretouch(reflect.TypeOf(v))
// with more CompileOption...
err := sonic.Pretouch(reflect.TypeOf(v),
err := sonic.Pretouch(reflect.TypeOf(v),
// If the type is too deep nesting (nesting depth > option.DefaultMaxInlineDepth),
// you can set compile recursive loops in Pretouch for better stability in JIT.
option.WithCompileRecursiveDepth(loop),
@ -358,5 +398,14 @@ Why? Because `ast.Node` stores its children using `array`:
**CAUTION:** `ast.Node` **DOESN'T** ensure concurrent security directly, due to its **lazy-load** design. However, you can call `Node.Load()`/`Node.LoadAll()` to achieve that, which may bring performance reduction while it still works faster than converting to `map` or `interface{}`
### Ast.Node or Ast.Visitor?
For generic data, `ast.Node` should be enough for your needs in most cases.
However, `ast.Node` is designed for partially processing JSON string. It has some special designs such as lazy-load which might not be suitable for directly parsing the whole JSON string like `Unmarshal()`. Although `ast.Node` is better then `map` or `interface{}`, it's also a kind of intermediate representation after all if your final types are customized and you have to convert the above types to your custom types after parsing.
For better performance, in previous case the `ast.Visitor` will be the better choice. It performs JSON decoding like `Unmarshal()` and you can directly use your final types to represents a JSON AST without any intermediate representations.
But `ast.Visitor` is not a very handy API. You might need to write a lot of code to implement your visitor and carefully maintain the tree hierarchy during decoding. Please read the comments in [ast/visitor.go](https://github.com/bytedance/sonic/blob/main/ast/visitor.go) carefully if you decide to use this API.
## Community
Sonic is a subproject of [CloudWeGo](https://www.cloudwego.io/). We are committed to building a cloud native ecosystem.

@ -6,8 +6,8 @@
## 依赖
- Go 1.15~1.20
- Linux/MacOS/Windows
- Go 1.16~1.20
- Linux / MacOS / Windows(需要 Go1.17 以上)
- Amd64 架构
## 特色
@ -79,6 +79,10 @@ BenchmarkSetOne_Jsoniter-16 79475 ns/op 163.8
BenchmarkSetOne_Parallel_Sonic-16 850.9 ns/op 15305.31 MB/s 1584 B/op 17 allocs/op
BenchmarkSetOne_Parallel_Sjson-16 18194 ns/op 715.77 MB/s 52247 B/op 9 allocs/op
BenchmarkSetOne_Parallel_Jsoniter-16 33560 ns/op 388.05 MB/s 45892 B/op 964 allocs/op
BenchmarkLoadNode/LoadAll()-16 11384 ns/op 1143.93 MB/s 6307 B/op 25 allocs/op
BenchmarkLoadNode_Parallel/LoadAll()-16 5493 ns/op 2370.68 MB/s 7145 B/op 25 allocs/op
BenchmarkLoadNode/Interface()-16 17722 ns/op 734.85 MB/s 13323 B/op 88 allocs/op
BenchmarkLoadNode_Parallel/Interface()-16 10330 ns/op 1260.70 MB/s 15178 B/op 88 allocs/op
```
- [小型](https://github.com/bytedance/sonic/blob/main/testdata/small.go) (400B, 11 个键, 3 层)
![small benchmarks](./docs/imgs/bench-small.png)
@ -298,6 +302,41 @@ println(string(buf) == string(exp)) // true
- 迭代: `Values()`, `Properties()`, `ForEach()`, `SortKeys()`
- 修改: `Set()`, `SetByIndex()`, `Add()`
### `Ast.Visitor`
Sonic 提供了一个高级的 API 用于直接全量解析 JSON 到非标准容器里 (既不是 `struct` 也不是 `map[string]interface{}`) 且不需要借助任何中间表示 (`ast.Node` 或 `interface{}`)。举个例子,你可能定义了下述的类型,它们看起来像 `interface{}`,但实际上并不是:
```go
type UserNode interface {}
// the following types implement the UserNode interface.
type (
UserNull struct{}
UserBool struct{ Value bool }
UserInt64 struct{ Value int64 }
UserFloat64 struct{ Value float64 }
UserString struct{ Value string }
UserObject struct{ Value map[string]UserNode }
UserArray struct{ Value []UserNode }
)
```
Sonic 提供了下述的 API 来返回 **“对 JSON AST 的前序遍历”**。`ast.Visitor` 是一个 SAX 风格的接口,这在某些 C++ 的 JSON 解析库中被使用到。你需要自己实现一个 `ast.Visitor`,将它传递给 `ast.Preorder()` 方法。在你的实现中你可以使用自定义的类型来表示 JSON 的值。在你的 `ast.Visitor` 中,可能需要有一个 O(n) 空间复杂度的容器(比如说栈)来记录 object / array 的层级。
```go
func Preorder(str string, visitor Visitor, opts *VisitorOptions) error
type Visitor interface {
OnNull() error
OnBool(v bool) error
OnString(v string) error
OnInt64(v int64, n json.Number) error
OnFloat64(v float64, n json.Number) error
OnObjectBegin(capacity int) error
OnObjectKey(key string) error
OnObjectEnd() error
OnArrayBegin(capacity int) error
OnArrayEnd() error
}
```
详细用法参看 [ast/visitor.go](https://github.com/bytedance/sonic/blob/main/ast/visitor.go),我们还为 `UserNode` 实现了一个示例 `ast.Visitor`,你可以在 [ast/visitor_test.go](https://github.com/bytedance/sonic/blob/main/ast/visitor_test.go) 中找到它。
## 兼容性
由于开发高性能代码的困难性, Sonic **不**保证对所有环境的支持。对于在不同环境中使用 Sonic 构建应用程序的开发者,我们有以下建议:
@ -327,7 +366,7 @@ func init() {
err := sonic.Pretouch(reflect.TypeOf(v))
// with more CompileOption...
err := sonic.Pretouch(reflect.TypeOf(v),
err := sonic.Pretouch(reflect.TypeOf(v),
// If the type is too deep nesting (nesting depth > option.DefaultMaxInlineDepth),
// you can set compile recursive loops in Pretouch for better stability in JIT.
option.WithCompileRecursiveDepth(loop),
@ -377,6 +416,15 @@ go someFunc(user)
**注意**:由于 `ast.Node` 的惰性加载设计,其**不能**直接保证并发安全性,但你可以调用 `Node.Load()` / `Node.LoadAll()` 来实现并发安全。尽管可能会带来性能损失,但仍比转换成 `map``interface{}` 更为高效。
### 使用 `ast.Node` 还是 `ast.Visitor`
对于泛型数据的解析,`ast.Node` 在大多数场景上应该能够满足你的需求。
然而,`ast.Node` 是一种针对部分解析 JSON 而设计的泛型容器,它包含一些特殊设计,比如惰性加载,如果你希望像 `Unmarshal()` 那样直接解析整个 JSON这些设计可能并不合适。尽管 `ast.Node` 相较于 `map``interface{}` 来说是更好的一种泛型容器,但它毕竟也是一种中间表示,如果你的最终类型是自定义的,你还得在解析完成后将上述类型转化成你自定义的类型。
在上述场景中,如果想要有更极致的性能,`ast.Visitor` 会是更好的选择。它采用和 `Unmarshal()` 类似的形式解析 JSON并且你可以直接使用你的最终类型去表示 JSON AST而不需要经过额外的任何中间表示。
但是,`ast.Visitor` 并不是一个很易用的 API。你可能需要写大量的代码去实现自己的 `ast.Visitor`,并且需要在解析过程中仔细维护树的层级。如果你决定要使用这个 API请先仔细阅读 [ast/visitor.go](https://github.com/bytedance/sonic/blob/main/ast/visitor.go) 中的注释。
## 社区
Sonic 是 [CloudWeGo](https://www.cloudwego.io/) 下的一个子项目。我们致力于构建云原生生态系统。

@ -184,3 +184,8 @@ func Get(src []byte, path ...interface{}) (ast.Node, error) {
func GetFromString(src string, path ...interface{}) (ast.Node, error) {
return ast.NewSearcher(src).GetByPath(path...)
}
// Valid reports whether data is a valid JSON encoding.
func Valid(data []byte) bool {
return ConfigDefault.Valid(data)
}

@ -1,4 +1,4 @@
// +build amd64,go1.15,!go1.21
// +build amd64,go1.16,!go1.21
/*
* Copyright 2022 ByteDance Inc.
@ -87,7 +87,13 @@ func encodeBase64(src []byte) string {
func (self *Parser) decodeValue() (val types.JsonState) {
sv := (*rt.GoString)(unsafe.Pointer(&self.s))
self.p = native.Value(sv.Ptr, sv.Len, self.p, &val, 0)
flag := types.F_USE_NUMBER
if self.dbuf != nil {
flag = 0
val.Dbuf = self.dbuf
val.Dcap = types.MaxDigitNums
}
self.p = native.Value(sv.Ptr, sv.Len, self.p, &val, uint64(flag))
return
}

@ -1,4 +1,4 @@
// +build !amd64 go1.21
// +build !amd64 !go1.16 go1.21
/*
* Copyright 2022 ByteDance Inc.
@ -27,6 +27,10 @@ import (
`github.com/bytedance/sonic/internal/rt`
)
func init() {
println("WARNING: sonic only supports Go1.16~1.20 && CPU amd64, but your environment is not suitable")
}
func quote(buf *[]byte, val string) {
quoteString(buf, val)
}
@ -49,7 +53,7 @@ func encodeBase64(src []byte) string {
}
func (self *Parser) decodeValue() (val types.JsonState) {
e, v := decodeValue(self.s, self.p)
e, v := decodeValue(self.s, self.p, self.dbuf == nil)
if e < 0 {
return v
}

@ -0,0 +1,329 @@
/**
* Copyright 2023 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ast
import (
`sort`
`unsafe`
)
type nodeChunk [_DEFAULT_NODE_CAP]Node
type linkedNodes struct {
head nodeChunk
tail []*nodeChunk
size int
}
func (self *linkedNodes) Cap() int {
if self == nil {
return 0
}
return (len(self.tail)+1)*_DEFAULT_NODE_CAP
}
func (self *linkedNodes) Len() int {
if self == nil {
return 0
}
return self.size
}
func (self *linkedNodes) At(i int) (*Node) {
if self == nil {
return nil
}
if i >= 0 && i<self.size && i < _DEFAULT_NODE_CAP {
return &self.head[i]
} else if i >= _DEFAULT_NODE_CAP && i<self.size {
a, b := i/_DEFAULT_NODE_CAP-1, i%_DEFAULT_NODE_CAP
if a < len(self.tail) {
return &self.tail[a][b]
}
}
return nil
}
func (self *linkedNodes) Add(v Node) {
if self.size < _DEFAULT_NODE_CAP {
self.head[self.size] = v
self.size++
return
}
a, b, c := self.size/_DEFAULT_NODE_CAP-1 , self.size%_DEFAULT_NODE_CAP, cap(self.tail)
if a - c >= 0 {
c += 1 + c>>_APPEND_GROW_SHIFT
tmp := make([]*nodeChunk, a + 1, c)
copy(tmp, self.tail)
self.tail = tmp
} else if a >= len(self.tail) {
self.tail = self.tail[:a+1]
}
var n = &self.tail[a]
if *n == nil {
*n = new(nodeChunk)
}
(*n)[b] = v
self.size++
}
func (self *linkedNodes) ToSlice(con []Node) {
if len(con) < self.size {
return
}
i := (self.size-1)
a, b := i/_DEFAULT_NODE_CAP-1, i%_DEFAULT_NODE_CAP
if a < 0 {
copy(con, self.head[:b+1])
return
} else {
copy(con, self.head[:])
con = con[_DEFAULT_NODE_CAP:]
}
for i:=0; i<a; i++ {
copy(con, self.tail[i][:])
con = con[_DEFAULT_NODE_CAP:]
}
copy(con, self.tail[a][:b+1])
}
func (self *linkedNodes) FromSlice(con []Node) {
self.size = len(con)
i := self.size-1
a, b := i/_DEFAULT_NODE_CAP-1, i%_DEFAULT_NODE_CAP
if a < 0 {
copy(self.head[:b+1], con)
return
} else {
copy(self.head[:], con)
con = con[_DEFAULT_NODE_CAP:]
}
if cap(self.tail) <= a {
c := (a+1) + (a+1)>>_APPEND_GROW_SHIFT
self.tail = make([]*nodeChunk, a+1, c)
}
self.tail = self.tail[:a+1]
for i:=0; i<a; i++ {
self.tail[i] = new(nodeChunk)
copy(self.tail[i][:], con)
con = con[_DEFAULT_NODE_CAP:]
}
self.tail[a] = new(nodeChunk)
copy(self.tail[a][:b+1], con)
}
type pairChunk [_DEFAULT_NODE_CAP]Pair
type linkedPairs struct {
head pairChunk
tail []*pairChunk
size int
}
func (self *linkedPairs) Cap() int {
if self == nil {
return 0
}
return (len(self.tail)+1)*_DEFAULT_NODE_CAP
}
func (self *linkedPairs) Len() int {
if self == nil {
return 0
}
return self.size
}
func (self *linkedPairs) At(i int) *Pair {
if self == nil {
return nil
}
if i >= 0 && i < _DEFAULT_NODE_CAP && i<self.size {
return &self.head[i]
} else if i >= _DEFAULT_NODE_CAP && i<self.size {
a, b := i/_DEFAULT_NODE_CAP-1, i%_DEFAULT_NODE_CAP
if a < len(self.tail) {
return &self.tail[a][b]
}
}
return nil
}
func (self *linkedPairs) Add(v Pair) {
if self.size < _DEFAULT_NODE_CAP {
self.head[self.size] = v
self.size++
return
}
a, b, c := self.size/_DEFAULT_NODE_CAP-1 , self.size%_DEFAULT_NODE_CAP, cap(self.tail)
if a - c >= 0 {
c += 1 + c>>_APPEND_GROW_SHIFT
tmp := make([]*pairChunk, a + 1, c)
copy(tmp, self.tail)
self.tail = tmp
} else if a >= len(self.tail) {
self.tail = self.tail[:a+1]
}
var n = &self.tail[a]
if *n == nil {
*n = new(pairChunk)
}
(*n)[b] = v
self.size++
}
// linear search
func (self *linkedPairs) Get(key string) (*Pair, int) {
for i:=0; i<self.size; i++ {
if n := self.At(i); n.Key == key {
return n, i
}
}
return nil, -1
}
func (self *linkedPairs) ToSlice(con []Pair) {
if len(con) < self.size {
return
}
i := self.size-1
a, b := i/_DEFAULT_NODE_CAP-1, i%_DEFAULT_NODE_CAP
if a < 0 {
copy(con, self.head[:b+1])
return
} else {
copy(con, self.head[:])
con = con[_DEFAULT_NODE_CAP:]
}
for i:=0; i<a; i++ {
copy(con, self.tail[i][:])
con = con[_DEFAULT_NODE_CAP:]
}
copy(con, self.tail[a][:b+1])
}
func (self *linkedPairs) ToMap(con map[string]Node) {
for i:=0; i<self.size; i++ {
n := self.At(i)
con[n.Key] = n.Value
}
}
func (self *linkedPairs) FromSlice(con []Pair) {
self.size = len(con)
i := self.size-1
a, b := i/_DEFAULT_NODE_CAP-1, i%_DEFAULT_NODE_CAP
if a < 0 {
copy(self.head[:b+1], con)
return
} else {
copy(self.head[:], con)
con = con[_DEFAULT_NODE_CAP:]
}
if cap(self.tail) <= a {
c := (a+1) + (a+1)>>_APPEND_GROW_SHIFT
self.tail = make([]*pairChunk, a+1, c)
}
self.tail = self.tail[:a+1]
for i:=0; i<a; i++ {
self.tail[i] = new(pairChunk)
copy(self.tail[i][:], con)
con = con[_DEFAULT_NODE_CAP:]
}
self.tail[a] = new(pairChunk)
copy(self.tail[a][:b+1], con)
}
func (self *linkedPairs) Less(i, j int) bool {
return lessFrom(self.At(i).Key, self.At(j).Key, 0)
}
func (self *linkedPairs) Swap(i, j int) {
a, b := self.At(i), self.At(j)
*a, *b = *b, *a
}
func (self *linkedPairs) Sort() {
sort.Sort(self)
}
// Compare two strings from the pos d.
func lessFrom(a, b string, d int) bool {
l := len(a)
if l > len(b) {
l = len(b)
}
for i := d; i < l; i++ {
if a[i] == b[i] {
continue
}
return a[i] < b[i]
}
return len(a) < len(b)
}
type parseObjectStack struct {
parser Parser
v linkedPairs
}
type parseArrayStack struct {
parser Parser
v linkedNodes
}
func newLazyArray(p *Parser) Node {
s := new(parseArrayStack)
s.parser = *p
return Node{
t: _V_ARRAY_LAZY,
p: unsafe.Pointer(s),
}
}
func newLazyObject(p *Parser) Node {
s := new(parseObjectStack)
s.parser = *p
return Node{
t: _V_OBJECT_LAZY,
p: unsafe.Pointer(s),
}
}
func (self *Node) getParserAndArrayStack() (*Parser, *parseArrayStack) {
stack := (*parseArrayStack)(self.p)
return &stack.parser, stack
}
func (self *Node) getParserAndObjectStack() (*Parser, *parseObjectStack) {
stack := (*parseObjectStack)(self.p)
return &stack.parser, stack
}

@ -220,7 +220,7 @@ func decodeFloat64(src string, pos int) (ret int, v float64, err error) {
return ret, v, nil
}
func decodeValue(src string, pos int) (ret int, v types.JsonState) {
func decodeValue(src string, pos int, skipnum bool) (ret int, v types.JsonState) {
pos = skipBlank(src, pos)
if pos < 0 {
return pos, types.JsonState{Vt: types.ValueType(pos)}
@ -256,20 +256,30 @@ func decodeValue(src string, pos int) (ret int, v types.JsonState) {
}
return ret, types.JsonState{Vt: types.V_FALSE}
case '-', '+', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
var iv int64
ret, iv, _ = decodeInt64(src, pos)
if ret >= 0 {
return ret, types.JsonState{Vt: types.V_INTEGER, Iv: iv, Ep: pos}
} else if ret != -int(types.ERR_INVALID_NUMBER_FMT) {
return ret, types.JsonState{Vt: types.ValueType(ret)}
}
var fv float64
ret, fv, _ = decodeFloat64(src, pos)
if ret >= 0 {
return ret, types.JsonState{Vt: types.V_DOUBLE, Dv: fv, Ep: pos}
if skipnum {
ret = skipNumber(src, pos)
if ret >= 0 {
return ret, types.JsonState{Vt: types.V_DOUBLE, Iv: 0, Ep: pos}
} else {
return ret, types.JsonState{Vt: types.ValueType(ret)}
}
} else {
return ret, types.JsonState{Vt: types.ValueType(ret)}
var iv int64
ret, iv, _ = decodeInt64(src, pos)
if ret >= 0 {
return ret, types.JsonState{Vt: types.V_INTEGER, Iv: iv, Ep: pos}
} else if ret != -int(types.ERR_INVALID_NUMBER_FMT) {
return ret, types.JsonState{Vt: types.ValueType(ret)}
}
var fv float64
ret, fv, _ = decodeFloat64(src, pos)
if ret >= 0 {
return ret, types.JsonState{Vt: types.V_DOUBLE, Dv: fv, Ep: pos}
} else {
return ret, types.JsonState{Vt: types.ValueType(ret)}
}
}
default:
return -int(types.ERR_INVALID_CHAR), types.JsonState{Vt:-types.ValueType(types.ERR_INVALID_CHAR)}
}

@ -19,8 +19,6 @@ package ast
import (
`sync`
`unicode/utf8`
`github.com/bytedance/sonic/internal/rt`
)
const (
@ -165,18 +163,18 @@ func (self *Node) encodeFalse(buf *[]byte) error {
}
func (self *Node) encodeNumber(buf *[]byte) error {
str := rt.StrFrom(self.p, self.v)
str := self.toString()
*buf = append(*buf, str...)
return nil
}
func (self *Node) encodeString(buf *[]byte) error {
if self.v == 0 {
if self.l == 0 {
*buf = append(*buf, '"', '"')
return nil
}
quote(buf, rt.StrFrom(self.p, self.v))
quote(buf, self.toString())
return nil
}
@ -195,16 +193,28 @@ func (self *Node) encodeArray(buf *[]byte) error {
*buf = append(*buf, '[')
var p = (*Node)(self.p)
err := p.encode(buf)
if err != nil {
return err
var s = (*linkedNodes)(self.p)
var started bool
if nb > 0 {
n := s.At(0)
if n.Exists() {
if err := n.encode(buf); err != nil {
return err
}
started = true
}
}
for i := 1; i < nb; i++ {
*buf = append(*buf, ',')
p = p.unsafe_next()
err := p.encode(buf)
if err != nil {
n := s.At(i)
if !n.Exists() {
continue
}
if started {
*buf = append(*buf, ',')
}
started = true
if err := n.encode(buf); err != nil {
return err
}
}
@ -240,16 +250,28 @@ func (self *Node) encodeObject(buf *[]byte) error {
*buf = append(*buf, '{')
var p = (*Pair)(self.p)
err := p.encode(buf)
if err != nil {
return err
var s = (*linkedPairs)(self.p)
var started bool
if nb > 0 {
n := s.At(0)
if n.Value.Exists() {
if err := n.encode(buf); err != nil {
return err
}
started = true
}
}
for i := 1; i < nb; i++ {
*buf = append(*buf, ',')
p = p.unsafe_next()
err := p.encode(buf)
if err != nil {
n := s.At(i)
if !n.Value.Exists() {
continue
}
if started {
*buf = append(*buf, ',')
}
started = true
if err := n.encode(buf); err != nil {
return err
}
}

@ -8,23 +8,55 @@ import (
`github.com/bytedance/sonic/internal/native/types`
)
func (self *Parser) syntaxError(err types.ParsingError) SyntaxError {
return SyntaxError{
Pos : self.p,
Src : self.s,
Code: err,
func newError(err types.ParsingError, msg string) *Node {
return &Node{
t: V_ERROR,
l: uint(err),
p: unsafe.Pointer(&msg),
}
}
// Error returns error message if the node is invalid
func (self Node) Error() string {
if self.t != V_ERROR {
return ""
} else {
return *(*string)(self.p)
}
}
func newSyntaxError(err SyntaxError) *Node {
msg := err.Description()
return &Node{
t: V_ERROR,
v: int64(err.Code),
l: uint(err.Code),
p: unsafe.Pointer(&msg),
}
}
func (self *Parser) syntaxError(err types.ParsingError) SyntaxError {
return SyntaxError{
Pos : self.p,
Src : self.s,
Code: err,
}
}
func unwrapError(err error) *Node {
if se, ok := err.(*Node); ok {
return se
}else if sse, ok := err.(Node); ok {
return &sse
} else {
msg := err.Error()
return &Node{
t: V_ERROR,
p: unsafe.Pointer(&msg),
}
}
}
type SyntaxError struct {
Pos int
Src string

@ -132,22 +132,22 @@ type Scanner func(path Sequence, node *Node) bool
func (self *Node) ForEach(sc Scanner) error {
switch self.itype() {
case types.V_ARRAY:
ns, err := self.UnsafeArray()
ns, err := self.unsafeArray()
if err != nil {
return err
}
for i := range ns {
if !sc(Sequence{i, nil}, &ns[i]) {
for i:=0; i<ns.Len(); i++ {
if !sc(Sequence{i, nil}, ns.At(i)) {
return err
}
}
case types.V_OBJECT:
ns, err := self.UnsafeMap()
ns, err := self.unsafeMap()
if err != nil {
return err
}
for i := range ns {
if !sc(Sequence{i, &ns[i].Key}, &ns[i].Value) {
for i:=0; i<ns.Len(); i++ {
if !sc(Sequence{i, &ns.At(i).Key}, &ns.At(i).Value) {
return err
}
}
@ -156,9 +156,3 @@ func (self *Node) ForEach(sc Scanner) error {
}
return self.Check()
}
type PairSlice []Pair
func (self PairSlice) Sort() {
radixQsort(self, 0, maxDepth(len(self)))
}

@ -51,12 +51,12 @@ const (
const (
V_NONE = 0
V_ERROR = 1
V_NULL = 2
V_TRUE = 3
V_FALSE = 4
V_ARRAY = 5
V_OBJECT = 6
V_STRING = 7
V_NULL = int(types.V_NULL)
V_TRUE = int(types.V_TRUE)
V_FALSE = int(types.V_FALSE)
V_ARRAY = int(types.V_ARRAY)
V_OBJECT = int(types.V_OBJECT)
V_STRING = int(types.V_STRING)
V_NUMBER = int(_V_NUMBER)
V_ANY = int(_V_ANY)
)
@ -66,8 +66,8 @@ var (
)
type Node struct {
v int64
t types.ValueType
l uint
p unsafe.Pointer
}
@ -126,15 +126,6 @@ func (self *Node) Check() error {
}
}
// Error returns error message if the node is invalid
func (self Node) Error() string {
if self.t != V_ERROR {
return ""
} else {
return *(*string)(self.p)
}
}
// IsRaw returns true if node's underlying value is raw json
func (self Node) IsRaw() bool {
return self.t&_V_RAW != 0
@ -156,7 +147,7 @@ func (self *Node) Raw() (string, error) {
buf, err := self.MarshalJSON()
return rt.Mem2Str(buf), err
}
return rt.StrFrom(self.p, self.v), nil
return self.toString(), nil
}
func (self *Node) checkRaw() error {
@ -181,14 +172,14 @@ func (self *Node) Bool() (bool, error) {
case types.V_FALSE : return false, nil
case types.V_NULL : return false, nil
case _V_NUMBER :
if i, err := numberToInt64(self); err == nil {
if i, err := self.toInt64(); err == nil {
return i != 0, nil
} else if f, err := numberToFloat64(self); err == nil {
} else if f, err := self.toFloat64(); err == nil {
return f != 0, nil
} else {
return false, err
}
case types.V_STRING: return strconv.ParseBool(rt.StrFrom(self.p, self.v))
case types.V_STRING: return strconv.ParseBool(self.toString())
case _V_ANY :
any := self.packAny()
switch v := any.(type) {
@ -229,9 +220,9 @@ func (self *Node) Int64() (int64, error) {
}
switch self.t {
case _V_NUMBER, types.V_STRING :
if i, err := numberToInt64(self); err == nil {
if i, err := self.toInt64(); err == nil {
return i, nil
} else if f, err := numberToFloat64(self); err == nil {
} else if f, err := self.toFloat64(); err == nil {
return int64(f), nil
} else {
return 0, err
@ -283,7 +274,7 @@ func (self *Node) StrictInt64() (int64, error) {
return 0, err
}
switch self.t {
case _V_NUMBER : return numberToInt64(self)
case _V_NUMBER : return self.toInt64()
case _V_ANY :
any := self.packAny()
switch v := any.(type) {
@ -325,12 +316,12 @@ func (self *Node) Number() (json.Number, error) {
return json.Number(""), err
}
switch self.t {
case _V_NUMBER : return toNumber(self) , nil
case _V_NUMBER : return self.toNumber(), nil
case types.V_STRING :
if _, err := numberToInt64(self); err == nil {
return toNumber(self), nil
} else if _, err := numberToFloat64(self); err == nil {
return toNumber(self), nil
if _, err := self.toInt64(); err == nil {
return self.toNumber(), nil
} else if _, err := self.toFloat64(); err == nil {
return self.toNumber(), nil
} else {
return json.Number(""), err
}
@ -372,7 +363,7 @@ func (self *Node) StrictNumber() (json.Number, error) {
return json.Number(""), err
}
switch self.t {
case _V_NUMBER : return toNumber(self) , nil
case _V_NUMBER : return self.toNumber() , nil
case _V_ANY :
if v, ok := self.packAny().(json.Number); ok {
return v, nil
@ -394,7 +385,7 @@ func (self *Node) String() (string, error) {
case types.V_NULL : return "" , nil
case types.V_TRUE : return "true" , nil
case types.V_FALSE : return "false", nil
case types.V_STRING, _V_NUMBER : return rt.StrFrom(self.p, self.v), nil
case types.V_STRING, _V_NUMBER : return self.toString(), nil
case _V_ANY :
any := self.packAny()
switch v := any.(type) {
@ -426,7 +417,7 @@ func (self *Node) StrictString() (string, error) {
return "", err
}
switch self.t {
case types.V_STRING : return rt.StrFrom(self.p, self.v), nil
case types.V_STRING : return self.toString(), nil
case _V_ANY :
if v, ok := self.packAny().(string); ok {
return v, nil
@ -445,7 +436,7 @@ func (self *Node) Float64() (float64, error) {
return 0.0, err
}
switch self.t {
case _V_NUMBER, types.V_STRING : return numberToFloat64(self)
case _V_NUMBER, types.V_STRING : return self.toFloat64()
case types.V_TRUE : return 1.0, nil
case types.V_FALSE : return 0.0, nil
case types.V_NULL : return 0.0, nil
@ -494,7 +485,7 @@ func (self *Node) StrictFloat64() (float64, error) {
return 0.0, err
}
switch self.t {
case _V_NUMBER : return numberToFloat64(self)
case _V_NUMBER : return self.toFloat64()
case _V_ANY :
any := self.packAny()
switch v := any.(type) {
@ -509,15 +500,14 @@ func (self *Node) StrictFloat64() (float64, error) {
/** Sequencial Value Methods **/
// Len returns children count of a array|object|string node
// For partially loaded node, it also works but only counts the parsed children
// WARN: For partially loaded node, it also works but only counts the parsed children
// WARN: For ARRAY|OBJECT nodes which has been conducted `UnsetXX()`, its length WON'T change
func (self *Node) Len() (int, error) {
if err := self.checkRaw(); err != nil {
return 0, err
}
if self.t == types.V_ARRAY || self.t == types.V_OBJECT || self.t == _V_ARRAY_LAZY || self.t == _V_OBJECT_LAZY {
return int(self.v & _LEN_MASK), nil
} else if self.t == types.V_STRING {
return int(self.v), nil
if self.t == types.V_ARRAY || self.t == types.V_OBJECT || self.t == _V_ARRAY_LAZY || self.t == _V_OBJECT_LAZY || self.t == types.V_STRING {
return int(self.l), nil
} else if self.t == _V_NONE || self.t == types.V_NULL {
return 0, nil
} else {
@ -526,7 +516,7 @@ func (self *Node) Len() (int, error) {
}
func (self Node) len() int {
return int(self.v & _LEN_MASK)
return int(self.l)
}
// Cap returns malloc capacity of a array|object node for children
@ -534,19 +524,16 @@ func (self *Node) Cap() (int, error) {
if err := self.checkRaw(); err != nil {
return 0, err
}
if self.t == types.V_ARRAY || self.t == types.V_OBJECT || self.t == _V_ARRAY_LAZY || self.t == _V_OBJECT_LAZY {
return int(self.v >> _CAP_BITS), nil
} else if self.t == _V_NONE || self.t == types.V_NULL {
return 0, nil
} else {
return 0, ErrUnsupportType
switch self.t {
case types.V_ARRAY: return (*linkedNodes)(self.p).Cap(), nil
case types.V_OBJECT: return (*linkedPairs)(self.p).Cap(), nil
case _V_ARRAY_LAZY: return (*parseArrayStack)(self.p).v.Cap(), nil
case _V_OBJECT_LAZY: return (*parseObjectStack)(self.p).v.Cap(), nil
case _V_NONE, types.V_NULL: return 0, nil
default: return 0, ErrUnsupportType
}
}
func (self Node) cap() int {
return int(self.v >> _CAP_BITS)
}
// Set sets the node of given key under self, and reports if the key has existed.
//
// If self is V_NONE or V_NULL, it becomes V_OBJECT and sets the node at the key.
@ -561,20 +548,15 @@ func (self *Node) Set(key string, node Node) (bool, error) {
}
p := self.Get(key)
if !p.Exists() {
l := self.len()
c := self.cap()
if l == c {
// TODO: maybe change append size in future
c += _DEFAULT_NODE_CAP
mem := unsafe_NewArray(_PAIR_TYPE, c)
memmove(mem, self.p, _PAIR_SIZE * uintptr(l))
self.p = mem
// self must be fully-loaded here
if self.len() == 0 {
*self = newObject(new(linkedPairs))
}
v := self.pairAt(l)
v.Key = key
v.Value = node
self.setCapAndLen(c, l+1)
s := (*linkedPairs)(self.p)
s.Add(Pair{key, node})
self.l++
return false, nil
} else if err := p.Check(); err != nil {
@ -591,6 +573,7 @@ func (self *Node) SetAny(key string, val interface{}) (bool, error) {
}
// Unset remove the node of given key under object parent, and reports if the key has existed.
// WARN: After conducting `UnsetXX()`, the node's length WON'T change
func (self *Node) Unset(key string) (bool, error) {
self.must(types.V_OBJECT, "an object")
p, i := self.skipKey(key)
@ -629,6 +612,7 @@ func (self *Node) SetAnyByIndex(index int, val interface{}) (bool, error) {
}
// UnsetByIndex remove the node of given index
// WARN: After conducting `UnsetXX()`, the node's length WON'T change
func (self *Node) UnsetByIndex(index int) (bool, error) {
var p *Node
it := self.itype()
@ -665,26 +649,17 @@ func (self *Node) Add(node Node) error {
return nil
}
if err := self.should(types.V_ARRAY, "an array"); err != nil {
return err
}
if err := self.skipAllIndex(); err != nil {
s, err := self.unsafeArray()
if err != nil {
return err
}
var p rt.GoSlice
p.Cap = self.cap()
p.Len = self.len()
p.Ptr = self.p
s := *(*[]Node)(unsafe.Pointer(&p))
s = append(s, node)
self.p = unsafe.Pointer(&s[0])
self.setCapAndLen(cap(s), len(s))
s.Add(node)
self.l++
return nil
}
// SetAny wraps val with V_ANY node, and Add() the node.
func (self *Node) AddAny(val interface{}) error {
return self.Add(NewAny(val))
@ -730,6 +705,8 @@ func (self *Node) Get(key string) *Node {
// Index indexies node at given idx,
// node type CAN be either V_OBJECT or V_ARRAY
// WARN: After conducting `UnsetXX()`, the node's length WON'T change,
// thus its children's indexing WON'T change too
func (self *Node) Index(idx int) *Node {
if err := self.checkRaw(); err != nil {
return unwrapError(err)
@ -753,6 +730,8 @@ func (self *Node) Index(idx int) *Node {
// IndexPair indexies pair at given idx,
// node type MUST be either V_OBJECT
// WARN: After conducting `UnsetXX()`, the node's length WON'T change,
// thus its children's indexing WON'T change too
func (self *Node) IndexPair(idx int) *Pair {
if err := self.should(types.V_OBJECT, "an object"); err != nil {
return nil
@ -837,6 +816,8 @@ func (self *Node) MapUseNode() (map[string]Node, error) {
// MapUnsafe exports the underlying pointer to its children map
// WARN: don't use it unless you know what you are doing
//
// Deprecated: this API now returns copied nodes instead of directly reference,
func (self *Node) UnsafeMap() ([]Pair, error) {
if err := self.should(types.V_OBJECT, "an object"); err != nil {
return nil, err
@ -844,18 +825,30 @@ func (self *Node) UnsafeMap() ([]Pair, error) {
if err := self.skipAllKey(); err != nil {
return nil, err
}
s := rt.Ptr2SlicePtr(self.p, int(self.len()), self.cap())
return *(*[]Pair)(s), nil
return self.toGenericObjectUsePair()
}
func (self *Node) unsafeMap() (*linkedPairs, error) {
if err := self.should(types.V_OBJECT, "an object"); err != nil {
return nil, err
}
if err := self.skipAllKey(); err != nil {
return nil, err
}
if self.p == nil {
*self = newObject(new(linkedPairs))
}
return (*linkedPairs)(self.p), nil
}
// SortKeys sorts children of a V_OBJECT node in ascending key-order.
// If recurse is true, it recursively sorts children's children as long as a V_OBJECT node is found.
func (self *Node) SortKeys(recurse bool) (err error) {
ps, err := self.UnsafeMap()
ps, err := self.unsafeMap()
if err != nil {
return err
}
PairSlice(ps).Sort()
ps.Sort()
if recurse {
var sc Scanner
sc = func(path Sequence, node *Node) bool {
@ -936,6 +929,9 @@ func (self *Node) ArrayUseNode() ([]Node, error) {
// ArrayUnsafe exports the underlying pointer to its children array
// WARN: don't use it unless you know what you are doing
//
// Deprecated: this API now returns copied nodes instead of directly reference,
// which has no difference with ArrayUseNode
func (self *Node) UnsafeArray() ([]Node, error) {
if err := self.should(types.V_ARRAY, "an array"); err != nil {
return nil, err
@ -943,8 +939,20 @@ func (self *Node) UnsafeArray() ([]Node, error) {
if err := self.skipAllIndex(); err != nil {
return nil, err
}
s := rt.Ptr2SlicePtr(self.p, self.len(), self.cap())
return *(*[]Node)(s), nil
return self.toGenericArrayUseNode()
}
func (self *Node) unsafeArray() (*linkedNodes, error) {
if err := self.should(types.V_ARRAY, "an array"); err != nil {
return nil, err
}
if err := self.skipAllIndex(); err != nil {
return nil, err
}
if self.p == nil {
*self = newArray(new(linkedNodes))
}
return (*linkedNodes)(self.p), nil
}
// Interface loads all children under all pathes from this node,
@ -961,9 +969,9 @@ func (self *Node) Interface() (interface{}, error) {
case types.V_FALSE : return false, nil
case types.V_ARRAY : return self.toGenericArray()
case types.V_OBJECT : return self.toGenericObject()
case types.V_STRING : return rt.StrFrom(self.p, self.v), nil
case types.V_STRING : return self.toString(), nil
case _V_NUMBER :
v, err := numberToFloat64(self)
v, err := self.toFloat64()
if err != nil {
return nil, err
}
@ -1005,8 +1013,8 @@ func (self *Node) InterfaceUseNumber() (interface{}, error) {
case types.V_FALSE : return false, nil
case types.V_ARRAY : return self.toGenericArrayUseNumber()
case types.V_OBJECT : return self.toGenericObjectUseNumber()
case types.V_STRING : return rt.StrFrom(self.p, self.v), nil
case _V_NUMBER : return toNumber(self), nil
case types.V_STRING : return self.toString(), nil
case _V_NUMBER : return self.toNumber(), nil
case _V_ARRAY_LAZY :
if err := self.loadAllIndex(); err != nil {
return nil, err
@ -1114,13 +1122,14 @@ var (
_PAIR_TYPE = rt.UnpackEface(Pair{}).Type
)
func (self *Node) setCapAndLen(cap int, len int) {
if self.t == types.V_ARRAY || self.t == types.V_OBJECT || self.t == _V_ARRAY_LAZY || self.t == _V_OBJECT_LAZY {
self.v = int64(len&_LEN_MASK | cap<<_CAP_BITS)
} else {
panic("value does not have a length")
}
}
// func (self *Node) setCapAndLen(cap int, len int) {
// if self.t == types.V_ARRAY || self.t == types.V_OBJECT || self.t == _V_ARRAY_LAZY || self.t == _V_OBJECT_LAZY {
// self.l = uint32(len)
// self.c = uint32(cap)
// } else {
// panic("value does not have a length")
// }
// }
func (self *Node) unsafe_next() *Node {
return (*Node)(unsafe.Pointer(uintptr(unsafe.Pointer(self)) + _NODE_SIZE))
@ -1153,37 +1162,25 @@ func (self *Node) should(t types.ValueType, s string) error {
}
func (self *Node) nodeAt(i int) *Node {
var p = self.p
var p *linkedNodes
if self.isLazy() {
_, stack := self.getParserAndArrayStack()
p = *(*unsafe.Pointer)(unsafe.Pointer(&stack.v))
p = &stack.v
} else {
p = (*linkedNodes)(self.p)
}
return (*Node)(unsafe.Pointer(uintptr(p) + uintptr(i)*_NODE_SIZE))
return p.At(i)
}
func (self *Node) pairAt(i int) *Pair {
var p = self.p
var p *linkedPairs
if self.isLazy() {
_, stack := self.getParserAndObjectStack()
p = *(*unsafe.Pointer)(unsafe.Pointer(&stack.v))
p = &stack.v
} else {
p = (*linkedPairs)(self.p)
}
return (*Pair)(unsafe.Pointer(uintptr(p) + uintptr(i)*_PAIR_SIZE))
}
func (self *Node) getParserAndArrayStack() (*Parser, *parseArrayStack) {
stack := (*parseArrayStack)(self.p)
ret := (*rt.GoSlice)(unsafe.Pointer(&stack.v))
ret.Len = self.len()
ret.Cap = self.cap()
return &stack.parser, stack
}
func (self *Node) getParserAndObjectStack() (*Parser, *parseObjectStack) {
stack := (*parseObjectStack)(self.p)
ret := (*rt.GoSlice)(unsafe.Pointer(&stack.v))
ret.Len = self.len()
ret.Cap = self.cap()
return &stack.parser, stack
return p.At(i)
}
func (self *Node) skipAllIndex() error {
@ -1194,7 +1191,7 @@ func (self *Node) skipAllIndex() error {
parser, stack := self.getParserAndArrayStack()
parser.skipValue = true
parser.noLazy = true
*self, err = parser.decodeArray(stack.v)
*self, err = parser.decodeArray(&stack.v)
if err != 0 {
return parser.ExportError(err)
}
@ -1209,7 +1206,7 @@ func (self *Node) skipAllKey() error {
parser, stack := self.getParserAndObjectStack()
parser.skipValue = true
parser.noLazy = true
*self, err = parser.decodeObject(stack.v)
*self, err = parser.decodeObject(&stack.v)
if err != 0 {
return parser.ExportError(err)
}
@ -1223,21 +1220,16 @@ func (self *Node) skipKey(key string) (*Node, int) {
if nb > 0 {
/* linear search */
var p *Pair
var i int
if lazy {
s := (*parseObjectStack)(self.p)
p = &s.v[0]
p, i = s.v.Get(key)
} else {
p = (*Pair)(self.p)
p, i = (*linkedPairs)(self.p).Get(key)
}
if p.Key == key {
return &p.Value, 0
}
for i := 1; i < nb; i++ {
p = p.unsafe_next()
if p.Key == key {
return &p.Value, i
}
if p != nil {
return &p.Value, i
}
}
@ -1311,7 +1303,7 @@ func (self *Node) loadAllIndex() error {
var err types.ParsingError
parser, stack := self.getParserAndArrayStack()
parser.noLazy = true
*self, err = parser.decodeArray(stack.v)
*self, err = parser.decodeArray(&stack.v)
if err != 0 {
return parser.ExportError(err)
}
@ -1325,7 +1317,7 @@ func (self *Node) loadAllKey() error {
var err types.ParsingError
parser, stack := self.getParserAndObjectStack()
parser.noLazy = true
*self, err = parser.decodeObject(stack.v)
*self, err = parser.decodeObject(&stack.v)
if err != 0 {
return parser.ExportError(err)
}
@ -1333,58 +1325,36 @@ func (self *Node) loadAllKey() error {
}
func (self *Node) removeNode(i int) {
nb := self.len() - 1
node := self.nodeAt(i)
if i == nb {
self.setCapAndLen(self.cap(), nb)
*node = Node{}
if node == nil {
return
}
from := self.nodeAt(i + 1)
memmove(unsafe.Pointer(node), unsafe.Pointer(from), _NODE_SIZE * uintptr(nb - i))
last := self.nodeAt(nb)
*last = Node{}
self.setCapAndLen(self.cap(), nb)
*node = Node{}
// NOTICE: for consistency with linkedNodes, we DOSEN'T reduce size here
// self.l--
}
func (self *Node) removePair(i int) {
nb := self.len() - 1
node := self.pairAt(i)
if i == nb {
self.setCapAndLen(self.cap(), nb)
*node = Pair{}
last := self.pairAt(i)
if last == nil {
return
}
from := self.pairAt(i + 1)
memmove(unsafe.Pointer(node), unsafe.Pointer(from), _PAIR_SIZE * uintptr(nb - i))
last := self.pairAt(nb)
*last = Pair{}
self.setCapAndLen(self.cap(), nb)
// NOTICE: for consistency with linkedNodes, we DOSEN'T reduce size here
// self.l--
}
func (self *Node) toGenericArray() ([]interface{}, error) {
nb := self.len()
ret := make([]interface{}, nb)
if nb == 0 {
return ret, nil
return []interface{}{}, nil
}
ret := make([]interface{}, nb)
/* convert each item */
var p = (*Node)(self.p)
x, err := p.Interface()
if err != nil {
return nil, err
}
ret[0] = x
for i := 1; i < nb; i++ {
p = p.unsafe_next()
var s = (*linkedNodes)(self.p)
for i := 0; i < nb; i++ {
p := s.At(i)
x, err := p.Interface()
if err != nil {
return nil, err
@ -1398,21 +1368,15 @@ func (self *Node) toGenericArray() ([]interface{}, error) {
func (self *Node) toGenericArrayUseNumber() ([]interface{}, error) {
nb := self.len()
ret := make([]interface{}, nb)
if nb == 0 {
return ret, nil
return []interface{}{}, nil
}
ret := make([]interface{}, nb)
/* convert each item */
var p = (*Node)(self.p)
x, err := p.InterfaceUseNumber()
if err != nil {
return nil, err
}
ret[0] = x
for i := 1; i < nb; i++ {
p = p.unsafe_next()
var s = (*linkedNodes)(self.p)
for i := 0; i < nb; i++ {
p := s.At(i)
x, err := p.InterfaceUseNumber()
if err != nil {
return nil, err
@ -1426,45 +1390,28 @@ func (self *Node) toGenericArrayUseNumber() ([]interface{}, error) {
func (self *Node) toGenericArrayUseNode() ([]Node, error) {
var nb = self.len()
var out = make([]Node, nb)
if nb == 0 {
return out, nil
return []Node{}, nil
}
var p = (*Node)(self.p)
out[0] = *p
if err := p.Check(); err != nil {
return nil, err
}
for i := 1; i < nb; i++ {
p = p.unsafe_next()
if err := p.Check(); err != nil {
return nil, err
}
out[i] = *p
}
var s = (*linkedNodes)(self.p)
var out = make([]Node, nb)
s.ToSlice(out)
return out, nil
}
func (self *Node) toGenericObject() (map[string]interface{}, error) {
nb := self.len()
ret := make(map[string]interface{}, nb)
if nb == 0 {
return ret, nil
return map[string]interface{}{}, nil
}
ret := make(map[string]interface{}, nb)
/* convert each item */
var p = (*Pair)(self.p)
x, err := p.Value.Interface()
if err != nil {
return nil, err
}
ret[p.Key] = x
for i := 1; i < nb; i++ {
p = p.unsafe_next()
var s = (*linkedPairs)(self.p)
for i := 0; i < nb; i++ {
p := s.At(i)
x, err := p.Value.Interface()
if err != nil {
return nil, err
@ -1479,21 +1426,15 @@ func (self *Node) toGenericObject() (map[string]interface{}, error) {
func (self *Node) toGenericObjectUseNumber() (map[string]interface{}, error) {
nb := self.len()
ret := make(map[string]interface{}, nb)
if nb == 0 {
return ret, nil
return map[string]interface{}{}, nil
}
ret := make(map[string]interface{}, nb)
/* convert each item */
var p = (*Pair)(self.p)
x, err := p.Value.InterfaceUseNumber()
if err != nil {
return nil, err
}
ret[p.Key] = x
for i := 1; i < nb; i++ {
p = p.unsafe_next()
var s = (*linkedPairs)(self.p)
for i := 0; i < nb; i++ {
p := s.At(i)
x, err := p.Value.InterfaceUseNumber()
if err != nil {
return nil, err
@ -1507,25 +1448,28 @@ func (self *Node) toGenericObjectUseNumber() (map[string]interface{}, error) {
func (self *Node) toGenericObjectUseNode() (map[string]Node, error) {
var nb = self.len()
var out = make(map[string]Node, nb)
if nb == 0 {
return out, nil
return map[string]Node{}, nil
}
var p = (*Pair)(self.p)
out[p.Key] = p.Value
if err := p.Value.Check(); err != nil {
return nil, err
}
var s = (*linkedPairs)(self.p)
var out = make(map[string]Node, nb)
s.ToMap(out)
for i := 1; i < nb; i++ {
p = p.unsafe_next()
if err := p.Value.Check(); err != nil {
return nil, err
}
out[p.Key] = p.Value
/* all done */
return out, nil
}
func (self *Node) toGenericObjectUsePair() ([]Pair, error) {
var nb = self.len()
if nb == 0 {
return []Pair{}, nil
}
var s = (*linkedPairs)(self.p)
var out = make([]Pair, nb)
s.ToSlice(out)
/* all done */
return out, nil
}
@ -1536,15 +1480,12 @@ var (
nullNode = Node{t: types.V_NULL}
trueNode = Node{t: types.V_TRUE}
falseNode = Node{t: types.V_FALSE}
emptyArrayNode = Node{t: types.V_ARRAY}
emptyObjectNode = Node{t: types.V_OBJECT}
)
// NewRaw creates a node of raw json.
// If the input json is invalid, NewRaw returns a error Node.
func NewRaw(json string) Node {
parser := NewParser(json)
parser := NewParserObj(json)
start, err := parser.skip()
if err != 0 {
return *newError(err, err.Message())
@ -1567,7 +1508,6 @@ func NewAny(any interface{}) Node {
default:
return Node{
t: _V_ANY,
v: 0,
p: unsafe.Pointer(&any),
}
}
@ -1585,7 +1525,6 @@ func NewBytes(src []byte) Node {
// NewNull creates a node of type V_NULL
func NewNull() Node {
return Node{
v: 0,
p: nil,
t: types.V_NULL,
}
@ -1600,7 +1539,6 @@ func NewBool(v bool) Node {
t = types.V_TRUE
}
return Node{
v: 0,
p: nil,
t: t,
}
@ -1610,26 +1548,30 @@ func NewBool(v bool) Node {
// v must be a decimal string complying with RFC8259
func NewNumber(v string) Node {
return Node{
v: int64(len(v) & _LEN_MASK),
l: uint(len(v)),
p: rt.StrPtr(v),
t: _V_NUMBER,
}
}
func toNumber(node *Node) json.Number {
return json.Number(rt.StrFrom(node.p, node.v))
func (node Node) toNumber() json.Number {
return json.Number(rt.StrFrom(node.p, int64(node.l)))
}
func numberToFloat64(node *Node) (float64, error) {
ret,err := toNumber(node).Float64()
func (self Node) toString() string {
return rt.StrFrom(self.p, int64(self.l))
}
func (node Node) toFloat64() (float64, error) {
ret, err := node.toNumber().Float64()
if err != nil {
return 0, err
}
return ret, nil
}
func numberToInt64(node *Node) (int64, error) {
ret,err := toNumber(node).Int64()
func (node Node) toInt64() (int64, error) {
ret,err := node.toNumber().Int64()
if err != nil {
return 0, err
}
@ -1640,7 +1582,7 @@ func newBytes(v []byte) Node {
return Node{
t: types.V_STRING,
p: mem2ptr(v),
v: int64(len(v) & _LEN_MASK),
l: uint(len(v)),
}
}
@ -1652,103 +1594,65 @@ func NewString(v string) Node {
return Node{
t: types.V_STRING,
p: rt.StrPtr(v),
v: int64(len(v) & _LEN_MASK),
l: uint(len(v)),
}
}
// NewArray creates a node of type V_ARRAY,
// using v as its underlying children
func NewArray(v []Node) Node {
s := new(linkedNodes)
s.FromSlice(v)
return newArray(s)
}
func newArray(v *linkedNodes) Node {
return Node{
t: types.V_ARRAY,
v: int64(len(v)&_LEN_MASK | cap(v)<<_CAP_BITS),
p: *(*unsafe.Pointer)(unsafe.Pointer(&v)),
l: uint(v.Len()),
p: unsafe.Pointer(v),
}
}
func (self *Node) setArray(v []Node) {
func (self *Node) setArray(v *linkedNodes) {
self.t = types.V_ARRAY
self.setCapAndLen(cap(v), len(v))
self.p = *(*unsafe.Pointer)(unsafe.Pointer(&v))
self.l = uint(v.Len())
self.p = unsafe.Pointer(v)
}
// NewObject creates a node of type V_OBJECT,
// using v as its underlying children
func NewObject(v []Pair) Node {
return Node{
t: types.V_OBJECT,
v: int64(len(v)&_LEN_MASK | cap(v)<<_CAP_BITS),
p: *(*unsafe.Pointer)(unsafe.Pointer(&v)),
}
}
func (self *Node) setObject(v []Pair) {
self.t = types.V_OBJECT
self.setCapAndLen(cap(v), len(v))
self.p = *(*unsafe.Pointer)(unsafe.Pointer(&v))
}
type parseObjectStack struct {
parser Parser
v []Pair
}
type parseArrayStack struct {
parser Parser
v []Node
s := new(linkedPairs)
s.FromSlice(v)
return newObject(s)
}
func newLazyArray(p *Parser, v []Node) Node {
s := new(parseArrayStack)
s.parser = *p
s.v = v
func newObject(v *linkedPairs) Node {
return Node{
t: _V_ARRAY_LAZY,
v: int64(len(v)&_LEN_MASK | cap(v)<<_CAP_BITS),
p: unsafe.Pointer(s),
}
}
func (self *Node) setLazyArray(p *Parser, v []Node) {
s := new(parseArrayStack)
s.parser = *p
s.v = v
self.t = _V_ARRAY_LAZY
self.setCapAndLen(cap(v), len(v))
self.p = (unsafe.Pointer)(s)
}
func newLazyObject(p *Parser, v []Pair) Node {
s := new(parseObjectStack)
s.parser = *p
s.v = v
return Node{
t: _V_OBJECT_LAZY,
v: int64(len(v)&_LEN_MASK | cap(v)<<_CAP_BITS),
p: unsafe.Pointer(s),
t: types.V_OBJECT,
l: uint(v.Len()),
p: unsafe.Pointer(v),
}
}
func (self *Node) setLazyObject(p *Parser, v []Pair) {
s := new(parseObjectStack)
s.parser = *p
s.v = v
self.t = _V_OBJECT_LAZY
self.setCapAndLen(cap(v), len(v))
self.p = (unsafe.Pointer)(s)
func (self *Node) setObject(v *linkedPairs) {
self.t = types.V_OBJECT
self.l = uint(v.Len())
self.p = unsafe.Pointer(v)
}
func newRawNode(str string, typ types.ValueType) Node {
return Node{
t: _V_RAW | typ,
p: rt.StrPtr(str),
v: int64(len(str) & _LEN_MASK),
l: uint(len(str)),
}
}
func (self *Node) parseRaw(full bool) {
raw := rt.StrFrom(self.p, self.v)
parser := NewParser(raw)
raw := self.toString()
parser := NewParserObj(raw)
if full {
parser.noLazy = true
parser.skipValue = false
@ -1760,14 +1664,6 @@ func (self *Node) parseRaw(full bool) {
}
}
func newError(err types.ParsingError, msg string) *Node {
return &Node{
t: V_ERROR,
v: int64(err),
p: unsafe.Pointer(&msg),
}
}
var typeJumpTable = [256]types.ValueType{
'"' : types.V_STRING,
'-' : _V_NUMBER,
@ -1791,18 +1687,3 @@ var typeJumpTable = [256]types.ValueType{
func switchRawType(c byte) types.ValueType {
return typeJumpTable[c]
}
func unwrapError(err error) *Node {
if se, ok := err.(*Node); ok {
return se
}else if sse, ok := err.(Node); ok {
return &sse
} else {
msg := err.Error()
return &Node{
t: V_ERROR,
v: 0,
p: unsafe.Pointer(&msg),
}
}
}

@ -18,11 +18,15 @@ package ast
import (
`fmt`
`github.com/bytedance/sonic/internal/native/types`
`github.com/bytedance/sonic/internal/rt`
)
const _DEFAULT_NODE_CAP int = 16
const (
_DEFAULT_NODE_CAP int = 8
_APPEND_GROW_SHIFT = 1
)
const (
_ERR_NOT_FOUND types.ParsingError = 33
@ -39,6 +43,7 @@ type Parser struct {
s string
noLazy bool
skipValue bool
dbuf *byte
}
/** Parser Private Methods **/
@ -107,7 +112,7 @@ func (self *Parser) lspace(sp int) int {
return sp
}
func (self *Parser) decodeArray(ret []Node) (Node, types.ParsingError) {
func (self *Parser) decodeArray(ret *linkedNodes) (Node, types.ParsingError) {
sp := self.p
ns := len(self.s)
@ -119,7 +124,7 @@ func (self *Parser) decodeArray(ret []Node) (Node, types.ParsingError) {
/* check for empty array */
if self.s[self.p] == ']' {
self.p++
return emptyArrayNode, 0
return Node{t: types.V_ARRAY}, 0
}
/* allocate array space and parse every element */
@ -149,7 +154,7 @@ func (self *Parser) decodeArray(ret []Node) (Node, types.ParsingError) {
}
/* add the value to result */
ret = append(ret, val)
ret.Add(val)
self.p = self.lspace(self.p)
/* check for EOF */
@ -160,17 +165,17 @@ func (self *Parser) decodeArray(ret []Node) (Node, types.ParsingError) {
/* check for the next character */
switch self.s[self.p] {
case ',' : self.p++
case ']' : self.p++; return NewArray(ret), 0
default:
if val.isLazy() {
return newLazyArray(self, ret), 0
}
return Node{}, types.ERR_INVALID_CHAR
case ']' : self.p++; return newArray(ret), 0
default:
// if val.isLazy() {
// return newLazyArray(self, ret), 0
// }
return Node{}, types.ERR_INVALID_CHAR
}
}
}
func (self *Parser) decodeObject(ret []Pair) (Node, types.ParsingError) {
func (self *Parser) decodeObject(ret *linkedPairs) (Node, types.ParsingError) {
sp := self.p
ns := len(self.s)
@ -182,7 +187,7 @@ func (self *Parser) decodeObject(ret []Pair) (Node, types.ParsingError) {
/* check for empty object */
if self.s[self.p] == '}' {
self.p++
return emptyObjectNode, 0
return Node{t: types.V_OBJECT}, 0
}
/* decode each pair */
@ -235,7 +240,8 @@ func (self *Parser) decodeObject(ret []Pair) (Node, types.ParsingError) {
}
/* add the value to result */
ret = append(ret, Pair{Key: key, Value: val})
// FIXME: ret's address may change here, thus previous referred node in ret may be invalid !!
ret.Add(Pair{Key: key, Value: val})
self.p = self.lspace(self.p)
/* check for EOF */
@ -246,11 +252,11 @@ func (self *Parser) decodeObject(ret []Pair) (Node, types.ParsingError) {
/* check for the next character */
switch self.s[self.p] {
case ',' : self.p++
case '}' : self.p++; return NewObject(ret), 0
case '}' : self.p++; return newObject(ret), 0
default:
if val.isLazy() {
return newLazyObject(self, ret), 0
}
// if val.isLazy() {
// return newLazyObject(self, ret), 0
// }
return Node{}, types.ERR_INVALID_CHAR
}
}
@ -290,15 +296,23 @@ func (self *Parser) Parse() (Node, types.ParsingError) {
case types.V_FALSE : return falseNode, 0
case types.V_STRING : return self.decodeString(val.Iv, val.Ep)
case types.V_ARRAY:
if p := skipBlank(self.s, self.p); p >= self.p && self.s[p] == ']' {
self.p = p + 1
return Node{t: types.V_ARRAY}, 0
}
if self.noLazy {
return self.decodeArray(make([]Node, 0, _DEFAULT_NODE_CAP))
return self.decodeArray(new(linkedNodes))
}
return newLazyArray(self, make([]Node, 0, _DEFAULT_NODE_CAP)), 0
return newLazyArray(self), 0
case types.V_OBJECT:
if p := skipBlank(self.s, self.p); p >= self.p && self.s[p] == '}' {
self.p = p + 1
return Node{t: types.V_OBJECT}, 0
}
if self.noLazy {
return self.decodeObject(make([]Pair, 0, _DEFAULT_NODE_CAP))
return self.decodeObject(new(linkedPairs))
}
return newLazyObject(self, make([]Pair, 0, _DEFAULT_NODE_CAP)), 0
return newLazyObject(self), 0
case types.V_DOUBLE : return NewNumber(self.s[val.Ep:self.p]), 0
case types.V_INTEGER : return NewNumber(self.s[val.Ep:self.p]), 0
default : return Node{}, types.ParsingError(-val.Vt)
@ -429,7 +443,7 @@ func (self *Node) skipNextNode() *Node {
}
parser, stack := self.getParserAndArrayStack()
ret := stack.v
ret := &stack.v
sp := parser.p
ns := len(parser.s)
@ -458,7 +472,8 @@ func (self *Node) skipNextNode() *Node {
}
/* add the value to result */
ret = append(ret, val)
ret.Add(val)
self.l++
parser.p = parser.lspace(parser.p)
/* check for EOF */
@ -470,12 +485,11 @@ func (self *Node) skipNextNode() *Node {
switch parser.s[parser.p] {
case ',':
parser.p++
self.setLazyArray(parser, ret)
return &ret[len(ret)-1]
return ret.At(ret.Len()-1)
case ']':
parser.p++
self.setArray(ret)
return &ret[len(ret)-1]
return ret.At(ret.Len()-1)
default:
return newSyntaxError(parser.syntaxError(types.ERR_INVALID_CHAR))
}
@ -487,7 +501,7 @@ func (self *Node) skipNextPair() (*Pair) {
}
parser, stack := self.getParserAndObjectStack()
ret := stack.v
ret := &stack.v
sp := parser.p
ns := len(parser.s)
@ -541,7 +555,8 @@ func (self *Node) skipNextPair() (*Pair) {
}
/* add the value to result */
ret = append(ret, Pair{Key: key, Value: val})
ret.Add(Pair{Key: key, Value: val})
self.l++
parser.p = parser.lspace(parser.p)
/* check for EOF */
@ -553,12 +568,11 @@ func (self *Node) skipNextPair() (*Pair) {
switch parser.s[parser.p] {
case ',':
parser.p++
self.setLazyObject(parser, ret)
return &ret[len(ret)-1]
return ret.At(ret.Len()-1)
case '}':
parser.p++
self.setObject(ret)
return &ret[len(ret)-1]
return ret.At(ret.Len()-1)
default:
return &Pair{key, *newSyntaxError(parser.syntaxError(types.ERR_INVALID_CHAR))}
}
@ -601,10 +615,30 @@ func LoadsUseNumber(src string) (int, interface{}, error) {
}
}
// NewParser returns pointer of new allocated parser
func NewParser(src string) *Parser {
return &Parser{s: src}
}
// NewParser returns new allocated parser
func NewParserObj(src string) Parser {
return Parser{s: src}
}
// decodeNumber controls if parser decodes the number values instead of skip them
// WARN: once you set decodeNumber(true), please set decodeNumber(false) before you drop the parser
// otherwise the memory CANNOT be reused
func (self *Parser) decodeNumber(decode bool) {
if !decode && self.dbuf != nil {
types.FreeDbuf(self.dbuf)
self.dbuf = nil
return
}
if decode && self.dbuf == nil {
self.dbuf = types.NewDbuf()
}
}
// ExportError converts types.ParsingError to std Error
func (self *Parser) ExportError(err types.ParsingError) error {
if err == _ERR_NOT_FOUND {

@ -1,206 +0,0 @@
/*
* Copyright 2021 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ast
// Algorithm 3-way Radix Quicksort, d means the radix.
// Reference: https://algs4.cs.princeton.edu/51radix/Quick3string.java.html
func radixQsort(kvs PairSlice, d, maxDepth int) {
for len(kvs) > 11 {
// To avoid the worst case of quickSort (time: O(n^2)), use introsort here.
// Reference: https://en.wikipedia.org/wiki/Introsort and
// https://github.com/golang/go/issues/467
if maxDepth == 0 {
heapSort(kvs, 0, len(kvs))
return
}
maxDepth--
p := pivot(kvs, d)
lt, i, gt := 0, 0, len(kvs)
for i < gt {
c := byteAt(kvs[i].Key, d)
if c < p {
swap(kvs, lt, i)
i++
lt++
} else if c > p {
gt--
swap(kvs, i, gt)
} else {
i++
}
}
// kvs[0:lt] < v = kvs[lt:gt] < kvs[gt:len(kvs)]
// Native implemention:
// radixQsort(kvs[:lt], d, maxDepth)
// if p > -1 {
// radixQsort(kvs[lt:gt], d+1, maxDepth)
// }
// radixQsort(kvs[gt:], d, maxDepth)
// Optimize as follows: make recursive calls only for the smaller parts.
// Reference: https://www.geeksforgeeks.org/quicksort-tail-call-optimization-reducing-worst-case-space-log-n/
if p == -1 {
if lt > len(kvs) - gt {
radixQsort(kvs[gt:], d, maxDepth)
kvs = kvs[:lt]
} else {
radixQsort(kvs[:lt], d, maxDepth)
kvs = kvs[gt:]
}
} else {
ml := maxThree(lt, gt-lt, len(kvs)-gt)
if ml == lt {
radixQsort(kvs[lt:gt], d+1, maxDepth)
radixQsort(kvs[gt:], d, maxDepth)
kvs = kvs[:lt]
} else if ml == gt-lt {
radixQsort(kvs[:lt], d, maxDepth)
radixQsort(kvs[gt:], d, maxDepth)
kvs = kvs[lt:gt]
d += 1
} else {
radixQsort(kvs[:lt], d, maxDepth)
radixQsort(kvs[lt:gt], d+1, maxDepth)
kvs = kvs[gt:]
}
}
}
insertRadixSort(kvs, d)
}
func insertRadixSort(kvs PairSlice, d int) {
for i := 1; i < len(kvs); i++ {
for j := i; j > 0 && lessFrom(kvs[j].Key, kvs[j-1].Key, d); j-- {
swap(kvs, j, j-1)
}
}
}
func pivot(kvs PairSlice, d int) int {
m := len(kvs) >> 1
if len(kvs) > 40 {
// Tukey's ``Ninther,'' median of three mediankvs of three.
t := len(kvs) / 8
return medianThree(
medianThree(byteAt(kvs[0].Key, d), byteAt(kvs[t].Key, d), byteAt(kvs[2*t].Key, d)),
medianThree(byteAt(kvs[m].Key, d), byteAt(kvs[m-t].Key, d), byteAt(kvs[m+t].Key, d)),
medianThree(byteAt(kvs[len(kvs)-1].Key, d),
byteAt(kvs[len(kvs)-1-t].Key, d),
byteAt(kvs[len(kvs)-1-2*t].Key, d)))
}
return medianThree(byteAt(kvs[0].Key, d), byteAt(kvs[m].Key, d), byteAt(kvs[len(kvs)-1].Key, d))
}
func medianThree(i, j, k int) int {
if i > j {
i, j = j, i
} // i < j
if k < i {
return i
}
if k > j {
return j
}
return k
}
func maxThree(i, j, k int) int {
max := i
if max < j {
max = j
}
if max < k {
max = k
}
return max
}
// maxDepth returns a threshold at which quicksort should switch
// to heapsort. It returnkvs 2*ceil(lg(n+1)).
func maxDepth(n int) int {
var depth int
for i := n; i > 0; i >>= 1 {
depth++
}
return depth * 2
}
// siftDown implements the heap property on kvs[lo:hi].
// first is an offset into the array where the root of the heap lies.
func siftDown(kvs PairSlice, lo, hi, first int) {
root := lo
for {
child := 2*root + 1
if child >= hi {
break
}
if child+1 < hi && kvs[first+child].Key < kvs[first+child+1].Key {
child++
}
if kvs[first+root].Key >= kvs[first+child].Key {
return
}
swap(kvs, first+root, first+child)
root = child
}
}
func heapSort(kvs PairSlice, a, b int) {
first := a
lo := 0
hi := b - a
// Build heap with the greatest element at top.
for i := (hi - 1) / 2; i >= 0; i-- {
siftDown(kvs, i, hi, first)
}
// Pop elements, the largest first, into end of kvs.
for i := hi - 1; i >= 0; i-- {
swap(kvs, first, first+i)
siftDown(kvs, lo, i, first)
}
}
// Note that Pair.Key is NOT pointed to Pair.m when map key is integer after swap
func swap(kvs PairSlice, a, b int) {
kvs[a].Key, kvs[b].Key = kvs[b].Key, kvs[a].Key
kvs[a].Value, kvs[b].Value = kvs[b].Value, kvs[a].Value
}
// Compare two strings from the pos d.
func lessFrom(a, b string, d int) bool {
l := len(a)
if l > len(b) {
l = len(b)
}
for i := d; i < l; i++ {
if a[i] == b[i] {
continue
}
return a[i] < b[i]
}
return len(a) < len(b)
}
func byteAt(b string, p int) int {
if p < len(b) {
return int(b[p])
}
return -1
}

@ -0,0 +1,315 @@
/*
* Copyright 2021 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ast
import (
`encoding/json`
`github.com/bytedance/sonic/internal/native/types`
)
// Visitor handles the callbacks during preorder traversal of a JSON AST.
//
// According to the JSON RFC8259, a JSON AST can be defined by
// the following rules without seperator / whitespace tokens.
//
// JSON-AST = value
// value = false / null / true / object / array / number / string
// object = begin-object [ member *( member ) ] end-object
// member = string value
// array = begin-array [ value *( value ) ] end-array
//
type Visitor interface {
// OnNull handles a JSON null value.
OnNull() error
// OnBool handles a JSON true / false value.
OnBool(v bool) error
// OnString handles a JSON string value.
OnString(v string) error
// OnInt64 handles a JSON number value with int64 type.
OnInt64(v int64, n json.Number) error
// OnFloat64 handles a JSON number value with float64 type.
OnFloat64(v float64, n json.Number) error
// OnObjectBegin handles the beginning of a JSON object value with a
// suggested capacity that can be used to make your custom object container.
//
// After this point the visitor will receive a sequence of callbacks like
// [string, value, string, value, ......, ObjectEnd].
//
// Note:
// 1. This is a recursive definition which means the value can
// also be a JSON object / array described by a sequence of callbacks.
// 2. The suggested capacity will be 0 if current object is empty.
// 3. Currently sonic use a fixed capacity for non-empty object (keep in
// sync with ast.Node) which might not be very suitable. This may be
// improved in future version.
OnObjectBegin(capacity int) error
// OnObjectKey handles a JSON object key string in member.
OnObjectKey(key string) error
// OnObjectEnd handles the ending of a JSON object value.
OnObjectEnd() error
// OnArrayBegin handles the beginning of a JSON array value with a
// suggested capacity that can be used to make your custom array container.
//
// After this point the visitor will receive a sequence of callbacks like
// [value, value, value, ......, ArrayEnd].
//
// Note:
// 1. This is a recursive definition which means the value can
// also be a JSON object / array described by a sequence of callbacks.
// 2. The suggested capacity will be 0 if current array is empty.
// 3. Currently sonic use a fixed capacity for non-empty array (keep in
// sync with ast.Node) which might not be very suitable. This may be
// improved in future version.
OnArrayBegin(capacity int) error
// OnArrayEnd handles the ending of a JSON array value.
OnArrayEnd() error
}
// VisitorOptions contains all Visitor's options. The default value is an
// empty VisitorOptions{}.
type VisitorOptions struct {
// OnlyNumber indicates parser to directly return number value without
// conversion, then the first argument of OnInt64 / OnFloat64 will always
// be zero.
OnlyNumber bool
}
var defaultVisitorOptions = &VisitorOptions{}
// Preorder decodes the whole JSON string and callbacks each AST node to visitor
// during preorder traversal. Any visitor method with an error returned will
// break the traversal and the given error will be directly returned. The opts
// argument can be reused after every call.
func Preorder(str string, visitor Visitor, opts *VisitorOptions) error {
if opts == nil {
opts = defaultVisitorOptions
}
// process VisitorOptions first to guarantee that all options will be
// constant during decoding and make options more readable.
var (
optDecodeNumber = !opts.OnlyNumber
)
tv := &traverser{
parser: Parser{
s: str,
noLazy: true,
skipValue: false,
},
visitor: visitor,
}
if optDecodeNumber {
tv.parser.decodeNumber(true)
}
err := tv.decodeValue()
if optDecodeNumber {
tv.parser.decodeNumber(false)
}
return err
}
type traverser struct {
parser Parser
visitor Visitor
}
// NOTE: keep in sync with (*Parser).Parse method.
func (self *traverser) decodeValue() error {
switch val := self.parser.decodeValue(); val.Vt {
case types.V_EOF:
return types.ERR_EOF
case types.V_NULL:
return self.visitor.OnNull()
case types.V_TRUE:
return self.visitor.OnBool(true)
case types.V_FALSE:
return self.visitor.OnBool(false)
case types.V_STRING:
return self.decodeString(val.Iv, val.Ep)
case types.V_DOUBLE:
return self.visitor.OnFloat64(val.Dv,
json.Number(self.parser.s[val.Ep:self.parser.p]))
case types.V_INTEGER:
return self.visitor.OnInt64(val.Iv,
json.Number(self.parser.s[val.Ep:self.parser.p]))
case types.V_ARRAY:
return self.decodeArray()
case types.V_OBJECT:
return self.decodeObject()
default:
return types.ParsingError(-val.Vt)
}
}
// NOTE: keep in sync with (*Parser).decodeArray method.
func (self *traverser) decodeArray() error {
sp := self.parser.p
ns := len(self.parser.s)
/* check for EOF */
self.parser.p = self.parser.lspace(sp)
if self.parser.p >= ns {
return types.ERR_EOF
}
/* check for empty array */
if self.parser.s[self.parser.p] == ']' {
self.parser.p++
if err := self.visitor.OnArrayBegin(0); err != nil {
return err
}
return self.visitor.OnArrayEnd()
}
/* allocate array space and parse every element */
if err := self.visitor.OnArrayBegin(_DEFAULT_NODE_CAP); err != nil {
return err
}
for {
/* decode the value */
if err := self.decodeValue(); err != nil {
return err
}
self.parser.p = self.parser.lspace(self.parser.p)
/* check for EOF */
if self.parser.p >= ns {
return types.ERR_EOF
}
/* check for the next character */
switch self.parser.s[self.parser.p] {
case ',':
self.parser.p++
case ']':
self.parser.p++
return self.visitor.OnArrayEnd()
default:
return types.ERR_INVALID_CHAR
}
}
}
// NOTE: keep in sync with (*Parser).decodeObject method.
func (self *traverser) decodeObject() error {
sp := self.parser.p
ns := len(self.parser.s)
/* check for EOF */
self.parser.p = self.parser.lspace(sp)
if self.parser.p >= ns {
return types.ERR_EOF
}
/* check for empty object */
if self.parser.s[self.parser.p] == '}' {
self.parser.p++
if err := self.visitor.OnObjectBegin(0); err != nil {
return err
}
return self.visitor.OnObjectEnd()
}
/* allocate object space and decode each pair */
if err := self.visitor.OnObjectBegin(_DEFAULT_NODE_CAP); err != nil {
return err
}
for {
var njs types.JsonState
var err types.ParsingError
/* decode the key */
if njs = self.parser.decodeValue(); njs.Vt != types.V_STRING {
return types.ERR_INVALID_CHAR
}
/* extract the key */
idx := self.parser.p - 1
key := self.parser.s[njs.Iv:idx]
/* check for escape sequence */
if njs.Ep != -1 {
if key, err = unquote(key); err != 0 {
return err
}
}
if err := self.visitor.OnObjectKey(key); err != nil {
return err
}
/* expect a ':' delimiter */
if err = self.parser.delim(); err != 0 {
return err
}
/* decode the value */
if err := self.decodeValue(); err != nil {
return err
}
self.parser.p = self.parser.lspace(self.parser.p)
/* check for EOF */
if self.parser.p >= ns {
return types.ERR_EOF
}
/* check for the next character */
switch self.parser.s[self.parser.p] {
case ',':
self.parser.p++
case '}':
self.parser.p++
return self.visitor.OnObjectEnd()
default:
return types.ERR_INVALID_CHAR
}
}
}
// NOTE: keep in sync with (*Parser).decodeString method.
func (self *traverser) decodeString(iv int64, ep int) error {
p := self.parser.p - 1
s := self.parser.s[iv:p]
/* fast path: no escape sequence */
if ep == -1 {
return self.visitor.OnString(s)
}
/* unquote the string */
out, err := unquote(s)
if err != 0 {
return err
}
return self.visitor.OnString(out)
}

@ -1,4 +1,4 @@
// +build !amd64 go1.21
// +build !amd64 !go1.16 go1.21
/*
* Copyright 2021 ByteDance Inc.

@ -1,4 +1,4 @@
// +build amd64,go1.15,!go1.21
// +build amd64,go1.16,!go1.21
/*
* Copyright 2023 ByteDance Inc.
@ -25,6 +25,10 @@ import (
// Decoder is the decoder context object
type Decoder = decoder.Decoder
// SyntaxError represents json syntax error
type SyntaxError = decoder.SyntaxError
// MismatchTypeError represents dismatching between json and object
type MismatchTypeError = decoder.MismatchTypeError
// Options for decode.
@ -42,8 +46,6 @@ const (
// StreamDecoder is the decoder context object for streaming input.
type StreamDecoder = decoder.StreamDecoder
type SyntaxError = decoder.SyntaxError
var (
// NewDecoder creates a new decoder instance.
NewDecoder = decoder.NewDecoder

@ -1,4 +1,5 @@
// +build !amd64 go1.21
//go:build !amd64 || !go1.16 || go1.21
// +build !amd64 !go1.16 go1.21
/*
* Copyright 2023 ByteDance Inc.
@ -14,28 +15,34 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
*/
package decoder
import (
`encoding/json`
`bytes`
`reflect`
`github.com/bytedance/sonic/internal/native/types`
`github.com/bytedance/sonic/option`
`io`
`bytes`
`encoding/json`
`io`
`reflect`
`unsafe`
`github.com/bytedance/sonic/internal/native/types`
`github.com/bytedance/sonic/option`
)
func init() {
println("WARNING: sonic only supports Go1.16~1.20 && CPU amd64, but your environment is not suitable")
}
const (
_F_use_int64 = iota
_F_use_number
_F_disable_urc
_F_disable_unknown
_F_copy_string
_F_validate_string
_F_allow_control = 31
_F_use_int64 = 0
_F_disable_urc = 2
_F_disable_unknown = 3
_F_copy_string = 4
_F_use_number = types.B_USE_NUMBER
_F_validate_string = types.B_VALIDATE_STRING
_F_allow_control = types.B_ALLOW_CONTROL
)
type Options uint64
@ -194,3 +201,17 @@ func (self *StreamDecoder) Decode(val interface{}) (err error) {
return dec.Decode(val)
}
// SyntaxError represents json syntax error
type SyntaxError json.SyntaxError
// Description
func (s SyntaxError) Description() string {
return (*json.SyntaxError)(unsafe.Pointer(&s)).Error()
}
// Error
func (s SyntaxError) Error() string {
return (*json.SyntaxError)(unsafe.Pointer(&s)).Error()
}
// MismatchTypeError represents dismatching between json and object
type MismatchTypeError json.UnmarshalTypeError

@ -1,4 +1,4 @@
// +build amd64,go1.15,!go1.21
// +build amd64,go1.16,!go1.21
/*
* Copyright 2023 ByteDance Inc.

@ -1,4 +1,4 @@
// +build !amd64 go1.21
// +build !amd64 !go1.16 go1.21
/*
* Copyright 2023 ByteDance Inc.
@ -27,6 +27,10 @@ import (
`github.com/bytedance/sonic/option`
)
func init() {
println("WARNING: sonic only supports Go1.16~1.20 && CPU amd64, but your environment is not suitable")
}
// Options is a set of encoding options.
type Options uint64

@ -0,0 +1,197 @@
/*
* Copyright 2022 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package abi
import (
`fmt`
`reflect`
`sort`
`strings`
`github.com/bytedance/sonic/internal/rt`
)
type FunctionLayout struct {
FP uint32
Args []Parameter
Rets []Parameter
}
func (self FunctionLayout) String() string {
return self.formatFn()
}
func (self FunctionLayout) ArgSize() uint32 {
size := uintptr(0)
for _, arg := range self.Args {
size += arg.Type.Size()
}
return uint32(size)
}
type slot struct {
p bool
m uint32
}
func (self FunctionLayout) StackMap() *rt.StackMap {
var st []slot
var mb rt.StackMapBuilder
/* add arguments */
for _, v := range self.Args {
st = append(st, slot {
m: v.Mem,
p: v.IsPointer,
})
}
/* add stack-passed return values */
for _, v := range self.Rets {
if !v.InRegister {
st = append(st, slot {
m: v.Mem,
p: v.IsPointer,
})
}
}
/* sort by memory offset */
sort.Slice(st, func(i int, j int) bool {
return st[i].m < st[j].m
})
/* add the bits */
for _, v := range st {
mb.AddField(v.p)
}
/* build the stack map */
return mb.Build()
}
func (self FunctionLayout) formatFn() string {
fp := self.FP
return fmt.Sprintf("\n%#04x\nRets:\n%s\nArgs:\n%s", fp, self.formatSeq(self.Rets, &fp), self.formatSeq(self.Args, &fp))
}
func (self FunctionLayout) formatSeq(v []Parameter, fp *uint32) string {
nb := len(v)
mm := make([]string, 0, len(v))
/* convert each part */
for i := nb-1; i >=0; i-- {
*fp -= PtrSize
mm = append(mm, fmt.Sprintf("%#04x %s", *fp, v[i].String()))
}
/* join them together */
return strings.Join(mm, "\n")
}
type Frame struct {
desc *FunctionLayout
locals []bool
ccall bool
}
func NewFrame(desc *FunctionLayout, locals []bool, ccall bool) Frame {
fr := Frame{}
fr.desc = desc
fr.locals = locals
fr.ccall = ccall
return fr
}
func (self *Frame) String() string {
out := self.desc.String()
off := -8
out += fmt.Sprintf("\n%#4x [Return PC]", off)
off -= 8
out += fmt.Sprintf("\n%#4x [RBP]", off)
off -= 8
for _, v := range ReservedRegs(self.ccall) {
out += fmt.Sprintf("\n%#4x [%v]", off, v)
off -= PtrSize
}
for _, b := range self.locals {
out += fmt.Sprintf("\n%#4x [%v]", off, b)
off -= PtrSize
}
return out
}
func (self *Frame) Prev() uint32 {
return self.Size() + PtrSize
}
func (self *Frame) Size() uint32 {
return uint32(self.Offs() + PtrSize)
}
func (self *Frame) Offs() uint32 {
return uint32(len(ReservedRegs(self.ccall)) * PtrSize + len(self.locals)*PtrSize)
}
func (self *Frame) ArgPtrs() *rt.StackMap {
return self.desc.StackMap()
}
func (self *Frame) LocalPtrs() *rt.StackMap {
var m rt.StackMapBuilder
for _, b := range self.locals {
m.AddFields(len(ReservedRegs(self.ccall)), b)
}
return m.Build()
}
func alignUp(n uint32, a int) uint32 {
return (uint32(n) + uint32(a) - 1) &^ (uint32(a) - 1)
}
func isPointer(vt reflect.Type) bool {
switch vt.Kind() {
case reflect.Bool : fallthrough
case reflect.Int : fallthrough
case reflect.Int8 : fallthrough
case reflect.Int16 : fallthrough
case reflect.Int32 : fallthrough
case reflect.Int64 : fallthrough
case reflect.Uint : fallthrough
case reflect.Uint8 : fallthrough
case reflect.Uint16 : fallthrough
case reflect.Uint32 : fallthrough
case reflect.Uint64 : fallthrough
case reflect.Float32 : fallthrough
case reflect.Float64 : fallthrough
case reflect.Uintptr : return false
case reflect.Chan : fallthrough
case reflect.Func : fallthrough
case reflect.Map : fallthrough
case reflect.Ptr : fallthrough
case reflect.UnsafePointer : return true
case reflect.Complex64 : fallthrough
case reflect.Complex128 : fallthrough
case reflect.Array : fallthrough
case reflect.Struct : panic("abi: unsupported types")
default : panic("abi: invalid value type")
}
}

@ -0,0 +1,282 @@
/*
* Copyright 2022 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package abi
import (
`fmt`
`reflect`
`unsafe`
. `github.com/chenzhuoyu/iasm/x86_64`
)
const (
PtrSize = 8 // pointer size
PtrAlign = 8 // pointer alignment
)
var iregOrderC = []Register{
RDI,
RSI,
RDX,
RCX,
R8,
R9,
}
var xregOrderC = []Register{
XMM0,
XMM1,
XMM2,
XMM3,
XMM4,
XMM5,
XMM6,
XMM7,
}
var (
intType = reflect.TypeOf(0)
ptrType = reflect.TypeOf(unsafe.Pointer(nil))
)
func (self *Frame) argv(i int) *MemoryOperand {
return Ptr(RSP, int32(self.Prev() + self.desc.Args[i].Mem))
}
// spillv is used for growstack spill registers
func (self *Frame) spillv(i int) *MemoryOperand {
// remain one slot for caller return pc
return Ptr(RSP, PtrSize + int32(self.desc.Args[i].Mem))
}
func (self *Frame) retv(i int) *MemoryOperand {
return Ptr(RSP, int32(self.Prev() + self.desc.Rets[i].Mem))
}
func (self *Frame) resv(i int) *MemoryOperand {
return Ptr(RSP, int32(self.Offs() - uint32((i+1) * PtrSize)))
}
func (self *Frame) emitGrowStack(p *Program, entry *Label) {
// spill all register arguments
for i, v := range self.desc.Args {
if v.InRegister {
if v.IsFloat == floatKind64 {
p.MOVSD(v.Reg, self.spillv(i))
} else if v.IsFloat == floatKind32 {
p.MOVSS(v.Reg, self.spillv(i))
}else {
p.MOVQ(v.Reg, self.spillv(i))
}
}
}
// call runtime.morestack_noctxt
p.MOVQ(F_morestack_noctxt, R12)
p.CALLQ(R12)
// load all register arguments
for i, v := range self.desc.Args {
if v.InRegister {
if v.IsFloat == floatKind64 {
p.MOVSD(self.spillv(i), v.Reg)
} else if v.IsFloat == floatKind32 {
p.MOVSS(self.spillv(i), v.Reg)
}else {
p.MOVQ(self.spillv(i), v.Reg)
}
}
}
// jump back to the function entry
p.JMP(entry)
}
func (self *Frame) GrowStackTextSize() uint32 {
p := DefaultArch.CreateProgram()
// spill all register arguments
for i, v := range self.desc.Args {
if v.InRegister {
if v.IsFloat == floatKind64 {
p.MOVSD(v.Reg, self.spillv(i))
} else if v.IsFloat == floatKind32 {
p.MOVSS(v.Reg, self.spillv(i))
}else {
p.MOVQ(v.Reg, self.spillv(i))
}
}
}
// call runtime.morestack_noctxt
p.MOVQ(F_morestack_noctxt, R12)
p.CALLQ(R12)
// load all register arguments
for i, v := range self.desc.Args {
if v.InRegister {
if v.IsFloat == floatKind64 {
p.MOVSD(self.spillv(i), v.Reg)
} else if v.IsFloat == floatKind32 {
p.MOVSS(self.spillv(i), v.Reg)
} else {
p.MOVQ(self.spillv(i), v.Reg)
}
}
}
// jump back to the function entry
l := CreateLabel("")
p.Link(l)
p.JMP(l)
return uint32(len(p.Assemble(0)))
}
func (self *Frame) emitPrologue(p *Program) {
p.SUBQ(self.Size(), RSP)
p.MOVQ(RBP, Ptr(RSP, int32(self.Offs())))
p.LEAQ(Ptr(RSP, int32(self.Offs())), RBP)
}
func (self *Frame) emitEpilogue(p *Program) {
p.MOVQ(Ptr(RSP, int32(self.Offs())), RBP)
p.ADDQ(self.Size(), RSP)
p.RET()
}
func (self *Frame) emitReserveRegs(p *Program) {
// spill reserved registers
for i, r := range ReservedRegs(self.ccall) {
switch r.(type) {
case Register64:
p.MOVQ(r, self.resv(i))
case XMMRegister:
p.MOVSD(r, self.resv(i))
default:
panic(fmt.Sprintf("unsupported register type %t to reserve", r))
}
}
}
func (self *Frame) emitSpillPtrs(p *Program) {
// spill pointer argument registers
for i, r := range self.desc.Args {
if r.InRegister && r.IsPointer {
p.MOVQ(r.Reg, self.argv(i))
}
}
}
func (self *Frame) emitClearPtrs(p *Program) {
// spill pointer argument registers
for i, r := range self.desc.Args {
if r.InRegister && r.IsPointer {
p.MOVQ(int64(0), self.argv(i))
}
}
}
func (self *Frame) emitCallC(p *Program, addr uintptr) {
p.MOVQ(addr, RAX)
p.CALLQ(RAX)
}
type floatKind uint8
const (
notFloatKind floatKind = iota
floatKind32
floatKind64
)
type Parameter struct {
InRegister bool
IsPointer bool
IsFloat floatKind
Reg Register
Mem uint32
Type reflect.Type
}
func mkIReg(vt reflect.Type, reg Register64) (p Parameter) {
p.Reg = reg
p.Type = vt
p.InRegister = true
p.IsPointer = isPointer(vt)
return
}
func isFloat(vt reflect.Type) floatKind {
switch vt.Kind() {
case reflect.Float32:
return floatKind32
case reflect.Float64:
return floatKind64
default:
return notFloatKind
}
}
func mkXReg(vt reflect.Type, reg XMMRegister) (p Parameter) {
p.Reg = reg
p.Type = vt
p.InRegister = true
p.IsFloat = isFloat(vt)
return
}
func mkStack(vt reflect.Type, mem uint32) (p Parameter) {
p.Mem = mem
p.Type = vt
p.InRegister = false
p.IsPointer = isPointer(vt)
p.IsFloat = isFloat(vt)
return
}
func (self Parameter) String() string {
if self.InRegister {
return fmt.Sprintf("[%%%s, Pointer(%v), Float(%v)]", self.Reg, self.IsPointer, self.IsFloat)
} else {
return fmt.Sprintf("[%d(FP), Pointer(%v), Float(%v)]", self.Mem, self.IsPointer, self.IsFloat)
}
}
func CallC(addr uintptr, fr Frame, maxStack uintptr) []byte {
p := DefaultArch.CreateProgram()
stack := CreateLabel("_stack_grow")
entry := CreateLabel("_entry")
p.Link(entry)
fr.emitStackCheck(p, stack, maxStack)
fr.emitPrologue(p)
fr.emitReserveRegs(p)
fr.emitSpillPtrs(p)
fr.emitExchangeArgs(p)
fr.emitCallC(p, addr)
fr.emitExchangeRets(p)
fr.emitRestoreRegs(p)
fr.emitEpilogue(p)
p.Link(stack)
fr.emitGrowStack(p, entry)
return p.Assemble(0)
}
func (self *Frame) emitDebug(p *Program) {
p.INT(3)
}

@ -0,0 +1,182 @@
//go:build !go1.17
// +build !go1.17
/*
* Copyright 2022 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package abi
import (
`fmt`
`reflect`
`runtime`
. `github.com/chenzhuoyu/iasm/x86_64`
)
func ReservedRegs(callc bool) []Register {
return nil
}
func salloc(p []Parameter, sp uint32, vt reflect.Type) (uint32, []Parameter) {
switch vt.Kind() {
case reflect.Bool : return sp + 8, append(p, mkStack(reflect.TypeOf(false), sp))
case reflect.Int : return sp + 8, append(p, mkStack(intType, sp))
case reflect.Int8 : return sp + 8, append(p, mkStack(reflect.TypeOf(int8(0)), sp))
case reflect.Int16 : return sp + 8, append(p, mkStack(reflect.TypeOf(int16(0)), sp))
case reflect.Int32 : return sp + 8, append(p, mkStack(reflect.TypeOf(int32(0)), sp))
case reflect.Int64 : return sp + 8, append(p, mkStack(reflect.TypeOf(int64(0)), sp))
case reflect.Uint : return sp + 8, append(p, mkStack(reflect.TypeOf(uint(0)), sp))
case reflect.Uint8 : return sp + 8, append(p, mkStack(reflect.TypeOf(uint8(0)), sp))
case reflect.Uint16 : return sp + 8, append(p, mkStack(reflect.TypeOf(uint16(0)), sp))
case reflect.Uint32 : return sp + 8, append(p, mkStack(reflect.TypeOf(uint32(0)), sp))
case reflect.Uint64 : return sp + 8, append(p, mkStack(reflect.TypeOf(uint64(0)), sp))
case reflect.Uintptr : return sp + 8, append(p, mkStack(reflect.TypeOf(uintptr(0)), sp))
case reflect.Float32 : return sp + 8, append(p, mkStack(reflect.TypeOf(float32(0)), sp))
case reflect.Float64 : return sp + 8, append(p, mkStack(reflect.TypeOf(float64(0)), sp))
case reflect.Complex64 : panic("abi: go116: not implemented: complex64")
case reflect.Complex128 : panic("abi: go116: not implemented: complex128")
case reflect.Array : panic("abi: go116: not implemented: arrays")
case reflect.Chan : return sp + 8, append(p, mkStack(reflect.TypeOf((chan int)(nil)), sp))
case reflect.Func : return sp + 8, append(p, mkStack(reflect.TypeOf((func())(nil)), sp))
case reflect.Map : return sp + 8, append(p, mkStack(reflect.TypeOf((map[int]int)(nil)), sp))
case reflect.Ptr : return sp + 8, append(p, mkStack(reflect.TypeOf((*int)(nil)), sp))
case reflect.UnsafePointer : return sp + 8, append(p, mkStack(ptrType, sp))
case reflect.Interface : return sp + 16, append(p, mkStack(ptrType, sp), mkStack(ptrType, sp + 8))
case reflect.Slice : return sp + 24, append(p, mkStack(ptrType, sp), mkStack(intType, sp + 8), mkStack(intType, sp + 16))
case reflect.String : return sp + 16, append(p, mkStack(ptrType, sp), mkStack(intType, sp + 8))
case reflect.Struct : panic("abi: go116: not implemented: structs")
default : panic("abi: invalid value type")
}
}
func NewFunctionLayout(ft reflect.Type) FunctionLayout {
var sp uint32
var fn FunctionLayout
/* assign every arguments */
for i := 0; i < ft.NumIn(); i++ {
sp, fn.Args = salloc(fn.Args, sp, ft.In(i))
}
/* assign every return value */
for i := 0; i < ft.NumOut(); i++ {
sp, fn.Rets = salloc(fn.Rets, sp, ft.Out(i))
}
/* update function ID and stack pointer */
fn.FP = sp
return fn
}
func (self *Frame) emitExchangeArgs(p *Program) {
iregArgs, xregArgs := 0, 0
for _, v := range self.desc.Args {
if v.IsFloat != notFloatKind {
xregArgs += 1
} else {
iregArgs += 1
}
}
if iregArgs > len(iregOrderC) {
panic("too many arguments, only support at most 6 integer arguments now")
}
if xregArgs > len(xregOrderC) {
panic("too many arguments, only support at most 8 float arguments now")
}
ic, xc := iregArgs, xregArgs
for i := 0; i < len(self.desc.Args); i++ {
arg := self.desc.Args[i]
if arg.IsFloat == floatKind64 {
p.MOVSD(self.argv(i), xregOrderC[xregArgs - xc])
xc -= 1
} else if arg.IsFloat == floatKind32 {
p.MOVSS(self.argv(i), xregOrderC[xregArgs - xc])
xc -= 1
} else {
p.MOVQ(self.argv(i), iregOrderC[iregArgs - ic])
ic -= 1
}
}
}
func (self *Frame) emitStackCheck(p *Program, to *Label, maxStack uintptr) {
// get the current goroutine
switch runtime.GOOS {
case "linux" : p.MOVQ(Abs(-8), R14).FS()
case "darwin" : p.MOVQ(Abs(0x30), R14).GS()
case "windows": break // windows always stores G pointer at R14
default : panic("unsupported operating system")
}
// check the stack guard
p.LEAQ(Ptr(RSP, -int32(self.Size() + uint32(maxStack))), RAX)
p.CMPQ(Ptr(R14, _G_stackguard0), RAX)
p.JBE(to)
}
func (self *Frame) StackCheckTextSize() uint32 {
p := DefaultArch.CreateProgram()
// get the current goroutine
switch runtime.GOOS {
case "linux" : p.MOVQ(Abs(-8), R14).FS()
case "darwin" : p.MOVQ(Abs(0x30), R14).GS()
case "windows": break // windows always stores G pointer at R14
default : panic("unsupported operating system")
}
// check the stack guard
p.LEAQ(Ptr(RSP, -int32(self.Size())), RAX)
p.CMPQ(Ptr(R14, _G_stackguard0), RAX)
l := CreateLabel("")
p.Link(l)
p.JBE(l)
return uint32(len(p.Assemble(0)))
}
func (self *Frame) emitExchangeRets(p *Program) {
if len(self.desc.Rets) > 1 {
panic("too many results, only support one result now")
}
// store result
if len(self.desc.Rets) ==1 {
if self.desc.Rets[0].IsFloat == floatKind64 {
p.MOVSD(xregOrderC[0], self.retv(0))
} else if self.desc.Rets[0].IsFloat == floatKind32 {
p.MOVSS(xregOrderC[0], self.retv(0))
} else {
p.MOVQ(RAX, self.retv(0))
}
}
}
func (self *Frame) emitRestoreRegs(p *Program) {
// load reserved registers
for i, r := range ReservedRegs(self.ccall) {
switch r.(type) {
case Register64:
p.MOVQ(self.resv(i), r)
case XMMRegister:
p.MOVSD(self.resv(i), r)
default:
panic(fmt.Sprintf("unsupported register type %t to reserve", r))
}
}
}

@ -0,0 +1,316 @@
//go:build go1.17
// +build go1.17
/*
* Copyright 2022 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** Go Internal ABI implementation
*
* This module implements the function layout algorithm described by the Go internal ABI.
* See https://github.com/golang/go/blob/master/src/cmd/compile/abi-internal.md for more info.
*/
package abi
import (
`fmt`
`reflect`
. `github.com/chenzhuoyu/iasm/x86_64`
)
/** Frame Structure of the Generated Function
FP +------------------------------+
| . . . |
| 2nd reg argument spill space |
+ 1st reg argument spill space |
| <pointer-sized alignment> |
| . . . |
| 2nd stack-assigned result |
+ 1st stack-assigned result |
| <pointer-sized alignment> |
| . . . |
| 2nd stack-assigned argument |
| 1st stack-assigned argument |
| stack-assigned receiver |
prev() +------------------------------+ (Previous Frame)
Return PC |
size() -------------------------------|
Saved RBP |
offs() -------------------------------|
1th Reserved Registers |
-------------------------------|
2th Reserved Registers |
-------------------------------|
Local Variables |
RSP -------------------------------| lower addresses
*/
const zeroRegGo = XMM15
var iregOrderGo = [...]Register64 {
RAX,// RDI
RBX,// RSI
RCX,// RDX
RDI,// RCX
RSI,// R8
R8, // R9
R9,
R10,
R11,
}
var xregOrderGo = [...]XMMRegister {
XMM0,
XMM1,
XMM2,
XMM3,
XMM4,
XMM5,
XMM6,
XMM7,
XMM8,
XMM9,
XMM10,
XMM11,
XMM12,
XMM13,
XMM14,
}
func ReservedRegs(callc bool) []Register {
if callc {
return nil
}
return []Register {
R14, // current goroutine
R15, // GOT reference
}
}
type stackAlloc struct {
s uint32
i int
x int
}
func (self *stackAlloc) reset() {
self.i, self.x = 0, 0
}
func (self *stackAlloc) ireg(vt reflect.Type) (p Parameter) {
p = mkIReg(vt, iregOrderGo[self.i])
self.i++
return
}
func (self *stackAlloc) xreg(vt reflect.Type) (p Parameter) {
p = mkXReg(vt, xregOrderGo[self.x])
self.x++
return
}
func (self *stackAlloc) stack(vt reflect.Type) (p Parameter) {
p = mkStack(vt, self.s)
self.s += uint32(vt.Size())
return
}
func (self *stackAlloc) spill(n uint32, a int) uint32 {
self.s = alignUp(self.s, a) + n
return self.s
}
func (self *stackAlloc) alloc(p []Parameter, vt reflect.Type) []Parameter {
nb := vt.Size()
vk := vt.Kind()
/* zero-sized objects are allocated on stack */
if nb == 0 {
return append(p, mkStack(intType, self.s))
}
/* check for value type */
switch vk {
case reflect.Bool : return self.valloc(p, reflect.TypeOf(false))
case reflect.Int : return self.valloc(p, intType)
case reflect.Int8 : return self.valloc(p, reflect.TypeOf(int8(0)))
case reflect.Int16 : return self.valloc(p, reflect.TypeOf(int16(0)))
case reflect.Int32 : return self.valloc(p, reflect.TypeOf(uint32(0)))
case reflect.Int64 : return self.valloc(p, reflect.TypeOf(int64(0)))
case reflect.Uint : return self.valloc(p, reflect.TypeOf(uint(0)))
case reflect.Uint8 : return self.valloc(p, reflect.TypeOf(uint8(0)))
case reflect.Uint16 : return self.valloc(p, reflect.TypeOf(uint16(0)))
case reflect.Uint32 : return self.valloc(p, reflect.TypeOf(uint32(0)))
case reflect.Uint64 : return self.valloc(p, reflect.TypeOf(uint64(0)))
case reflect.Uintptr : return self.valloc(p, reflect.TypeOf(uintptr(0)))
case reflect.Float32 : return self.valloc(p, reflect.TypeOf(float32(0)))
case reflect.Float64 : return self.valloc(p, reflect.TypeOf(float64(0)))
case reflect.Complex64 : panic("abi: go117: not implemented: complex64")
case reflect.Complex128 : panic("abi: go117: not implemented: complex128")
case reflect.Array : panic("abi: go117: not implemented: arrays")
case reflect.Chan : return self.valloc(p, reflect.TypeOf((chan int)(nil)))
case reflect.Func : return self.valloc(p, reflect.TypeOf((func())(nil)))
case reflect.Map : return self.valloc(p, reflect.TypeOf((map[int]int)(nil)))
case reflect.Ptr : return self.valloc(p, reflect.TypeOf((*int)(nil)))
case reflect.UnsafePointer : return self.valloc(p, ptrType)
case reflect.Interface : return self.valloc(p, ptrType, ptrType)
case reflect.Slice : return self.valloc(p, ptrType, intType, intType)
case reflect.String : return self.valloc(p, ptrType, intType)
case reflect.Struct : panic("abi: go117: not implemented: structs")
default : panic("abi: invalid value type")
}
}
func (self *stackAlloc) valloc(p []Parameter, vts ...reflect.Type) []Parameter {
for _, vt := range vts {
enum := isFloat(vt)
if enum != notFloatKind && self.x < len(xregOrderGo) {
p = append(p, self.xreg(vt))
} else if enum == notFloatKind && self.i < len(iregOrderGo) {
p = append(p, self.ireg(vt))
} else {
p = append(p, self.stack(vt))
}
}
return p
}
func NewFunctionLayout(ft reflect.Type) FunctionLayout {
var sa stackAlloc
var fn FunctionLayout
/* assign every arguments */
for i := 0; i < ft.NumIn(); i++ {
fn.Args = sa.alloc(fn.Args, ft.In(i))
}
/* reset the register counter, and add a pointer alignment field */
sa.reset()
/* assign every return value */
for i := 0; i < ft.NumOut(); i++ {
fn.Rets = sa.alloc(fn.Rets, ft.Out(i))
}
sa.spill(0, PtrAlign)
/* assign spill slots */
for i := 0; i < len(fn.Args); i++ {
if fn.Args[i].InRegister {
fn.Args[i].Mem = sa.spill(PtrSize, PtrAlign) - PtrSize
}
}
/* add the final pointer alignment field */
fn.FP = sa.spill(0, PtrAlign)
return fn
}
func (self *Frame) emitExchangeArgs(p *Program) {
iregArgs := make([]Parameter, 0, len(self.desc.Args))
xregArgs := 0
for _, v := range self.desc.Args {
if v.InRegister {
if v.IsFloat != notFloatKind {
xregArgs += 1
} else {
iregArgs = append(iregArgs, v)
}
} else {
panic("not support stack-assgined arguments now")
}
}
if xregArgs > len(xregOrderC) {
panic("too many arguments, only support at most 8 integer register arguments now")
}
switch len(iregArgs) {
case 0, 1, 2, 3: {
//Fast-Path: when arguments count are less than four, just exchange the registers
for i := 0; i < len(iregArgs); i++ {
p.MOVQ(iregOrderGo[i], iregOrderC[i])
}
}
case 4, 5, 6: {
// need to spill 3th ~ regArgs registers before exchange
for i := 3; i < len(iregArgs); i++ {
arg := iregArgs[i]
// pointer args have already been spilled
if !arg.IsPointer {
p.MOVQ(iregOrderGo[i], Ptr(RSP, int32(self.Prev() + arg.Mem)))
}
}
p.MOVQ(iregOrderGo[0], iregOrderC[0])
p.MOVQ(iregOrderGo[1], iregOrderC[1])
p.MOVQ(iregOrderGo[2], iregOrderC[2])
for i := 3; i < len(iregArgs); i++ {
arg := iregArgs[i]
p.MOVQ(Ptr(RSP, int32(self.Prev() + arg.Mem)), iregOrderC[i])
}
}
default:
panic("too many arguments, only support at most 6 integer register arguments now")
}
}
func (self *Frame) emitStackCheck(p *Program, to *Label, maxStack uintptr) {
p.LEAQ(Ptr(RSP, int32(-(self.Size() + uint32(maxStack)))), R12)
p.CMPQ(Ptr(R14, _G_stackguard0), R12)
p.JBE(to)
}
func (self *Frame) StackCheckTextSize() uint32 {
p := DefaultArch.CreateProgram()
p.LEAQ(Ptr(RSP, int32(-(self.Size()))), R12)
p.CMPQ(Ptr(R14, _G_stackguard0), R12)
to := CreateLabel("")
p.Link(to)
p.JBE(to)
return uint32(len(p.Assemble(0)))
}
func (self *Frame) emitExchangeRets(p *Program) {
if len(self.desc.Rets) > 1 {
panic("too many results, only support one result now")
}
// store result
if len(self.desc.Rets) == 1 && !self.desc.Rets[0].InRegister {
if self.desc.Rets[0].IsFloat == floatKind64 {
p.MOVSD(xregOrderC[0], self.retv(0))
} else if self.desc.Rets[0].IsFloat == floatKind32 {
p.MOVSS(xregOrderC[0], self.retv(0))
} else {
p.MOVQ(RAX, self.retv(0))
}
}
}
func (self *Frame) emitRestoreRegs(p *Program) {
// load reserved registers
for i, r := range ReservedRegs(self.ccall) {
switch r.(type) {
case Register64:
p.MOVQ(self.resv(i), r)
case XMMRegister:
p.MOVSD(self.resv(i), r)
default:
panic(fmt.Sprintf("unsupported register type %t to reserve", r))
}
}
// zero xmm15 for go abi
p.XORPS(zeroRegGo, zeroRegGo)
}

@ -0,0 +1,35 @@
/**
* Copyright 2023 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package abi
import (
_ `unsafe`
`github.com/bytedance/sonic/internal/rt`
)
const (
_G_stackguard0 = 0x10
)
var (
F_morestack_noctxt = uintptr(rt.FuncAddr(morestack_noctxt))
)
//go:linkname morestack_noctxt runtime.morestack_noctxt
func morestack_noctxt()

@ -30,14 +30,14 @@ import (
)
const (
_F_use_int64 = iota
_F_use_number
_F_disable_urc
_F_disable_unknown
_F_copy_string
_F_validate_string
_F_allow_control = 31
_F_use_int64 = 0
_F_disable_urc = 2
_F_disable_unknown = 3
_F_copy_string = 4
_F_use_number = types.B_USE_NUMBER
_F_validate_string = types.B_VALIDATE_STRING
_F_allow_control = types.B_ALLOW_CONTROL
)
type Options uint64

@ -29,7 +29,7 @@ const (
_MinSlice = 2
_MaxStack = 4096 // 4k slots
_MaxStackBytes = _MaxStack * _PtrBytes
_MaxDigitNums = 800 // used in atof fallback algorithm
_MaxDigitNums = types.MaxDigitNums // used in atof fallback algorithm
)
const (

@ -1,124 +0,0 @@
/*
* Copyright 2021 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package loader
import (
`reflect`
`sync`
`unsafe`
`github.com/bytedance/sonic/internal/rt`
)
//go:linkname lastmoduledatap runtime.lastmoduledatap
//goland:noinspection GoUnusedGlobalVariable
var lastmoduledatap *_ModuleData
//go:linkname moduledataverify1 runtime.moduledataverify1
func moduledataverify1(_ *_ModuleData)
// PCDATA and FUNCDATA table indexes.
//
// See funcdata.h and $GROOT/src/cmd/internal/objabi/funcdata.go.
const (
_FUNCDATA_ArgsPointerMaps = 0
_FUNCDATA_LocalsPointerMaps = 1
)
type funcInfo struct {
*_Func
datap *_ModuleData
}
//go:linkname findfunc runtime.findfunc
func findfunc(pc uintptr) funcInfo
//go:linkname funcdata runtime.funcdata
func funcdata(f funcInfo, i uint8) unsafe.Pointer
var (
modLock sync.Mutex
modList []*_ModuleData
)
var emptyByte byte
func encodeVariant(v int) []byte {
var u int
var r []byte
/* split every 7 bits */
for v > 127 {
u = v & 0x7f
v = v >> 7
r = append(r, byte(u) | 0x80)
}
/* check for last one */
if v == 0 {
return r
}
/* add the last one */
r = append(r, byte(v))
return r
}
func registerModule(mod *_ModuleData) {
modLock.Lock()
modList = append(modList, mod)
lastmoduledatap.next = mod
lastmoduledatap = mod
modLock.Unlock()
}
func stackMap(f interface{}) (args uintptr, locals uintptr) {
fv := reflect.ValueOf(f)
if fv.Kind() != reflect.Func {
panic("f must be reflect.Func kind!")
}
fi := findfunc(fv.Pointer())
return uintptr(funcdata(fi, uint8(_FUNCDATA_ArgsPointerMaps))), uintptr(funcdata(fi, uint8(_FUNCDATA_LocalsPointerMaps)))
}
var moduleCache = struct{
m map[*_ModuleData][]byte
l sync.Mutex
}{
m : make(map[*_ModuleData][]byte),
}
func cacheStackmap(argPtrs []bool, localPtrs []bool, mod *_ModuleData) (argptrs uintptr, localptrs uintptr) {
as := rt.StackMapBuilder{}
for _, b := range argPtrs {
as.AddField(b)
}
ab, _ := as.Build().MarshalBinary()
ls := rt.StackMapBuilder{}
for _, b := range localPtrs {
ls.AddField(b)
}
lb, _ := ls.Build().MarshalBinary()
cache := make([]byte, len(ab) + len(lb))
copy(cache, ab)
copy(cache[len(ab):], lb)
moduleCache.l.Lock()
moduleCache.m[mod] = cache
moduleCache.l.Unlock()
return uintptr(rt.IndexByte(cache, 0)), uintptr(rt.IndexByte(cache, len(ab)))
}

@ -1,169 +0,0 @@
// +build go1.15,!go1.16
/*
* Copyright 2021 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package loader
import (
`unsafe`
`github.com/bytedance/sonic/internal/rt`
)
type _Func struct {
entry uintptr // start pc
nameoff int32 // function name
args int32 // in/out args size
deferreturn uint32 // offset of start of a deferreturn call instruction from entry, if any.
pcsp int32
pcfile int32
pcln int32
npcdata int32
funcID uint8 // set for certain special runtime functions
_ [2]int8 // unused
nfuncdata uint8 // must be last
argptrs uintptr
localptrs uintptr
}
type _FuncTab struct {
entry uintptr
funcoff uintptr
}
type _BitVector struct {
n int32 // # of bits
bytedata *uint8
}
type _PtabEntry struct {
name int32
typ int32
}
type _TextSection struct {
vaddr uintptr // prelinked section vaddr
length uintptr // section length
baseaddr uintptr // relocated section address
}
type _ModuleData struct {
pclntable []byte
ftab []_FuncTab
filetab []uint32
findfunctab *_FindFuncBucket
minpc, maxpc uintptr
text, etext uintptr
noptrdata, enoptrdata uintptr
data, edata uintptr
bss, ebss uintptr
noptrbss, enoptrbss uintptr
end, gcdata, gcbss uintptr
types, etypes uintptr
textsectmap []_TextSection
typelinks []int32 // offsets from types
itablinks []*rt.GoItab
ptab []_PtabEntry
pluginpath string
pkghashes []byte
modulename string
modulehashes []byte
hasmain uint8 // 1 if module contains the main function, 0 otherwise
gcdatamask, gcbssmask _BitVector
typemap map[int32]*rt.GoType // offset to *_rtype in previous module
bad bool // module failed to load and should be ignored
next *_ModuleData
}
type _FindFuncBucket struct {
idx uint32
subbuckets [16]byte
}
var findFuncTab = &_FindFuncBucket {
idx: 1,
}
func registerFunction(name string, pc uintptr, textSize uintptr, fp int, args int, size uintptr, argPtrs []bool, localPtrs []bool) {
mod := new(_ModuleData)
minpc := pc
maxpc := pc + size
/* build the PC & line table */
pclnt := []byte {
0xfb, 0xff, 0xff, 0xff, // magic : 0xfffffffb
0, // pad1 : 0
0, // pad2 : 0
1, // minLC : 1
4 << (^uintptr(0) >> 63), // ptrSize : 4 << (^uintptr(0) >> 63)
}
// cache arg and local stackmap
argptrs, localptrs := cacheStackmap(argPtrs, localPtrs, mod)
/* add the function name */
noff := len(pclnt)
pclnt = append(append(pclnt, name...), 0)
/* add PCDATA */
pcsp := len(pclnt)
pclnt = append(pclnt, encodeVariant((fp + 1) << 1)...)
pclnt = append(pclnt, encodeVariant(int(size))...)
/* function entry */
fnv := _Func {
entry : pc,
nameoff : int32(noff),
args : int32(args),
pcsp : int32(pcsp),
nfuncdata : 2,
argptrs : uintptr(argptrs),
localptrs : uintptr(localptrs),
}
/* align the func to 8 bytes */
if p := len(pclnt) % 8; p != 0 {
pclnt = append(pclnt, make([]byte, 8 - p)...)
}
/* add the function descriptor */
foff := len(pclnt)
pclnt = append(pclnt, (*(*[unsafe.Sizeof(_Func{})]byte)(unsafe.Pointer(&fnv)))[:]...)
/* function table */
tab := []_FuncTab {
{entry: pc, funcoff: uintptr(foff)},
{entry: pc, funcoff: uintptr(foff)},
{entry: maxpc},
}
/* module data */
*mod = _ModuleData {
pclntable : pclnt,
ftab : tab,
findfunctab : findFuncTab,
minpc : minpc,
maxpc : maxpc,
modulename : name,
gcdata: uintptr(unsafe.Pointer(&emptyByte)),
gcbss: uintptr(unsafe.Pointer(&emptyByte)),
}
/* verify and register the new module */
moduledataverify1(mod)
registerModule(mod)
}

@ -1,175 +0,0 @@
//go:build go1.16 && !go1.18
// +build go1.16,!go1.18
/*
* Copyright 2021 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package loader
import (
`unsafe`
)
type _Func struct {
entry uintptr // start pc
nameoff int32 // function name
args int32 // in/out args size
deferreturn uint32 // offset of start of a deferreturn call instruction from entry, if any.
pcsp uint32
pcfile uint32
pcln uint32
npcdata uint32
cuOffset uint32 // runtime.cutab offset of this function's CU
funcID uint8 // set for certain special runtime functions
_ [2]byte // pad
nfuncdata uint8 // must be last
argptrs uintptr
localptrs uintptr
}
type _FuncTab struct {
entry uintptr
funcoff uintptr
}
type _PCHeader struct {
magic uint32 // 0xFFFFFFFA
pad1, pad2 uint8 // 0,0
minLC uint8 // min instruction size
ptrSize uint8 // size of a ptr in bytes
nfunc int // number of functions in the module
nfiles uint // number of entries in the file tab.
funcnameOffset uintptr // offset to the funcnametab variable from _PCHeader
cuOffset uintptr // offset to the cutab variable from _PCHeader
filetabOffset uintptr // offset to the filetab variable from _PCHeader
pctabOffset uintptr // offset to the pctab varible from _PCHeader
pclnOffset uintptr // offset to the pclntab variable from _PCHeader
}
type _BitVector struct {
n int32 // # of bits
bytedata *uint8
}
type _PtabEntry struct {
name int32
typ int32
}
type _TextSection struct {
vaddr uintptr // prelinked section vaddr
length uintptr // section length
baseaddr uintptr // relocated section address
}
type _ModuleData struct {
pcHeader *_PCHeader
funcnametab []byte
cutab []uint32
filetab []byte
pctab []byte
pclntable []_Func
ftab []_FuncTab
findfunctab *_FindFuncBucket
minpc, maxpc uintptr
text, etext uintptr
noptrdata, enoptrdata uintptr
data, edata uintptr
bss, ebss uintptr
noptrbss, enoptrbss uintptr
end, gcdata, gcbss uintptr
types, etypes uintptr
textsectmap []_TextSection
typelinks []int32
itablinks []unsafe.Pointer
ptab []_PtabEntry
pluginpath string
pkghashes []struct{}
modulename string
modulehashes []struct{}
hasmain uint8
gcdatamask, gcbssmask _BitVector
typemap map[int32]unsafe.Pointer
bad bool
next *_ModuleData
}
type _FindFuncBucket struct {
idx uint32
subbuckets [16]byte
}
var modHeader = &_PCHeader {
magic : 0xfffffffa,
minLC : 1,
nfunc : 1,
ptrSize : 4 << (^uintptr(0) >> 63),
}
var findFuncTab = &_FindFuncBucket {
idx: 1,
}
func makePCtab(fp int) []byte {
return append([]byte{0}, encodeVariant((fp + 1) << 1)...)
}
func registerFunction(name string, pc uintptr, textSize uintptr, fp int, args int, size uintptr, argPtrs []bool, localPtrs []bool) {
mod := new(_ModuleData)
minpc := pc
maxpc := pc + size
// cache arg and local stackmap
argptrs, localptrs := cacheStackmap(argPtrs, localPtrs, mod)
/* function entry */
lnt := []_Func {{
entry : pc,
nameoff : 1,
args : int32(args),
pcsp : 1,
nfuncdata : 2,
argptrs : uintptr(argptrs),
localptrs : uintptr(localptrs),
}}
/* function table */
tab := []_FuncTab {
{entry: pc},
{entry: pc},
{entry: maxpc},
}
/* module data */
*mod = _ModuleData {
pcHeader : modHeader,
funcnametab : append(append([]byte{0}, name...), 0),
pctab : append(makePCtab(fp), encodeVariant(int(size))...),
pclntable : lnt,
ftab : tab,
findfunctab : findFuncTab,
minpc : minpc,
maxpc : maxpc,
modulename : name,
gcdata: uintptr(unsafe.Pointer(&emptyByte)),
gcbss: uintptr(unsafe.Pointer(&emptyByte)),
}
/* verify and register the new module */
moduledataverify1(mod)
registerModule(mod)
}

@ -1,201 +0,0 @@
// +build go1.18,!go1.20
/*
* Copyright 2021 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package loader
import (
`unsafe`
`github.com/bytedance/sonic/internal/rt`
)
// A FuncFlag holds bits about a function.
// This list must match the list in cmd/internal/objabi/funcid.go.
type funcFlag uint8
type _Func struct {
entryOff uint32 // start pc
nameoff int32 // function name
args int32 // in/out args size
deferreturn uint32 // offset of start of a deferreturn call instruction from entry, if any.
pcsp uint32
pcfile uint32
pcln uint32
npcdata uint32
cuOffset uint32 // runtime.cutab offset of this function's CU
funcID uint8 // set for certain special runtime functions
flag funcFlag
_ [1]byte // pad
nfuncdata uint8 // must be last
argptrs uint32
localptrs uint32
}
type _FuncTab struct {
entry uint32
funcoff uint32
}
type _PCHeader struct {
magic uint32 // 0xFFFFFFF0
pad1, pad2 uint8 // 0,0
minLC uint8 // min instruction size
ptrSize uint8 // size of a ptr in bytes
nfunc int // number of functions in the module
nfiles uint // number of entries in the file tab
textStart uintptr // base for function entry PC offsets in this module, equal to moduledata.text
funcnameOffset uintptr // offset to the funcnametab variable from pcHeader
cuOffset uintptr // offset to the cutab variable from pcHeader
filetabOffset uintptr // offset to the filetab variable from pcHeader
pctabOffset uintptr // offset to the pctab variable from pcHeader
pclnOffset uintptr // offset to the pclntab variable from pcHeader
}
type _BitVector struct {
n int32 // # of bits
bytedata *uint8
}
type _PtabEntry struct {
name int32
typ int32
}
type _TextSection struct {
vaddr uintptr // prelinked section vaddr
length uintptr // section length
baseaddr uintptr // relocated section address
}
type _ModuleData struct {
pcHeader *_PCHeader
funcnametab []byte
cutab []uint32
filetab []byte
pctab []byte
pclntable []byte
ftab []_FuncTab
findfunctab *_FindFuncBucket
minpc, maxpc uintptr
text, etext uintptr
noptrdata, enoptrdata uintptr
data, edata uintptr
bss, ebss uintptr
noptrbss, enoptrbss uintptr
end, gcdata, gcbss uintptr
types, etypes uintptr
rodata uintptr
gofunc uintptr
textsectmap []_TextSection
typelinks []int32
itablinks []unsafe.Pointer
ptab []_PtabEntry
pluginpath string
pkghashes []struct{}
modulename string
modulehashes []struct{}
hasmain uint8
gcdatamask, gcbssmask _BitVector
typemap map[int32]unsafe.Pointer
bad bool
next *_ModuleData
}
type _FindFuncBucket struct {
idx uint32
subbuckets [16]byte
}
func makePCtab(fp int) []byte {
return append([]byte{0}, encodeVariant((fp + 1) << 1)...)
}
func registerFunction(name string, pc uintptr, textSize uintptr, fp int, args int, size uintptr, argPtrs []bool, localPtrs []bool) {
mod := new(_ModuleData)
minpc := pc
maxpc := pc + size
findFuncTab := make([]_FindFuncBucket, textSize/4096 + 1)
modHeader := &_PCHeader {
magic : 0xfffffff0,
minLC : 1,
nfunc : 1,
ptrSize : 4 << (^uintptr(0) >> 63),
textStart: minpc,
}
// cache arg and local stackmap
argptrs, localptrs := cacheStackmap(argPtrs, localPtrs, mod)
base := argptrs
if argptrs > localptrs {
base = localptrs
}
/* function entry */
lnt := []_Func {{
entryOff : 0,
nameoff : 1,
args : int32(args),
pcsp : 1,
nfuncdata : 2,
argptrs: uint32(argptrs - base),
localptrs: uint32(localptrs - base),
}}
nlnt := len(lnt)*int(unsafe.Sizeof(_Func{}))
plnt := unsafe.Pointer(&lnt[0])
/* function table */
ftab := []_FuncTab {
{entry : 0, funcoff : 16},
{entry : uint32(size)},
}
nftab := len(ftab)*int(unsafe.Sizeof(_FuncTab{}))
pftab := unsafe.Pointer(&ftab[0])
pclntab := make([]byte, 0, nftab + nlnt)
pclntab = append(pclntab, rt.BytesFrom(pftab, nftab, nftab)...)
pclntab = append(pclntab, rt.BytesFrom(plnt, nlnt, nlnt)...)
/* module data */
*mod = _ModuleData {
pcHeader : modHeader,
funcnametab : append(append([]byte{0}, name...), 0),
pctab : append(makePCtab(fp), encodeVariant(int(size))...),
pclntable : pclntab,
ftab : ftab,
text : minpc,
etext : pc + textSize,
findfunctab : &findFuncTab[0],
minpc : minpc,
maxpc : maxpc,
modulename : name,
gcdata: uintptr(unsafe.Pointer(&emptyByte)),
gcbss: uintptr(unsafe.Pointer(&emptyByte)),
gofunc: base,
}
/* verify and register the new module */
moduledataverify1(mod)
registerModule(mod)
}

@ -1,201 +0,0 @@
// +build go1.20
/*
* Copyright 2021 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package loader
import (
`unsafe`
`github.com/bytedance/sonic/internal/rt`
)
// A FuncFlag holds bits about a function.
// This list must match the list in cmd/internal/objabi/funcid.go.
type funcFlag uint8
type _Func struct {
entryOff uint32 // start pc
nameoff int32 // function name
args int32 // in/out args size
deferreturn uint32 // offset of start of a deferreturn call instruction from entry, if any.
pcsp uint32
pcfile uint32
pcln uint32
npcdata uint32
cuOffset uint32 // runtime.cutab offset of this function's CU
funcID uint8 // set for certain special runtime functions
flag funcFlag
_ [1]byte // pad
nfuncdata uint8 // must be last
argptrs uint32
localptrs uint32
}
type _FuncTab struct {
entry uint32
funcoff uint32
}
type _PCHeader struct {
magic uint32 // 0xFFFFFFF0
pad1, pad2 uint8 // 0,0
minLC uint8 // min instruction size
ptrSize uint8 // size of a ptr in bytes
nfunc int // number of functions in the module
nfiles uint // number of entries in the file tab
textStart uintptr // base for function entry PC offsets in this module, equal to moduledata.text
funcnameOffset uintptr // offset to the funcnametab variable from pcHeader
cuOffset uintptr // offset to the cutab variable from pcHeader
filetabOffset uintptr // offset to the filetab variable from pcHeader
pctabOffset uintptr // offset to the pctab variable from pcHeader
pclnOffset uintptr // offset to the pclntab variable from pcHeader
}
type _BitVector struct {
n int32 // # of bits
bytedata *uint8
}
type _PtabEntry struct {
name int32
typ int32
}
type _TextSection struct {
vaddr uintptr // prelinked section vaddr
length uintptr // section length
baseaddr uintptr // relocated section address
}
type _ModuleData struct {
pcHeader *_PCHeader
funcnametab []byte
cutab []uint32
filetab []byte
pctab []byte
pclntable []byte
ftab []_FuncTab
findfunctab *_FindFuncBucket
minpc, maxpc uintptr
text, etext uintptr
noptrdata, enoptrdata uintptr
data, edata uintptr
bss, ebss uintptr
noptrbss, enoptrbss uintptr
end, gcdata, gcbss uintptr
types, etypes uintptr
rodata uintptr
gofunc uintptr
textsectmap []_TextSection
typelinks []int32
itablinks []unsafe.Pointer
ptab []_PtabEntry
pluginpath string
pkghashes []struct{}
modulename string
modulehashes []struct{}
hasmain uint8
gcdatamask, gcbssmask _BitVector
typemap map[int32]unsafe.Pointer
bad bool
next *_ModuleData
}
type _FindFuncBucket struct {
idx uint32
subbuckets [16]byte
}
func makePCtab(fp int) []byte {
return append([]byte{0}, encodeVariant((fp + 1) << 1)...)
}
func registerFunction(name string, pc uintptr, textSize uintptr, fp int, args int, size uintptr, argPtrs []bool, localPtrs []bool) {
mod := new(_ModuleData)
minpc := pc
maxpc := pc + size
findFuncTab := make([]_FindFuncBucket, textSize/4096 + 1)
modHeader := &_PCHeader {
magic : 0xfffffff0,
minLC : 1,
nfunc : 1,
ptrSize : 4 << (^uintptr(0) >> 63),
textStart: minpc,
}
// cache arg and local stackmap
argptrs, localptrs := cacheStackmap(argPtrs, localPtrs, mod)
base := argptrs
if argptrs > localptrs {
base = localptrs
}
/* function entry */
lnt := []_Func {{
entryOff : 0,
nameoff : 1,
args : int32(args),
pcsp : 1,
nfuncdata : 2,
argptrs: uint32(argptrs - base),
localptrs: uint32(localptrs - base),
}}
nlnt := len(lnt)*int(unsafe.Sizeof(_Func{}))
plnt := unsafe.Pointer(&lnt[0])
/* function table */
ftab := []_FuncTab {
{entry : 0, funcoff : 16},
{entry : uint32(size)},
}
nftab := len(ftab)*int(unsafe.Sizeof(_FuncTab{}))
pftab := unsafe.Pointer(&ftab[0])
pclntab := make([]byte, 0, nftab + nlnt)
pclntab = append(pclntab, rt.BytesFrom(pftab, nftab, nftab)...)
pclntab = append(pclntab, rt.BytesFrom(plnt, nlnt, nlnt)...)
/* module data */
*mod = _ModuleData {
pcHeader : modHeader,
funcnametab : append(append([]byte{0}, name...), 0),
pctab : append(makePCtab(fp), encodeVariant(int(size))...),
pclntable : pclntab,
ftab : ftab,
text : minpc,
etext : pc + textSize,
findfunctab : &findFuncTab[0],
minpc : minpc,
maxpc : maxpc,
modulename : name,
gcdata: uintptr(unsafe.Pointer(&emptyByte)),
gcbss: uintptr(unsafe.Pointer(&emptyByte)),
gofunc: base,
}
/* verify and register the new module */
moduledataverify1(mod)
registerModule(mod)
}

@ -1,74 +0,0 @@
//go:build darwin || linux
// +build darwin linux
/*
* Copyright 2021 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package loader
import (
`fmt`
`os`
`reflect`
`syscall`
`unsafe`
)
const (
_AP = syscall.MAP_ANON | syscall.MAP_PRIVATE
_RX = syscall.PROT_READ | syscall.PROT_EXEC
_RW = syscall.PROT_READ | syscall.PROT_WRITE
)
type Loader []byte
type Function unsafe.Pointer
func (self Loader) Load(fn string, fp int, args int, argPtrs []bool, localPtrs []bool) (f Function) {
p := os.Getpagesize()
n := (((len(self) - 1) / p) + 1) * p
/* register the function */
m := mmap(n)
v := fmt.Sprintf("runtime.__%s_%x", fn, m)
registerFunction(v, m, uintptr(n), fp, args, uintptr(len(self)), argPtrs, localPtrs)
/* reference as a slice */
s := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader {
Data : m,
Cap : n,
Len : len(self),
}))
/* copy the machine code, and make it executable */
copy(s, self)
mprotect(m, n)
return Function(&m)
}
func mmap(nb int) uintptr {
if m, _, e := syscall.RawSyscall6(syscall.SYS_MMAP, 0, uintptr(nb), _RW, _AP, 0, 0); e != 0 {
panic(e)
} else {
return m
}
}
func mprotect(p uintptr, nb int) {
if _, _, err := syscall.RawSyscall(syscall.SYS_MPROTECT, p, uintptr(nb), _RX); err != 0 {
panic(err)
}
}

@ -1,111 +0,0 @@
//go:build windows
// +build windows
/*
* Copyright 2021 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package loader
import (
`fmt`
`os`
`reflect`
`syscall`
`unsafe`
)
const (
MEM_COMMIT = 0x00001000
MEM_RESERVE = 0x00002000
)
var (
libKernel32 = syscall.NewLazyDLL("KERNEL32.DLL")
libKernel32_VirtualAlloc = libKernel32.NewProc("VirtualAlloc")
libKernel32_VirtualProtect = libKernel32.NewProc("VirtualProtect")
)
type Loader []byte
type Function unsafe.Pointer
func (self Loader) Load(fn string, fp int, args int, argPtrs []bool, localPtrs []bool) (f Function) {
p := os.Getpagesize()
n := (((len(self) - 1) / p) + 1) * p
/* register the function */
m := mmap(n)
v := fmt.Sprintf("runtime.__%s_%x", fn, m)
registerFunction(v, m, uintptr(n), fp, args, uintptr(len(self)), argPtrs, localPtrs)
/* reference as a slice */
s := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader {
Data : m,
Cap : n,
Len : len(self),
}))
/* copy the machine code, and make it executable */
copy(s, self)
mprotect(m, n)
return Function(&m)
}
func mmap(nb int) uintptr {
addr, err := winapi_VirtualAlloc(0, nb, MEM_COMMIT|MEM_RESERVE, syscall.PAGE_READWRITE)
if err != nil {
panic(err)
}
return addr
}
func mprotect(p uintptr, nb int) (oldProtect int) {
err := winapi_VirtualProtect(p, nb, syscall.PAGE_EXECUTE_READ, &oldProtect)
if err != nil {
panic(err)
}
return
}
// winapi_VirtualAlloc allocate memory
// Doc: https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualalloc
func winapi_VirtualAlloc(lpAddr uintptr, dwSize int, flAllocationType int, flProtect int) (uintptr, error) {
r1, _, err := libKernel32_VirtualAlloc.Call(
lpAddr,
uintptr(dwSize),
uintptr(flAllocationType),
uintptr(flProtect),
)
if r1 == 0 {
return 0, err
}
return r1, nil
}
// winapi_VirtualProtect change memory protection
// Doc: https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualprotect
func winapi_VirtualProtect(lpAddr uintptr, dwSize int, flNewProtect int, lpflOldProtect *int) error {
r1, _, err := libKernel32_VirtualProtect.Call(
lpAddr,
uintptr(dwSize),
uintptr(flNewProtect),
uintptr(unsafe.Pointer(lpflOldProtect)),
)
if r1 == 0 {
return err
}
return nil
}

@ -1,5 +1,7 @@
// Code generated by Makefile, DO NOT EDIT.
// Code generated by Makefile, DO NOT EDIT.
/*
* Copyright 2021 ByteDance Inc.
*
@ -22,114 +24,168 @@ import (
`unsafe`
`github.com/bytedance/sonic/internal/native/types`
`github.com/bytedance/sonic/internal/rt`
)
var (
__i64toa func(out unsafe.Pointer, val int64) (ret int)
__u64toa func(out unsafe.Pointer, val uint64) (ret int)
__f64toa func(out unsafe.Pointer, val float64) (ret int)
__f32toa func(out unsafe.Pointer, val float32) (ret int)
__lspace func(sp unsafe.Pointer, nb int, off int) (ret int)
__quote func(sp unsafe.Pointer, nb int, dp unsafe.Pointer, dn unsafe.Pointer, flags uint64) (ret int)
__html_escape func(sp unsafe.Pointer, nb int, dp unsafe.Pointer, dn unsafe.Pointer) (ret int)
__unquote func(sp unsafe.Pointer, nb int, dp unsafe.Pointer, ep unsafe.Pointer, flags uint64) (ret int)
__value func(s unsafe.Pointer, n int, p int, v unsafe.Pointer, flags uint64) (ret int)
__vstring func(s unsafe.Pointer, p unsafe.Pointer, v unsafe.Pointer, flags uint64)
__vnumber func(s unsafe.Pointer, p unsafe.Pointer, v unsafe.Pointer)
__vsigned func(s unsafe.Pointer, p unsafe.Pointer, v unsafe.Pointer)
__vunsigned func(s unsafe.Pointer, p unsafe.Pointer, v unsafe.Pointer)
__skip_one func(s unsafe.Pointer, p unsafe.Pointer, m unsafe.Pointer, flags uint64) (ret int)
__skip_one_fast func(s unsafe.Pointer, p unsafe.Pointer) (ret int)
__skip_array func(s unsafe.Pointer, p unsafe.Pointer, m unsafe.Pointer, flags uint64) (ret int)
__skip_object func(s unsafe.Pointer, p unsafe.Pointer, m unsafe.Pointer, flags uint64) (ret int)
__skip_number func(s unsafe.Pointer, p unsafe.Pointer) (ret int)
__validate_one func(s unsafe.Pointer, p unsafe.Pointer, m unsafe.Pointer) (ret int)
__get_by_path func(s unsafe.Pointer, p unsafe.Pointer, path unsafe.Pointer, m unsafe.Pointer) (ret int)
__validate_utf8 func(s unsafe.Pointer, p unsafe.Pointer, m unsafe.Pointer) (ret int)
__validate_utf8_fast func(s unsafe.Pointer) (ret int)
__fsm_exec func(m unsafe.Pointer, s unsafe.Pointer, p unsafe.Pointer, flags uint64) (ret int)
)
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __i64toa(out *byte, val int64) (ret int)
func i64toa(out *byte, val int64) (ret int) {
return __i64toa(rt.NoEscape(unsafe.Pointer(out)), val)
}
//go:nosplit
func u64toa(out *byte, val uint64) (ret int) {
return __u64toa(rt.NoEscape(unsafe.Pointer(out)), val)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __u64toa(out *byte, val uint64) (ret int)
func f64toa(out *byte, val float64) (ret int) {
return __f64toa(rt.NoEscape(unsafe.Pointer(out)), val)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __f64toa(out *byte, val float64) (ret int)
func f32toa(out *byte, val float32) (ret int) {
return __f32toa(rt.NoEscape(unsafe.Pointer(out)), val)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __f32toa(out *byte, val float32) (ret int)
func lspace(sp unsafe.Pointer, nb int, off int) (ret int) {
return __lspace(rt.NoEscape(sp), nb, off)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __lspace(sp unsafe.Pointer, nb int, off int) (ret int)
func quote(sp unsafe.Pointer, nb int, dp unsafe.Pointer, dn *int, flags uint64) (ret int) {
return __quote(rt.NoEscape(unsafe.Pointer(sp)), nb, rt.NoEscape(unsafe.Pointer(dp)), rt.NoEscape(unsafe.Pointer(dn)), flags)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __quote(sp unsafe.Pointer, nb int, dp unsafe.Pointer, dn *int, flags uint64) (ret int)
func html_escape(sp unsafe.Pointer, nb int, dp unsafe.Pointer, dn *int) (ret int) {
return __html_escape(rt.NoEscape(unsafe.Pointer(sp)), nb, rt.NoEscape(unsafe.Pointer(dp)), rt.NoEscape(unsafe.Pointer(dn)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __html_escape(sp unsafe.Pointer, nb int, dp unsafe.Pointer, dn *int) (ret int)
func unquote(sp unsafe.Pointer, nb int, dp unsafe.Pointer, ep *int, flags uint64) (ret int) {
return __unquote(rt.NoEscape(unsafe.Pointer(sp)), nb, rt.NoEscape(unsafe.Pointer(dp)), rt.NoEscape(unsafe.Pointer(ep)), flags)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __unquote(sp unsafe.Pointer, nb int, dp unsafe.Pointer, ep *int, flags uint64) (ret int)
func value(s unsafe.Pointer, n int, p int, v *types.JsonState, flags uint64) (ret int) {
return __value(rt.NoEscape(unsafe.Pointer(s)), n, p, rt.NoEscape(unsafe.Pointer(v)), flags)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __value(s unsafe.Pointer, n int, p int, v *types.JsonState, flags uint64) (ret int)
func vstring(s *string, p *int, v *types.JsonState, flags uint64) {
__vstring(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(v)), flags)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __vstring(s *string, p *int, v *types.JsonState, flags uint64)
func vnumber(s *string, p *int, v *types.JsonState) {
__vnumber(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(v)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __vnumber(s *string, p *int, v *types.JsonState)
func vsigned(s *string, p *int, v *types.JsonState) {
__vsigned(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(v)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __vsigned(s *string, p *int, v *types.JsonState)
func vunsigned(s *string, p *int, v *types.JsonState) {
__vunsigned(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(v)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __vunsigned(s *string, p *int, v *types.JsonState)
func skip_one(s *string, p *int, m *types.StateMachine, flags uint64) (ret int) {
return __skip_one(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(m)), flags)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __skip_one(s *string, p *int, m *types.StateMachine, flags uint64) (ret int)
func skip_one_fast(s *string, p *int) (ret int) {
return __skip_one_fast(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __skip_one_fast(s *string, p *int) (ret int)
func skip_array(s *string, p *int, m *types.StateMachine, flags uint64) (ret int) {
return __skip_array(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(m)), flags)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __skip_array(s *string, p *int, m *types.StateMachine, flags uint64) (ret int)
func skip_object(s *string, p *int, m *types.StateMachine, flags uint64) (ret int) {
return __skip_object(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(m)), flags)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __skip_object(s *string, p *int, m *types.StateMachine, flags uint64) (ret int)
func skip_number(s *string, p *int) (ret int) {
return __skip_number(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __skip_number(s *string, p *int) (ret int)
func validate_one(s *string, p *int, m *types.StateMachine) (ret int) {
return __validate_one(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(m)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __validate_one(s *string, p *int, m *types.StateMachine) (ret int)
func get_by_path(s *string, p *int, path *[]interface{}, m *types.StateMachine) (ret int) {
return __get_by_path(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(path)), rt.NoEscape(unsafe.Pointer(m)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __get_by_path(s *string, p *int, path *[]interface{}, m *types.StateMachine) (ret int)
func validate_utf8(s *string, p *int, m *types.StateMachine) (ret int) {
return __validate_utf8(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(m)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __validate_utf8(s *string, p *int, m *types.StateMachine) (ret int)
func validate_utf8_fast(s *string) (ret int) {
return __validate_utf8_fast(rt.NoEscape(unsafe.Pointer(s)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __validate_utf8_fast(s *string) (ret int)
func fsm_exec(m *types.StateMachine, s *string, p *int, flags uint64) (ret int) {
return __fsm_exec(rt.NoEscape(unsafe.Pointer(m)), rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), flags)
}

File diff suppressed because it is too large Load Diff

@ -1,49 +0,0 @@
// Code generated by Makefile, DO NOT EDIT.
/*
* Copyright 2021 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package avx
var (
S_f64toa = _subr__f64toa
S_f32toa = _subr__f32toa
S_i64toa = _subr__i64toa
S_u64toa = _subr__u64toa
S_lspace = _subr__lspace
)
var (
S_quote = _subr__quote
S_unquote = _subr__unquote
)
var (
S_value = _subr__value
S_vstring = _subr__vstring
S_vnumber = _subr__vnumber
S_vsigned = _subr__vsigned
S_vunsigned = _subr__vunsigned
)
var (
S_skip_one = _subr__skip_one
S_skip_one_fast = _subr__skip_one_fast
S_skip_array = _subr__skip_array
S_skip_object = _subr__skip_object
S_skip_number = _subr__skip_number
S_get_by_path = _subr__get_by_path
)

@ -3,107 +3,601 @@
package avx
//go:nosplit
//go:noescape
//goland:noinspection ALL
func __native_entry__() uintptr
import (
`github.com/bytedance/sonic/loader`
)
var (
_subr__f32toa = __native_entry__() + 31264
_subr__f64toa = __native_entry__() + 192
_subr__get_by_path = __native_entry__() + 25856
_subr__html_escape = __native_entry__() + 9040
_subr__i64toa = __native_entry__() + 3488
_subr__lspace = __native_entry__() + 16
_subr__quote = __native_entry__() + 4880
_subr__skip_array = __native_entry__() + 17952
_subr__skip_number = __native_entry__() + 21952
_subr__skip_object = __native_entry__() + 20368
_subr__skip_one = __native_entry__() + 22112
_subr__skip_one_fast = __native_entry__() + 22352
_subr__u64toa = __native_entry__() + 3600
_subr__unquote = __native_entry__() + 6672
_subr__validate_one = __native_entry__() + 22176
_subr__validate_utf8 = __native_entry__() + 30000
_subr__validate_utf8_fast = __native_entry__() + 30672
_subr__value = __native_entry__() + 12224
_subr__vnumber = __native_entry__() + 15616
_subr__vsigned = __native_entry__() + 17232
_subr__vstring = __native_entry__() + 14064
_subr__vunsigned = __native_entry__() + 17600
const (
_entry__f32toa = 31136
_entry__f64toa = 192
_entry__format_significand = 35248
_entry__format_integer = 3040
_entry__fsm_exec = 17920
_entry__advance_string = 14320
_entry__advance_string_default = 36640
_entry__do_skip_number = 20528
_entry__get_by_path = 25680
_entry__skip_one_fast = 22160
_entry__html_escape = 8912
_entry__i64toa = 3472
_entry__u64toa = 3584
_entry__lspace = 16
_entry__quote = 4864
_entry__skip_array = 17872
_entry__skip_number = 21792
_entry__skip_object = 20160
_entry__skip_one = 21936
_entry__unquote = 6576
_entry__validate_one = 21984
_entry__validate_utf8 = 29888
_entry__validate_utf8_fast = 30560
_entry__value = 12320
_entry__vnumber = 15648
_entry__atof_eisel_lemire64 = 10160
_entry__atof_native = 11712
_entry__decimal_to_f64 = 10528
_entry__right_shift = 36208
_entry__left_shift = 35712
_entry__vsigned = 17200
_entry__vstring = 14144
_entry__vunsigned = 17520
)
const (
_stack__f32toa = 48
_stack__f64toa = 80
_stack__get_by_path = 304
_stack__html_escape = 64
_stack__format_significand = 24
_stack__format_integer = 16
_stack__fsm_exec = 168
_stack__advance_string = 64
_stack__advance_string_default = 64
_stack__do_skip_number = 48
_stack__get_by_path = 280
_stack__skip_one_fast = 176
_stack__html_escape = 72
_stack__i64toa = 16
_stack__u64toa = 8
_stack__lspace = 8
_stack__quote = 56
_stack__skip_array = 128
_stack__skip_number = 72
_stack__skip_object = 128
_stack__skip_one = 128
_stack__skip_one_fast = 200
_stack__u64toa = 8
_stack__skip_array = 176
_stack__skip_number = 88
_stack__skip_object = 176
_stack__skip_one = 176
_stack__unquote = 88
_stack__validate_one = 128
_stack__validate_one = 176
_stack__validate_utf8 = 48
_stack__validate_utf8_fast = 24
_stack__value = 328
_stack__vnumber = 240
_stack__atof_eisel_lemire64 = 32
_stack__atof_native = 136
_stack__decimal_to_f64 = 80
_stack__right_shift = 8
_stack__left_shift = 24
_stack__vsigned = 16
_stack__vstring = 136
_stack__vunsigned = 16
_stack__vstring = 120
_stack__vunsigned = 8
)
var (
_ = _subr__f32toa
_ = _subr__f64toa
_ = _subr__get_by_path
_ = _subr__html_escape
_ = _subr__i64toa
_ = _subr__lspace
_ = _subr__quote
_ = _subr__skip_array
_ = _subr__skip_number
_ = _subr__skip_object
_ = _subr__skip_one
_ = _subr__skip_one_fast
_ = _subr__u64toa
_ = _subr__unquote
_ = _subr__validate_one
_ = _subr__validate_utf8
_ = _subr__validate_utf8_fast
_ = _subr__value
_ = _subr__vnumber
_ = _subr__vsigned
_ = _subr__vstring
_ = _subr__vunsigned
const (
_size__f32toa = 3392
_size__f64toa = 2848
_size__format_significand = 464
_size__format_integer = 432
_size__fsm_exec = 1692
_size__advance_string = 1280
_size__advance_string_default = 944
_size__do_skip_number = 924
_size__get_by_path = 4208
_size__skip_one_fast = 3016
_size__html_escape = 1248
_size__i64toa = 48
_size__u64toa = 1232
_size__lspace = 144
_size__quote = 1696
_size__skip_array = 48
_size__skip_number = 144
_size__skip_object = 48
_size__skip_one = 48
_size__unquote = 2272
_size__validate_one = 48
_size__validate_utf8 = 672
_size__validate_utf8_fast = 544
_size__value = 1316
_size__vnumber = 1552
_size__atof_eisel_lemire64 = 368
_size__atof_native = 608
_size__decimal_to_f64 = 1184
_size__right_shift = 400
_size__left_shift = 496
_size__vsigned = 320
_size__vstring = 128
_size__vunsigned = 336
)
const (
_ = _stack__f32toa
_ = _stack__f64toa
_ = _stack__get_by_path
_ = _stack__html_escape
_ = _stack__i64toa
_ = _stack__lspace
_ = _stack__quote
_ = _stack__skip_array
_ = _stack__skip_number
_ = _stack__skip_object
_ = _stack__skip_one
_ = _stack__skip_one_fast
_ = _stack__u64toa
_ = _stack__unquote
_ = _stack__validate_one
_ = _stack__validate_utf8
_ = _stack__validate_utf8_fast
_ = _stack__value
_ = _stack__vnumber
_ = _stack__vsigned
_ = _stack__vstring
_ = _stack__vunsigned
var (
_pcsp__f32toa = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{3350, 48},
{3351, 40},
{3353, 32},
{3355, 24},
{3357, 16},
{3359, 8},
{3363, 0},
{3385, 48},
}
_pcsp__f64toa = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{13, 48},
{2788, 56},
{2792, 48},
{2793, 40},
{2795, 32},
{2797, 24},
{2799, 16},
{2801, 8},
{2805, 0},
{2843, 56},
}
_pcsp__format_significand = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{452, 24},
{453, 16},
{455, 8},
{457, 0},
}
_pcsp__format_integer = [][2]uint32{
{1, 0},
{4, 8},
{412, 16},
{413, 8},
{414, 0},
{423, 16},
{424, 8},
{426, 0},
}
_pcsp__fsm_exec = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{13, 48},
{1342, 104},
{1346, 48},
{1347, 40},
{1349, 32},
{1351, 24},
{1353, 16},
{1355, 8},
{1356, 0},
{1692, 104},
}
_pcsp__advance_string = [][2]uint32{
{14, 0},
{18, 8},
{20, 16},
{22, 24},
{24, 32},
{26, 40},
{27, 48},
{557, 56},
{561, 48},
{562, 40},
{564, 32},
{566, 24},
{568, 16},
{570, 8},
{571, 0},
{1268, 56},
}
_pcsp__advance_string_default = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{13, 48},
{552, 64},
{556, 48},
{557, 40},
{559, 32},
{561, 24},
{563, 16},
{565, 8},
{566, 0},
{931, 64},
}
_pcsp__do_skip_number = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{849, 48},
{850, 40},
{852, 32},
{854, 24},
{856, 16},
{858, 8},
{859, 0},
{924, 48},
}
_pcsp__get_by_path = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{13, 48},
{4012, 104},
{4016, 48},
{4017, 40},
{4019, 32},
{4021, 24},
{4023, 16},
{4025, 8},
{4026, 0},
{4194, 104},
}
_pcsp__skip_one_fast = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{13, 48},
{658, 176},
{659, 168},
{661, 160},
{663, 152},
{665, 144},
{667, 136},
{671, 128},
{3016, 176},
}
_pcsp__html_escape = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{13, 48},
{1224, 72},
{1228, 48},
{1229, 40},
{1231, 32},
{1233, 24},
{1235, 16},
{1237, 8},
{1239, 0},
}
_pcsp__i64toa = [][2]uint32{
{14, 0},
{34, 8},
{36, 0},
}
_pcsp__u64toa = [][2]uint32{
{1, 0},
{161, 8},
{162, 0},
{457, 8},
{458, 0},
{756, 8},
{757, 0},
{1221, 8},
{1223, 0},
}
_pcsp__lspace = [][2]uint32{
{1, 0},
{89, 8},
{90, 0},
{103, 8},
{104, 0},
{111, 8},
{113, 0},
}
_pcsp__quote = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{13, 48},
{1649, 56},
{1653, 48},
{1654, 40},
{1656, 32},
{1658, 24},
{1660, 16},
{1662, 8},
{1663, 0},
{1690, 56},
}
_pcsp__skip_array = [][2]uint32{
{1, 0},
{28, 8},
{34, 0},
}
_pcsp__skip_number = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{100, 40},
{101, 32},
{103, 24},
{105, 16},
{107, 8},
{108, 0},
{139, 40},
}
_pcsp__skip_object = [][2]uint32{
{1, 0},
{28, 8},
{34, 0},
}
_pcsp__skip_one = [][2]uint32{
{1, 0},
{30, 8},
{36, 0},
}
_pcsp__unquote = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{13, 48},
{1684, 88},
{1688, 48},
{1689, 40},
{1691, 32},
{1693, 24},
{1695, 16},
{1697, 8},
{1698, 0},
{2270, 88},
}
_pcsp__validate_one = [][2]uint32{
{1, 0},
{35, 8},
{41, 0},
}
_pcsp__validate_utf8 = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{11, 40},
{623, 48},
{627, 40},
{628, 32},
{630, 24},
{632, 16},
{634, 8},
{635, 0},
{666, 48},
}
_pcsp__validate_utf8_fast = [][2]uint32{
{1, 0},
{4, 8},
{5, 16},
{247, 24},
{251, 16},
{252, 8},
{253, 0},
{527, 24},
{531, 16},
{532, 8},
{534, 0},
}
_pcsp__value = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{13, 48},
{495, 88},
{499, 48},
{500, 40},
{502, 32},
{504, 24},
{506, 16},
{508, 8},
{509, 0},
{1316, 88},
}
_pcsp__vnumber = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{13, 48},
{803, 104},
{807, 48},
{808, 40},
{810, 32},
{812, 24},
{814, 16},
{816, 8},
{817, 0},
{1547, 104},
}
_pcsp__atof_eisel_lemire64 = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{292, 32},
{293, 24},
{295, 16},
{297, 8},
{298, 0},
{362, 32},
}
_pcsp__atof_native = [][2]uint32{
{1, 0},
{4, 8},
{587, 56},
{591, 8},
{593, 0},
}
_pcsp__decimal_to_f64 = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{13, 48},
{1144, 56},
{1148, 48},
{1149, 40},
{1151, 32},
{1153, 24},
{1155, 16},
{1157, 8},
{1158, 0},
{1169, 56},
}
_pcsp__right_shift = [][2]uint32{
{1, 0},
{318, 8},
{319, 0},
{387, 8},
{388, 0},
{396, 8},
{398, 0},
}
_pcsp__left_shift = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{363, 24},
{364, 16},
{366, 8},
{367, 0},
{470, 24},
{471, 16},
{473, 8},
{474, 0},
{486, 24},
}
_pcsp__vsigned = [][2]uint32{
{1, 0},
{4, 8},
{112, 16},
{113, 8},
{114, 0},
{125, 16},
{126, 8},
{127, 0},
{260, 16},
{261, 8},
{262, 0},
{266, 16},
{267, 8},
{268, 0},
{306, 16},
{307, 8},
{308, 0},
{316, 16},
{317, 8},
{319, 0},
}
_pcsp__vstring = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{11, 40},
{105, 56},
{109, 40},
{110, 32},
{112, 24},
{114, 16},
{116, 8},
{118, 0},
}
_pcsp__vunsigned = [][2]uint32{
{1, 0},
{71, 8},
{72, 0},
{83, 8},
{84, 0},
{107, 8},
{108, 0},
{273, 8},
{274, 0},
{312, 8},
{313, 0},
{320, 8},
{322, 0},
}
)
var Funcs = []loader.CFunc{
{"__native_entry__", 0, 67, 0, nil},
{"_f32toa", _entry__f32toa, _size__f32toa, _stack__f32toa, _pcsp__f32toa},
{"_f64toa", _entry__f64toa, _size__f64toa, _stack__f64toa, _pcsp__f64toa},
{"_format_significand", _entry__format_significand, _size__format_significand, _stack__format_significand, _pcsp__format_significand},
{"_format_integer", _entry__format_integer, _size__format_integer, _stack__format_integer, _pcsp__format_integer},
{"_fsm_exec", _entry__fsm_exec, _size__fsm_exec, _stack__fsm_exec, _pcsp__fsm_exec},
{"_advance_string", _entry__advance_string, _size__advance_string, _stack__advance_string, _pcsp__advance_string},
{"_advance_string_default", _entry__advance_string_default, _size__advance_string_default, _stack__advance_string_default, _pcsp__advance_string_default},
{"_do_skip_number", _entry__do_skip_number, _size__do_skip_number, _stack__do_skip_number, _pcsp__do_skip_number},
{"_get_by_path", _entry__get_by_path, _size__get_by_path, _stack__get_by_path, _pcsp__get_by_path},
{"_skip_one_fast", _entry__skip_one_fast, _size__skip_one_fast, _stack__skip_one_fast, _pcsp__skip_one_fast},
{"_html_escape", _entry__html_escape, _size__html_escape, _stack__html_escape, _pcsp__html_escape},
{"_i64toa", _entry__i64toa, _size__i64toa, _stack__i64toa, _pcsp__i64toa},
{"_u64toa", _entry__u64toa, _size__u64toa, _stack__u64toa, _pcsp__u64toa},
{"_lspace", _entry__lspace, _size__lspace, _stack__lspace, _pcsp__lspace},
{"_quote", _entry__quote, _size__quote, _stack__quote, _pcsp__quote},
{"_skip_array", _entry__skip_array, _size__skip_array, _stack__skip_array, _pcsp__skip_array},
{"_skip_number", _entry__skip_number, _size__skip_number, _stack__skip_number, _pcsp__skip_number},
{"_skip_object", _entry__skip_object, _size__skip_object, _stack__skip_object, _pcsp__skip_object},
{"_skip_one", _entry__skip_one, _size__skip_one, _stack__skip_one, _pcsp__skip_one},
{"_unquote", _entry__unquote, _size__unquote, _stack__unquote, _pcsp__unquote},
{"_validate_one", _entry__validate_one, _size__validate_one, _stack__validate_one, _pcsp__validate_one},
{"_validate_utf8", _entry__validate_utf8, _size__validate_utf8, _stack__validate_utf8, _pcsp__validate_utf8},
{"_validate_utf8_fast", _entry__validate_utf8_fast, _size__validate_utf8_fast, _stack__validate_utf8_fast, _pcsp__validate_utf8_fast},
{"_value", _entry__value, _size__value, _stack__value, _pcsp__value},
{"_vnumber", _entry__vnumber, _size__vnumber, _stack__vnumber, _pcsp__vnumber},
{"_atof_eisel_lemire64", _entry__atof_eisel_lemire64, _size__atof_eisel_lemire64, _stack__atof_eisel_lemire64, _pcsp__atof_eisel_lemire64},
{"_atof_native", _entry__atof_native, _size__atof_native, _stack__atof_native, _pcsp__atof_native},
{"_decimal_to_f64", _entry__decimal_to_f64, _size__decimal_to_f64, _stack__decimal_to_f64, _pcsp__decimal_to_f64},
{"_right_shift", _entry__right_shift, _size__right_shift, _stack__right_shift, _pcsp__right_shift},
{"_left_shift", _entry__left_shift, _size__left_shift, _stack__left_shift, _pcsp__left_shift},
{"_vsigned", _entry__vsigned, _size__vsigned, _stack__vsigned, _pcsp__vsigned},
{"_vstring", _entry__vstring, _size__vstring, _stack__vstring, _pcsp__vstring},
{"_vunsigned", _entry__vunsigned, _size__vunsigned, _stack__vunsigned, _pcsp__vunsigned},
}

File diff suppressed because it is too large Load Diff

@ -1,5 +1,7 @@
// Code generated by Makefile, DO NOT EDIT.
// Code generated by Makefile, DO NOT EDIT.
/*
* Copyright 2021 ByteDance Inc.
*
@ -22,114 +24,168 @@ import (
`unsafe`
`github.com/bytedance/sonic/internal/native/types`
`github.com/bytedance/sonic/internal/rt`
)
var (
__i64toa func(out unsafe.Pointer, val int64) (ret int)
__u64toa func(out unsafe.Pointer, val uint64) (ret int)
__f64toa func(out unsafe.Pointer, val float64) (ret int)
__f32toa func(out unsafe.Pointer, val float32) (ret int)
__lspace func(sp unsafe.Pointer, nb int, off int) (ret int)
__quote func(sp unsafe.Pointer, nb int, dp unsafe.Pointer, dn unsafe.Pointer, flags uint64) (ret int)
__html_escape func(sp unsafe.Pointer, nb int, dp unsafe.Pointer, dn unsafe.Pointer) (ret int)
__unquote func(sp unsafe.Pointer, nb int, dp unsafe.Pointer, ep unsafe.Pointer, flags uint64) (ret int)
__value func(s unsafe.Pointer, n int, p int, v unsafe.Pointer, flags uint64) (ret int)
__vstring func(s unsafe.Pointer, p unsafe.Pointer, v unsafe.Pointer, flags uint64)
__vnumber func(s unsafe.Pointer, p unsafe.Pointer, v unsafe.Pointer)
__vsigned func(s unsafe.Pointer, p unsafe.Pointer, v unsafe.Pointer)
__vunsigned func(s unsafe.Pointer, p unsafe.Pointer, v unsafe.Pointer)
__skip_one func(s unsafe.Pointer, p unsafe.Pointer, m unsafe.Pointer, flags uint64) (ret int)
__skip_one_fast func(s unsafe.Pointer, p unsafe.Pointer) (ret int)
__skip_array func(s unsafe.Pointer, p unsafe.Pointer, m unsafe.Pointer, flags uint64) (ret int)
__skip_object func(s unsafe.Pointer, p unsafe.Pointer, m unsafe.Pointer, flags uint64) (ret int)
__skip_number func(s unsafe.Pointer, p unsafe.Pointer) (ret int)
__validate_one func(s unsafe.Pointer, p unsafe.Pointer, m unsafe.Pointer) (ret int)
__get_by_path func(s unsafe.Pointer, p unsafe.Pointer, path unsafe.Pointer, m unsafe.Pointer) (ret int)
__validate_utf8 func(s unsafe.Pointer, p unsafe.Pointer, m unsafe.Pointer) (ret int)
__validate_utf8_fast func(s unsafe.Pointer) (ret int)
__fsm_exec func(m unsafe.Pointer, s unsafe.Pointer, p unsafe.Pointer, flags uint64) (ret int)
)
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __i64toa(out *byte, val int64) (ret int)
func i64toa(out *byte, val int64) (ret int) {
return __i64toa(rt.NoEscape(unsafe.Pointer(out)), val)
}
//go:nosplit
func u64toa(out *byte, val uint64) (ret int) {
return __u64toa(rt.NoEscape(unsafe.Pointer(out)), val)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __u64toa(out *byte, val uint64) (ret int)
func f64toa(out *byte, val float64) (ret int) {
return __f64toa(rt.NoEscape(unsafe.Pointer(out)), val)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __f64toa(out *byte, val float64) (ret int)
func f32toa(out *byte, val float32) (ret int) {
return __f32toa(rt.NoEscape(unsafe.Pointer(out)), val)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __f32toa(out *byte, val float32) (ret int)
func lspace(sp unsafe.Pointer, nb int, off int) (ret int) {
return __lspace(rt.NoEscape(sp), nb, off)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __lspace(sp unsafe.Pointer, nb int, off int) (ret int)
func quote(sp unsafe.Pointer, nb int, dp unsafe.Pointer, dn *int, flags uint64) (ret int) {
return __quote(rt.NoEscape(unsafe.Pointer(sp)), nb, rt.NoEscape(unsafe.Pointer(dp)), rt.NoEscape(unsafe.Pointer(dn)), flags)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __quote(sp unsafe.Pointer, nb int, dp unsafe.Pointer, dn *int, flags uint64) (ret int)
func html_escape(sp unsafe.Pointer, nb int, dp unsafe.Pointer, dn *int) (ret int) {
return __html_escape(rt.NoEscape(unsafe.Pointer(sp)), nb, rt.NoEscape(unsafe.Pointer(dp)), rt.NoEscape(unsafe.Pointer(dn)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __html_escape(sp unsafe.Pointer, nb int, dp unsafe.Pointer, dn *int) (ret int)
func unquote(sp unsafe.Pointer, nb int, dp unsafe.Pointer, ep *int, flags uint64) (ret int) {
return __unquote(rt.NoEscape(unsafe.Pointer(sp)), nb, rt.NoEscape(unsafe.Pointer(dp)), rt.NoEscape(unsafe.Pointer(ep)), flags)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __unquote(sp unsafe.Pointer, nb int, dp unsafe.Pointer, ep *int, flags uint64) (ret int)
func value(s unsafe.Pointer, n int, p int, v *types.JsonState, flags uint64) (ret int) {
return __value(rt.NoEscape(unsafe.Pointer(s)), n, p, rt.NoEscape(unsafe.Pointer(v)), flags)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __value(s unsafe.Pointer, n int, p int, v *types.JsonState, flags uint64) (ret int)
func vstring(s *string, p *int, v *types.JsonState, flags uint64) {
__vstring(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(v)), flags)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __vstring(s *string, p *int, v *types.JsonState, flags uint64)
func vnumber(s *string, p *int, v *types.JsonState) {
__vnumber(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(v)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __vnumber(s *string, p *int, v *types.JsonState)
func vsigned(s *string, p *int, v *types.JsonState) {
__vsigned(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(v)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __vsigned(s *string, p *int, v *types.JsonState)
func vunsigned(s *string, p *int, v *types.JsonState) {
__vunsigned(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(v)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __vunsigned(s *string, p *int, v *types.JsonState)
func skip_one(s *string, p *int, m *types.StateMachine, flags uint64) (ret int) {
return __skip_one(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(m)), flags)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __skip_one(s *string, p *int, m *types.StateMachine, flags uint64) (ret int)
func skip_one_fast(s *string, p *int) (ret int) {
return __skip_one_fast(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __skip_one_fast(s *string, p *int) (ret int)
func skip_array(s *string, p *int, m *types.StateMachine, flags uint64) (ret int) {
return __skip_array(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(m)), flags)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __skip_array(s *string, p *int, m *types.StateMachine, flags uint64) (ret int)
func skip_object(s *string, p *int, m *types.StateMachine, flags uint64) (ret int) {
return __skip_object(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(m)), flags)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __skip_object(s *string, p *int, m *types.StateMachine, flags uint64) (ret int)
func skip_number(s *string, p *int) (ret int) {
return __skip_number(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __skip_number(s *string, p *int) (ret int)
func validate_one(s *string, p *int, m *types.StateMachine) (ret int) {
return __validate_one(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(m)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __validate_one(s *string, p *int, m *types.StateMachine) (ret int)
func get_by_path(s *string, p *int, path *[]interface{}, m *types.StateMachine) (ret int) {
return __get_by_path(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(path)), rt.NoEscape(unsafe.Pointer(m)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __get_by_path(s *string, p *int, path *[]interface{}, m *types.StateMachine) (ret int)
func validate_utf8(s *string, p *int, m *types.StateMachine) (ret int) {
return __validate_utf8(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(m)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __validate_utf8(s *string, p *int, m *types.StateMachine) (ret int)
func validate_utf8_fast(s *string) (ret int) {
return __validate_utf8_fast(rt.NoEscape(unsafe.Pointer(s)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __validate_utf8_fast(s *string) (ret int)
func fsm_exec(m *types.StateMachine, s *string, p *int, flags uint64) (ret int) {
return __fsm_exec(rt.NoEscape(unsafe.Pointer(m)), rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), flags)
}

File diff suppressed because it is too large Load Diff

@ -1,49 +0,0 @@
// Code generated by Makefile, DO NOT EDIT.
/*
* Copyright 2021 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package avx2
var (
S_f64toa = _subr__f64toa
S_f32toa = _subr__f32toa
S_i64toa = _subr__i64toa
S_u64toa = _subr__u64toa
S_lspace = _subr__lspace
)
var (
S_quote = _subr__quote
S_unquote = _subr__unquote
)
var (
S_value = _subr__value
S_vstring = _subr__vstring
S_vnumber = _subr__vnumber
S_vsigned = _subr__vsigned
S_vunsigned = _subr__vunsigned
)
var (
S_skip_one = _subr__skip_one
S_skip_one_fast = _subr__skip_one_fast
S_skip_array = _subr__skip_array
S_skip_object = _subr__skip_object
S_skip_number = _subr__skip_number
S_get_by_path = _subr__get_by_path
)

@ -3,107 +3,608 @@
package avx2
//go:nosplit
//go:noescape
//goland:noinspection ALL
func __native_entry__() uintptr
import (
`github.com/bytedance/sonic/loader`
)
var (
_subr__f32toa = __native_entry__() + 33888
_subr__f64toa = __native_entry__() + 288
_subr__get_by_path = __native_entry__() + 28336
_subr__html_escape = __native_entry__() + 10496
_subr__i64toa = __native_entry__() + 3584
_subr__lspace = __native_entry__() + 64
_subr__quote = __native_entry__() + 5072
_subr__skip_array = __native_entry__() + 20688
_subr__skip_number = __native_entry__() + 24912
_subr__skip_object = __native_entry__() + 22736
_subr__skip_one = __native_entry__() + 25072
_subr__skip_one_fast = __native_entry__() + 25488
_subr__u64toa = __native_entry__() + 3696
_subr__unquote = __native_entry__() + 7888
_subr__validate_one = __native_entry__() + 25136
_subr__validate_utf8 = __native_entry__() + 30320
_subr__validate_utf8_fast = __native_entry__() + 31280
_subr__value = __native_entry__() + 15024
_subr__vnumber = __native_entry__() + 18352
_subr__vsigned = __native_entry__() + 19968
_subr__vstring = __native_entry__() + 17024
_subr__vunsigned = __native_entry__() + 20336
const (
_entry__f32toa = 34624
_entry__f64toa = 320
_entry__format_significand = 38736
_entry__format_integer = 3168
_entry__fsm_exec = 21072
_entry__advance_ns = 16928
_entry__advance_string = 17664
_entry__advance_string_default = 40160
_entry__do_skip_number = 23696
_entry__get_by_path = 28864
_entry__skip_one_fast = 25936
_entry__html_escape = 10560
_entry__i64toa = 3600
_entry__u64toa = 3712
_entry__lspace = 64
_entry__quote = 5104
_entry__skip_array = 21024
_entry__skip_number = 25392
_entry__skip_object = 23088
_entry__skip_one = 25536
_entry__unquote = 7888
_entry__validate_one = 25584
_entry__validate_utf8 = 31040
_entry__validate_utf8_fast = 31984
_entry__value = 15376
_entry__vnumber = 18800
_entry__atof_eisel_lemire64 = 12624
_entry__atof_native = 14768
_entry__decimal_to_f64 = 13056
_entry__right_shift = 39696
_entry__left_shift = 39200
_entry__vsigned = 20352
_entry__vstring = 17424
_entry__vunsigned = 20672
)
const (
_stack__f32toa = 48
_stack__f64toa = 80
_stack__get_by_path = 296
_stack__format_significand = 24
_stack__format_integer = 16
_stack__fsm_exec = 144
_stack__advance_ns = 8
_stack__advance_string = 56
_stack__advance_string_default = 48
_stack__do_skip_number = 48
_stack__get_by_path = 272
_stack__skip_one_fast = 184
_stack__html_escape = 72
_stack__i64toa = 16
_stack__u64toa = 8
_stack__lspace = 8
_stack__quote = 56
_stack__skip_array = 128
_stack__skip_number = 72
_stack__skip_object = 128
_stack__skip_one = 128
_stack__skip_one_fast = 208
_stack__u64toa = 8
_stack__skip_array = 152
_stack__skip_number = 88
_stack__skip_object = 152
_stack__skip_one = 152
_stack__unquote = 72
_stack__validate_one = 128
_stack__validate_one = 152
_stack__validate_utf8 = 48
_stack__validate_utf8_fast = 176
_stack__value = 328
_stack__vnumber = 240
_stack__atof_eisel_lemire64 = 32
_stack__atof_native = 136
_stack__decimal_to_f64 = 80
_stack__right_shift = 8
_stack__left_shift = 24
_stack__vsigned = 16
_stack__vstring = 112
_stack__vunsigned = 16
_stack__vunsigned = 8
)
var (
_ = _subr__f32toa
_ = _subr__f64toa
_ = _subr__get_by_path
_ = _subr__html_escape
_ = _subr__i64toa
_ = _subr__lspace
_ = _subr__quote
_ = _subr__skip_array
_ = _subr__skip_number
_ = _subr__skip_object
_ = _subr__skip_one
_ = _subr__skip_one_fast
_ = _subr__u64toa
_ = _subr__unquote
_ = _subr__validate_one
_ = _subr__validate_utf8
_ = _subr__validate_utf8_fast
_ = _subr__value
_ = _subr__vnumber
_ = _subr__vsigned
_ = _subr__vstring
_ = _subr__vunsigned
const (
_size__f32toa = 3392
_size__f64toa = 2848
_size__format_significand = 464
_size__format_integer = 432
_size__fsm_exec = 1468
_size__advance_ns = 496
_size__advance_string = 1088
_size__advance_string_default = 768
_size__do_skip_number = 1360
_size__get_by_path = 2176
_size__skip_one_fast = 2428
_size__html_escape = 2064
_size__i64toa = 48
_size__u64toa = 1248
_size__lspace = 224
_size__quote = 2736
_size__skip_array = 48
_size__skip_number = 144
_size__skip_object = 48
_size__skip_one = 48
_size__unquote = 2480
_size__validate_one = 48
_size__validate_utf8 = 672
_size__validate_utf8_fast = 2608
_size__value = 1004
_size__vnumber = 1552
_size__atof_eisel_lemire64 = 368
_size__atof_native = 608
_size__decimal_to_f64 = 1712
_size__right_shift = 400
_size__left_shift = 496
_size__vsigned = 320
_size__vstring = 144
_size__vunsigned = 336
)
const (
_ = _stack__f32toa
_ = _stack__f64toa
_ = _stack__get_by_path
_ = _stack__html_escape
_ = _stack__i64toa
_ = _stack__lspace
_ = _stack__quote
_ = _stack__skip_array
_ = _stack__skip_number
_ = _stack__skip_object
_ = _stack__skip_one
_ = _stack__skip_one_fast
_ = _stack__u64toa
_ = _stack__unquote
_ = _stack__validate_one
_ = _stack__validate_utf8
_ = _stack__validate_utf8_fast
_ = _stack__value
_ = _stack__vnumber
_ = _stack__vsigned
_ = _stack__vstring
_ = _stack__vunsigned
var (
_pcsp__f32toa = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{3350, 48},
{3351, 40},
{3353, 32},
{3355, 24},
{3357, 16},
{3359, 8},
{3363, 0},
{3385, 48},
}
_pcsp__f64toa = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{13, 48},
{2788, 56},
{2792, 48},
{2793, 40},
{2795, 32},
{2797, 24},
{2799, 16},
{2801, 8},
{2805, 0},
{2843, 56},
}
_pcsp__format_significand = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{452, 24},
{453, 16},
{455, 8},
{457, 0},
}
_pcsp__format_integer = [][2]uint32{
{1, 0},
{4, 8},
{412, 16},
{413, 8},
{414, 0},
{423, 16},
{424, 8},
{426, 0},
}
_pcsp__fsm_exec = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{13, 48},
{1157, 88},
{1161, 48},
{1162, 40},
{1164, 32},
{1166, 24},
{1168, 16},
{1170, 8},
{1171, 0},
{1468, 88},
}
_pcsp__advance_ns = [][2]uint32{
{1, 0},
{453, 8},
{457, 0},
{481, 8},
{486, 0},
}
_pcsp__advance_string = [][2]uint32{
{14, 0},
{18, 8},
{20, 16},
{22, 24},
{24, 32},
{26, 40},
{27, 48},
{433, 56},
{437, 48},
{438, 40},
{440, 32},
{442, 24},
{444, 16},
{446, 8},
{450, 0},
{1078, 56},
}
_pcsp__advance_string_default = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{332, 48},
{333, 40},
{335, 32},
{337, 24},
{339, 16},
{341, 8},
{345, 0},
{757, 48},
}
_pcsp__do_skip_number = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{1274, 48},
{1275, 40},
{1277, 32},
{1279, 24},
{1281, 16},
{1283, 8},
{1287, 0},
{1360, 48},
}
_pcsp__get_by_path = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{13, 48},
{2049, 88},
{2053, 48},
{2054, 40},
{2056, 32},
{2058, 24},
{2060, 16},
{2062, 8},
{2063, 0},
{2170, 88},
}
_pcsp__skip_one_fast = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{13, 48},
{418, 176},
{419, 168},
{421, 160},
{423, 152},
{425, 144},
{427, 136},
{431, 128},
{2428, 176},
}
_pcsp__html_escape = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{13, 48},
{2045, 72},
{2049, 48},
{2050, 40},
{2052, 32},
{2054, 24},
{2056, 16},
{2058, 8},
{2063, 0},
}
_pcsp__i64toa = [][2]uint32{
{14, 0},
{34, 8},
{36, 0},
}
_pcsp__u64toa = [][2]uint32{
{1, 0},
{161, 8},
{162, 0},
{457, 8},
{458, 0},
{758, 8},
{759, 0},
{1225, 8},
{1227, 0},
}
_pcsp__lspace = [][2]uint32{
{1, 0},
{184, 8},
{188, 0},
{204, 8},
{208, 0},
{215, 8},
{220, 0},
}
_pcsp__quote = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{13, 48},
{2687, 56},
{2691, 48},
{2692, 40},
{2694, 32},
{2696, 24},
{2698, 16},
{2700, 8},
{2704, 0},
{2731, 56},
}
_pcsp__skip_array = [][2]uint32{
{1, 0},
{28, 8},
{34, 0},
}
_pcsp__skip_number = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{100, 40},
{101, 32},
{103, 24},
{105, 16},
{107, 8},
{108, 0},
{139, 40},
}
_pcsp__skip_object = [][2]uint32{
{1, 0},
{28, 8},
{34, 0},
}
_pcsp__skip_one = [][2]uint32{
{1, 0},
{30, 8},
{36, 0},
}
_pcsp__unquote = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{13, 48},
{79, 72},
{83, 48},
{84, 40},
{86, 32},
{88, 24},
{90, 16},
{92, 8},
{96, 0},
{2464, 72},
}
_pcsp__validate_one = [][2]uint32{
{1, 0},
{35, 8},
{41, 0},
}
_pcsp__validate_utf8 = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{11, 40},
{623, 48},
{627, 40},
{628, 32},
{630, 24},
{632, 16},
{634, 8},
{635, 0},
{666, 48},
}
_pcsp__validate_utf8_fast = [][2]uint32{
{1, 0},
{4, 8},
{5, 16},
{1738, 176},
{1739, 168},
{1743, 160},
{2018, 176},
{2019, 168},
{2023, 160},
{2600, 176},
}
_pcsp__value = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{13, 48},
{988, 88},
{992, 48},
{993, 40},
{995, 32},
{997, 24},
{999, 16},
{1001, 8},
{1004, 0},
}
_pcsp__vnumber = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{13, 48},
{803, 104},
{807, 48},
{808, 40},
{810, 32},
{812, 24},
{814, 16},
{816, 8},
{817, 0},
{1547, 104},
}
_pcsp__atof_eisel_lemire64 = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{292, 32},
{293, 24},
{295, 16},
{297, 8},
{298, 0},
{362, 32},
}
_pcsp__atof_native = [][2]uint32{
{1, 0},
{4, 8},
{587, 56},
{591, 8},
{593, 0},
}
_pcsp__decimal_to_f64 = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{13, 48},
{1673, 56},
{1677, 48},
{1678, 40},
{1680, 32},
{1682, 24},
{1684, 16},
{1686, 8},
{1690, 0},
{1702, 56},
}
_pcsp__right_shift = [][2]uint32{
{1, 0},
{318, 8},
{319, 0},
{387, 8},
{388, 0},
{396, 8},
{398, 0},
}
_pcsp__left_shift = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{363, 24},
{364, 16},
{366, 8},
{367, 0},
{470, 24},
{471, 16},
{473, 8},
{474, 0},
{486, 24},
}
_pcsp__vsigned = [][2]uint32{
{1, 0},
{4, 8},
{112, 16},
{113, 8},
{114, 0},
{125, 16},
{126, 8},
{127, 0},
{260, 16},
{261, 8},
{262, 0},
{266, 16},
{267, 8},
{268, 0},
{306, 16},
{307, 8},
{308, 0},
{316, 16},
{317, 8},
{319, 0},
}
_pcsp__vstring = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{11, 40},
{105, 56},
{109, 40},
{110, 32},
{112, 24},
{114, 16},
{116, 8},
{118, 0},
}
_pcsp__vunsigned = [][2]uint32{
{1, 0},
{71, 8},
{72, 0},
{83, 8},
{84, 0},
{107, 8},
{108, 0},
{273, 8},
{274, 0},
{312, 8},
{313, 0},
{320, 8},
{322, 0},
}
)
var Funcs = []loader.CFunc{
{"__native_entry__", 0, 67, 0, nil},
{"_f32toa", _entry__f32toa, _size__f32toa, _stack__f32toa, _pcsp__f32toa},
{"_f64toa", _entry__f64toa, _size__f64toa, _stack__f64toa, _pcsp__f64toa},
{"_format_significand", _entry__format_significand, _size__format_significand, _stack__format_significand, _pcsp__format_significand},
{"_format_integer", _entry__format_integer, _size__format_integer, _stack__format_integer, _pcsp__format_integer},
{"_fsm_exec", _entry__fsm_exec, _size__fsm_exec, _stack__fsm_exec, _pcsp__fsm_exec},
{"_advance_ns", _entry__advance_ns, _size__advance_ns, _stack__advance_ns, _pcsp__advance_ns},
{"_advance_string", _entry__advance_string, _size__advance_string, _stack__advance_string, _pcsp__advance_string},
{"_advance_string_default", _entry__advance_string_default, _size__advance_string_default, _stack__advance_string_default, _pcsp__advance_string_default},
{"_do_skip_number", _entry__do_skip_number, _size__do_skip_number, _stack__do_skip_number, _pcsp__do_skip_number},
{"_get_by_path", _entry__get_by_path, _size__get_by_path, _stack__get_by_path, _pcsp__get_by_path},
{"_skip_one_fast", _entry__skip_one_fast, _size__skip_one_fast, _stack__skip_one_fast, _pcsp__skip_one_fast},
{"_html_escape", _entry__html_escape, _size__html_escape, _stack__html_escape, _pcsp__html_escape},
{"_i64toa", _entry__i64toa, _size__i64toa, _stack__i64toa, _pcsp__i64toa},
{"_u64toa", _entry__u64toa, _size__u64toa, _stack__u64toa, _pcsp__u64toa},
{"_lspace", _entry__lspace, _size__lspace, _stack__lspace, _pcsp__lspace},
{"_quote", _entry__quote, _size__quote, _stack__quote, _pcsp__quote},
{"_skip_array", _entry__skip_array, _size__skip_array, _stack__skip_array, _pcsp__skip_array},
{"_skip_number", _entry__skip_number, _size__skip_number, _stack__skip_number, _pcsp__skip_number},
{"_skip_object", _entry__skip_object, _size__skip_object, _stack__skip_object, _pcsp__skip_object},
{"_skip_one", _entry__skip_one, _size__skip_one, _stack__skip_one, _pcsp__skip_one},
{"_unquote", _entry__unquote, _size__unquote, _stack__unquote, _pcsp__unquote},
{"_validate_one", _entry__validate_one, _size__validate_one, _stack__validate_one, _pcsp__validate_one},
{"_validate_utf8", _entry__validate_utf8, _size__validate_utf8, _stack__validate_utf8, _pcsp__validate_utf8},
{"_validate_utf8_fast", _entry__validate_utf8_fast, _size__validate_utf8_fast, _stack__validate_utf8_fast, _pcsp__validate_utf8_fast},
{"_value", _entry__value, _size__value, _stack__value, _pcsp__value},
{"_vnumber", _entry__vnumber, _size__vnumber, _stack__vnumber, _pcsp__vnumber},
{"_atof_eisel_lemire64", _entry__atof_eisel_lemire64, _size__atof_eisel_lemire64, _stack__atof_eisel_lemire64, _pcsp__atof_eisel_lemire64},
{"_atof_native", _entry__atof_native, _size__atof_native, _stack__atof_native, _pcsp__atof_native},
{"_decimal_to_f64", _entry__decimal_to_f64, _size__decimal_to_f64, _stack__decimal_to_f64, _pcsp__decimal_to_f64},
{"_right_shift", _entry__right_shift, _size__right_shift, _stack__right_shift, _pcsp__right_shift},
{"_left_shift", _entry__left_shift, _size__left_shift, _stack__left_shift, _pcsp__left_shift},
{"_vsigned", _entry__vsigned, _size__vsigned, _stack__vsigned, _pcsp__vsigned},
{"_vstring", _entry__vstring, _size__vstring, _stack__vstring, _pcsp__vstring},
{"_vunsigned", _entry__vunsigned, _size__vunsigned, _stack__vunsigned, _pcsp__vunsigned},
}

File diff suppressed because it is too large Load Diff

@ -24,6 +24,8 @@ import (
`github.com/bytedance/sonic/internal/native/avx2`
`github.com/bytedance/sonic/internal/native/sse`
`github.com/bytedance/sonic/internal/native/types`
`github.com/bytedance/sonic/internal/rt`
`github.com/bytedance/sonic/loader`
)
const (
@ -40,8 +42,9 @@ var (
)
var (
S_quote uintptr
S_unquote uintptr
S_quote uintptr
S_unquote uintptr
S_html_escape uintptr
)
var (
@ -53,140 +56,148 @@ var (
)
var (
S_skip_one uintptr
S_skip_one_fast uintptr
S_get_by_path uintptr
S_skip_array uintptr
S_skip_object uintptr
S_skip_number uintptr
S_skip_one uintptr
S_skip_one_fast uintptr
S_get_by_path uintptr
S_skip_array uintptr
S_skip_object uintptr
S_skip_number uintptr
)
var (
S_validate_one uintptr
S_validate_utf8 uintptr
S_validate_utf8_fast uintptr
)
var (
__Quote func(s unsafe.Pointer, nb int, dp unsafe.Pointer, dn unsafe.Pointer, flags uint64) int
__Unquote func(s unsafe.Pointer, nb int, dp unsafe.Pointer, ep unsafe.Pointer, flags uint64) int
__HTMLEscape func(s unsafe.Pointer, nb int, dp unsafe.Pointer, dn unsafe.Pointer) int
__Value func(s unsafe.Pointer, n int, p int, v unsafe.Pointer, flags uint64) int
__SkipOne func(s unsafe.Pointer, p unsafe.Pointer, m unsafe.Pointer, flags uint64) int
__SkipOneFast func(s unsafe.Pointer, p unsafe.Pointer) int
__GetByPath func(s unsafe.Pointer, p unsafe.Pointer, path unsafe.Pointer, m unsafe.Pointer) int
__ValidateOne func(s unsafe.Pointer, p unsafe.Pointer, m unsafe.Pointer) int
__I64toa func(out unsafe.Pointer, val int64) (ret int)
__U64toa func(out unsafe.Pointer, val uint64) (ret int)
__F64toa func(out unsafe.Pointer, val float64) (ret int)
__ValidateUTF8 func(s unsafe.Pointer, p unsafe.Pointer, m unsafe.Pointer) (ret int)
__ValidateUTF8Fast func(s unsafe.Pointer) (ret int)
)
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func Quote(s unsafe.Pointer, nb int, dp unsafe.Pointer, dn *int, flags uint64) int
func Quote(s unsafe.Pointer, nb int, dp unsafe.Pointer, dn *int, flags uint64) int {
return __Quote(rt.NoEscape(unsafe.Pointer(s)), nb, rt.NoEscape(unsafe.Pointer(dp)), rt.NoEscape(unsafe.Pointer(dn)), flags)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func Unquote(s unsafe.Pointer, nb int, dp unsafe.Pointer, ep *int, flags uint64) int
func Unquote(s unsafe.Pointer, nb int, dp unsafe.Pointer, ep *int, flags uint64) int {
return __Unquote(rt.NoEscape(unsafe.Pointer(s)), nb, rt.NoEscape(unsafe.Pointer(dp)), rt.NoEscape(unsafe.Pointer(ep)), flags)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func HTMLEscape(s unsafe.Pointer, nb int, dp unsafe.Pointer, dn *int) int
func HTMLEscape(s unsafe.Pointer, nb int, dp unsafe.Pointer, dn *int) int {
return __HTMLEscape(rt.NoEscape(unsafe.Pointer(s)), nb, rt.NoEscape(unsafe.Pointer(dp)), rt.NoEscape(unsafe.Pointer(dn)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func Value(s unsafe.Pointer, n int, p int, v *types.JsonState, flags uint64) int
func Value(s unsafe.Pointer, n int, p int, v *types.JsonState, flags uint64) int {
return __Value(rt.NoEscape(unsafe.Pointer(s)), n, p, rt.NoEscape(unsafe.Pointer(v)), flags)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func SkipOne(s *string, p *int, m *types.StateMachine, flags uint64) int
func SkipOne(s *string, p *int, m *types.StateMachine, flags uint64) int {
return __SkipOne(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(m)), flags)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func SkipOneFast(s *string, p *int) int
func SkipOneFast(s *string, p *int) int {
return __SkipOneFast(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func GetByPath(s *string, p *int, path *[]interface{}, m *types.StateMachine) int
func GetByPath(s *string, p *int, path *[]interface{}, m *types.StateMachine) int {
return __GetByPath(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(path)), rt.NoEscape(unsafe.Pointer(m)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func ValidateOne(s *string, p *int, m *types.StateMachine) int
func ValidateOne(s *string, p *int, m *types.StateMachine) int {
return __ValidateOne(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(m)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func I64toa(out *byte, val int64) (ret int)
func I64toa(out *byte, val int64) (ret int) {
return __I64toa(rt.NoEscape(unsafe.Pointer(out)), val)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func U64toa(out *byte, val uint64) (ret int)
func U64toa(out *byte, val uint64) (ret int) {
return __U64toa(rt.NoEscape(unsafe.Pointer(out)), val)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func F64toa(out *byte, val float64) (ret int)
func F64toa(out *byte, val float64) (ret int) {
return __F64toa(rt.NoEscape(unsafe.Pointer(out)), val)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func ValidateUTF8(s *string, p *int, m *types.StateMachine) (ret int)
func ValidateUTF8(s *string, p *int, m *types.StateMachine) (ret int) {
return __ValidateUTF8(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(m)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func ValidateUTF8Fast(s *string) (ret int)
func ValidateUTF8Fast(s *string) (ret int) {
return __ValidateUTF8Fast(rt.NoEscape(unsafe.Pointer(s)))
}
var stubs = []loader.GoC{
{"_f64toa", &S_f64toa, &__F64toa},
{"_f32toa", &S_f32toa, nil},
{"_i64toa", &S_i64toa, &__I64toa},
{"_u64toa", &S_u64toa, &__U64toa},
{"_lspace", &S_lspace, nil},
{"_quote", &S_quote, &__Quote},
{"_unquote", &S_unquote, &__Unquote},
{"_html_escape", &S_html_escape, &__HTMLEscape},
{"_value", &S_value, &__Value},
{"_vstring", &S_vstring, nil},
{"_vnumber", &S_vnumber, nil},
{"_vsigned", &S_vsigned, nil},
{"_vunsigned", &S_vunsigned, nil},
{"_skip_one", &S_skip_one, &__SkipOne},
{"_skip_one_fast", &S_skip_one_fast, &__SkipOneFast},
{"_get_by_path", &S_get_by_path, &__GetByPath},
{"_skip_array", &S_skip_array, nil},
{"_skip_object", &S_skip_object, nil},
{"_skip_number", &S_skip_number, nil},
{"_validate_one", &S_validate_one, &__ValidateOne},
{"_validate_utf8", &S_validate_utf8, &__ValidateUTF8},
{"_validate_utf8_fast", &S_validate_utf8_fast, &__ValidateUTF8Fast},
}
func useAVX() {
S_f64toa = avx.S_f64toa
S_f32toa = avx.S_f32toa
S_i64toa = avx.S_i64toa
S_u64toa = avx.S_u64toa
S_lspace = avx.S_lspace
S_quote = avx.S_quote
S_unquote = avx.S_unquote
S_value = avx.S_value
S_vstring = avx.S_vstring
S_vnumber = avx.S_vnumber
S_vsigned = avx.S_vsigned
S_vunsigned = avx.S_vunsigned
S_skip_one = avx.S_skip_one
S_skip_one_fast = avx.S_skip_one_fast
S_skip_array = avx.S_skip_array
S_skip_object = avx.S_skip_object
S_skip_number = avx.S_skip_number
S_get_by_path = avx.S_get_by_path
loader.WrapGoC(avx.Text__native_entry__, avx.Funcs, stubs, "avx", "avx/native.c")
}
func useAVX2() {
S_f64toa = avx2.S_f64toa
S_f32toa = avx2.S_f32toa
S_i64toa = avx2.S_i64toa
S_u64toa = avx2.S_u64toa
S_lspace = avx2.S_lspace
S_quote = avx2.S_quote
S_unquote = avx2.S_unquote
S_value = avx2.S_value
S_vstring = avx2.S_vstring
S_vnumber = avx2.S_vnumber
S_vsigned = avx2.S_vsigned
S_vunsigned = avx2.S_vunsigned
S_skip_one = avx2.S_skip_one
S_skip_one_fast = avx2.S_skip_one_fast
S_skip_array = avx2.S_skip_array
S_skip_object = avx2.S_skip_object
S_skip_number = avx2.S_skip_number
S_get_by_path = avx2.S_get_by_path
loader.WrapGoC(avx2.Text__native_entry__, avx2.Funcs, stubs, "avx2", "avx2/native.c")
}
func useSSE() {
S_f64toa = sse.S_f64toa
S_f32toa = sse.S_f32toa
S_i64toa = sse.S_i64toa
S_u64toa = sse.S_u64toa
S_lspace = sse.S_lspace
S_quote = sse.S_quote
S_unquote = sse.S_unquote
S_value = sse.S_value
S_vstring = sse.S_vstring
S_vnumber = sse.S_vnumber
S_vsigned = sse.S_vsigned
S_vunsigned = sse.S_vunsigned
S_skip_one = sse.S_skip_one
S_skip_one_fast = sse.S_skip_one_fast
S_skip_array = sse.S_skip_array
S_skip_object = sse.S_skip_object
S_skip_number = sse.S_skip_number
S_get_by_path = sse.S_get_by_path
loader.WrapGoC(sse.Text__native_entry__, sse.Funcs, stubs, "sse", "sse/native.c")
}
func init() {

@ -1,137 +0,0 @@
//
// Copyright 2021 ByteDance Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "go_asm.h"
#include "funcdata.h"
#include "textflag.h"
TEXT ·Quote(SB), NOSPLIT, $0 - 48
CMPB github·combytedancesonicinternalcpu·HasAVX2(SB), $0
JE 2(PC)
JMP github·combytedancesonicinternalnativeavx2·__quote(SB)
CMPB github·combytedancesonicinternalcpu·HasAVX(SB), $0
JE 2(PC)
JMP github·combytedancesonicinternalnativeavx·__quote(SB)
JMP github·combytedancesonicinternalnativesse·__quote(SB)
TEXT ·Unquote(SB), NOSPLIT, $0 - 48
CMPB github·combytedancesonicinternalcpu·HasAVX2(SB), $0
JE 2(PC)
JMP github·combytedancesonicinternalnativeavx2·__unquote(SB)
CMPB github·combytedancesonicinternalcpu·HasAVX(SB), $0
JE 2(PC)
JMP github·combytedancesonicinternalnativeavx·__unquote(SB)
JMP github·combytedancesonicinternalnativesse·__unquote(SB)
TEXT ·HTMLEscape(SB), NOSPLIT, $0 - 40
CMPB github·combytedancesonicinternalcpu·HasAVX2(SB), $0
JE 2(PC)
JMP github·combytedancesonicinternalnativeavx2·__html_escape(SB)
CMPB github·combytedancesonicinternalcpu·HasAVX(SB), $0
JE 2(PC)
JMP github·combytedancesonicinternalnativeavx·__html_escape(SB)
JMP github·combytedancesonicinternalnativesse·__html_escape(SB)
TEXT ·Value(SB), NOSPLIT, $0 - 48
CMPB github·combytedancesonicinternalcpu·HasAVX2(SB), $0
JE 2(PC)
JMP github·combytedancesonicinternalnativeavx2·__value(SB)
CMPB github·combytedancesonicinternalcpu·HasAVX(SB), $0
JE 2(PC)
JMP github·combytedancesonicinternalnativeavx·__value(SB)
JMP github·combytedancesonicinternalnativesse·__value(SB)
TEXT ·SkipOne(SB), NOSPLIT, $0 - 40
CMPB github·combytedancesonicinternalcpu·HasAVX2(SB), $0
JE 2(PC)
JMP github·combytedancesonicinternalnativeavx2·__skip_one(SB)
CMPB github·combytedancesonicinternalcpu·HasAVX(SB), $0
JE 2(PC)
JMP github·combytedancesonicinternalnativeavx·__skip_one(SB)
JMP github·combytedancesonicinternalnativesse·__skip_one(SB)
TEXT ·SkipOneFast(SB), NOSPLIT, $0 - 24
CMPB github·combytedancesonicinternalcpu·HasAVX2(SB), $0
JE 2(PC)
JMP github·combytedancesonicinternalnativeavx2·__skip_one_fast(SB)
CMPB github·combytedancesonicinternalcpu·HasAVX(SB), $0
JE 2(PC)
JMP github·combytedancesonicinternalnativeavx·__skip_one_fast(SB)
JMP github·combytedancesonicinternalnativesse·__skip_one_fast(SB)
TEXT ·GetByPath(SB), NOSPLIT, $0 - 40
CMPB github·combytedancesonicinternalcpu·HasAVX2(SB), $0
JE 2(PC)
JMP github·combytedancesonicinternalnativeavx2·__get_by_path(SB)
CMPB github·combytedancesonicinternalcpu·HasAVX(SB), $0
JE 2(PC)
JMP github·combytedancesonicinternalnativeavx·__get_by_path(SB)
JMP github·combytedancesonicinternalnativesse·__get_by_path(SB)
TEXT ·ValidateOne(SB), NOSPLIT, $0 - 32
CMPB github·combytedancesonicinternalcpu·HasAVX2(SB), $0
JE 2(PC)
JMP github·combytedancesonicinternalnativeavx2·__validate_one(SB)
CMPB github·combytedancesonicinternalcpu·HasAVX(SB), $0
JE 2(PC)
JMP github·combytedancesonicinternalnativeavx·__validate_one(SB)
JMP github·combytedancesonicinternalnativesse·__validate_one(SB)
TEXT ·ValidateUTF8(SB), NOSPLIT, $0 - 40
CMPB github·combytedancesonicinternalcpu·HasAVX2(SB), $0
JE 2(PC)
JMP github·combytedancesonicinternalnativeavx2·__validate_utf8(SB)
CMPB github·combytedancesonicinternalcpu·HasAVX(SB), $0
JE 2(PC)
JMP github·combytedancesonicinternalnativeavx·__validate_utf8(SB)
JMP github·combytedancesonicinternalnativesse·__validate_utf8(SB)
TEXT ·ValidateUTF8Fast(SB), NOSPLIT, $0 - 16
CMPB github·combytedancesonicinternalcpu·HasAVX2(SB), $0
JE 2(PC)
JMP github·combytedancesonicinternalnativeavx2·__validate_utf8_fast(SB)
CMPB github·combytedancesonicinternalcpu·HasAVX(SB), $0
JE 2(PC)
JMP github·combytedancesonicinternalnativeavx·__validate_utf8_fast(SB)
JMP github·combytedancesonicinternalnativesse·__validate_utf8_fast(SB)
TEXT ·I64toa(SB), NOSPLIT, $0 - 32
CMPB github·combytedancesonicinternalcpu·HasAVX2(SB), $0
JE 2(PC)
JMP github·combytedancesonicinternalnativeavx2·__i64toa(SB)
CMPB github·combytedancesonicinternalcpu·HasAVX(SB), $0
JE 2(PC)
JMP github·combytedancesonicinternalnativeavx·__i64toa(SB)
JMP github·combytedancesonicinternalnativesse·__i64toa(SB)
TEXT ·U64toa(SB), NOSPLIT, $0 - 32
CMPB github·combytedancesonicinternalcpu·HasAVX2(SB), $0
JE 2(PC)
JMP github·combytedancesonicinternalnativeavx2·__u64toa(SB)
CMPB github·combytedancesonicinternalcpu·HasAVX(SB), $0
JE 2(PC)
JMP github·combytedancesonicinternalnativeavx·__u64toa(SB)
JMP github·combytedancesonicinternalnativesse·__u64toa(SB)
TEXT ·F64toa(SB), NOSPLIT, $0 - 32
CMPB github·combytedancesonicinternalcpu·HasAVX2(SB), $0
JE 2(PC)
JMP github·combytedancesonicinternalnativeavx2·__f64toa(SB)
CMPB github·combytedancesonicinternalcpu·HasAVX(SB), $0
JE 2(PC)
JMP github·combytedancesonicinternalnativeavx·__f64toa(SB)
JMP github·combytedancesonicinternalnativesse·__f64toa(SB)

@ -1,3 +1,5 @@
// Code generated by Makefile, DO NOT EDIT.
/*
* Copyright 2021 ByteDance Inc.
*
@ -17,35 +19,35 @@
package {{PACKAGE}}
import (
`encoding/json`
`math`
`math/rand`
`strconv`
`testing`
`math/rand`
`encoding/json`
`github.com/stretchr/testify/assert`
)
func TestFastFloat_Encode(t *testing.T) {
var buf [64]byte
assert.Equal(t, "0" , string(buf[:__f64toa(&buf[0], 0)]))
assert.Equal(t, "-0" , string(buf[:__f64toa(&buf[0], math.Float64frombits(0x8000000000000000))]))
assert.Equal(t, "12340000000" , string(buf[:__f64toa(&buf[0], 1234e7)]))
assert.Equal(t, "12.34" , string(buf[:__f64toa(&buf[0], 1234e-2)]))
assert.Equal(t, "0.001234" , string(buf[:__f64toa(&buf[0], 1234e-6)]))
assert.Equal(t, "1e+30" , string(buf[:__f64toa(&buf[0], 1e30)]))
assert.Equal(t, "1.234e+33" , string(buf[:__f64toa(&buf[0], 1234e30)]))
assert.Equal(t, "1.234e+308" , string(buf[:__f64toa(&buf[0], 1234e305)]))
assert.Equal(t, "1.234e-317" , string(buf[:__f64toa(&buf[0], 1234e-320)]))
assert.Equal(t, "1.7976931348623157e+308" , string(buf[:__f64toa(&buf[0], 1.7976931348623157e308)]))
assert.Equal(t, "-12340000000" , string(buf[:__f64toa(&buf[0], -1234e7)]))
assert.Equal(t, "-12.34" , string(buf[:__f64toa(&buf[0], -1234e-2)]))
assert.Equal(t, "-0.001234" , string(buf[:__f64toa(&buf[0], -1234e-6)]))
assert.Equal(t, "-1e+30" , string(buf[:__f64toa(&buf[0], -1e30)]))
assert.Equal(t, "-1.234e+33" , string(buf[:__f64toa(&buf[0], -1234e30)]))
assert.Equal(t, "-1.234e+308" , string(buf[:__f64toa(&buf[0], -1234e305)]))
assert.Equal(t, "-1.234e-317" , string(buf[:__f64toa(&buf[0], -1234e-320)]))
assert.Equal(t, "-2.2250738585072014e-308" , string(buf[:__f64toa(&buf[0], -2.2250738585072014e-308)]))
assert.Equal(t, "0" , string(buf[:f64toa(&buf[0], 0)]))
assert.Equal(t, "-0" , string(buf[:f64toa(&buf[0], math.Float64frombits(0x8000000000000000))]))
assert.Equal(t, "12340000000" , string(buf[:f64toa(&buf[0], 1234e7)]))
assert.Equal(t, "12.34" , string(buf[:f64toa(&buf[0], 1234e-2)]))
assert.Equal(t, "0.001234" , string(buf[:f64toa(&buf[0], 1234e-6)]))
assert.Equal(t, "1e+30" , string(buf[:f64toa(&buf[0], 1e30)]))
assert.Equal(t, "1.234e+33" , string(buf[:f64toa(&buf[0], 1234e30)]))
assert.Equal(t, "1.234e+308" , string(buf[:f64toa(&buf[0], 1234e305)]))
assert.Equal(t, "1.234e-317" , string(buf[:f64toa(&buf[0], 1234e-320)]))
assert.Equal(t, "1.7976931348623157e+308" , string(buf[:f64toa(&buf[0], 1.7976931348623157e308)]))
assert.Equal(t, "-12340000000" , string(buf[:f64toa(&buf[0], -1234e7)]))
assert.Equal(t, "-12.34" , string(buf[:f64toa(&buf[0], -1234e-2)]))
assert.Equal(t, "-0.001234" , string(buf[:f64toa(&buf[0], -1234e-6)]))
assert.Equal(t, "-1e+30" , string(buf[:f64toa(&buf[0], -1e30)]))
assert.Equal(t, "-1.234e+33" , string(buf[:f64toa(&buf[0], -1234e30)]))
assert.Equal(t, "-1.234e+308" , string(buf[:f64toa(&buf[0], -1234e305)]))
assert.Equal(t, "-1.234e-317" , string(buf[:f64toa(&buf[0], -1234e-320)]))
assert.Equal(t, "-2.2250738585072014e-308" , string(buf[:f64toa(&buf[0], -2.2250738585072014e-308)]))
}
func TestFastFloat_Random(t *testing.T) {
@ -56,7 +58,7 @@ func TestFastFloat_Random(t *testing.T) {
f64 := math.Float64frombits(b64)
jout, jerr := json.Marshal(f64)
n := __f64toa(&buf[0], f64)
n := f64toa(&buf[0], f64)
if jerr == nil {
assert.Equal(t, jout, buf[:n])
} else {
@ -65,7 +67,7 @@ func TestFastFloat_Random(t *testing.T) {
f32 := math.Float32frombits(rand.Uint32())
jout, jerr = json.Marshal(f32)
n = __f32toa(&buf[0], f32)
n = f32toa(&buf[0], f32)
if jerr == nil {
assert.Equal(t, jout, buf[:n])
} else {
@ -97,7 +99,7 @@ func BenchmarkParseFloat64(b *testing.B) {
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { strconv.AppendFloat(buf[:0], c.float, 'g', -1, 64) }},
}, {
name: "FastFloat",
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { __f64toa(&buf[0], c.float) }},
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { f64toa(&buf[0], c.float) }},
}}
for _, bm := range f64bench {
name := bm.name + "_" + c.name
@ -128,11 +130,11 @@ func BenchmarkParseFloat32(b *testing.B) {
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { strconv.AppendFloat(buf[:0], float64(c.float), 'g', -1, 32) }},
}, {
name: "FastFloat32",
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { __f32toa(&buf[0], c.float) }},
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { f32toa(&buf[0], c.float) }},
}}
for _, bm := range bench {
name := bm.name + "_" + c.name
b.Run(name, bm.test)
}
}
}
}

@ -1,3 +1,5 @@
// Code generated by Makefile, DO NOT EDIT.
/*
* Copyright 2021 ByteDance Inc.
*
@ -26,126 +28,126 @@ import (
func TestFastInt_IntToString(t *testing.T) {
var buf [32]byte
assert.Equal(t, "0" , string(buf[:__i64toa(&buf[0], 0)]))
assert.Equal(t, "1" , string(buf[:__i64toa(&buf[0], 1)]))
assert.Equal(t, "12" , string(buf[:__i64toa(&buf[0], 12)]))
assert.Equal(t, "123" , string(buf[:__i64toa(&buf[0], 123)]))
assert.Equal(t, "1234" , string(buf[:__i64toa(&buf[0], 1234)]))
assert.Equal(t, "12345" , string(buf[:__i64toa(&buf[0], 12345)]))
assert.Equal(t, "123456" , string(buf[:__i64toa(&buf[0], 123456)]))
assert.Equal(t, "1234567" , string(buf[:__i64toa(&buf[0], 1234567)]))
assert.Equal(t, "12345678" , string(buf[:__i64toa(&buf[0], 12345678)]))
assert.Equal(t, "123456789" , string(buf[:__i64toa(&buf[0], 123456789)]))
assert.Equal(t, "1234567890" , string(buf[:__i64toa(&buf[0], 1234567890)]))
assert.Equal(t, "12345678901" , string(buf[:__i64toa(&buf[0], 12345678901)]))
assert.Equal(t, "123456789012" , string(buf[:__i64toa(&buf[0], 123456789012)]))
assert.Equal(t, "1234567890123" , string(buf[:__i64toa(&buf[0], 1234567890123)]))
assert.Equal(t, "12345678901234" , string(buf[:__i64toa(&buf[0], 12345678901234)]))
assert.Equal(t, "123456789012345" , string(buf[:__i64toa(&buf[0], 123456789012345)]))
assert.Equal(t, "1234567890123456" , string(buf[:__i64toa(&buf[0], 1234567890123456)]))
assert.Equal(t, "12345678901234567" , string(buf[:__i64toa(&buf[0], 12345678901234567)]))
assert.Equal(t, "123456789012345678" , string(buf[:__i64toa(&buf[0], 123456789012345678)]))
assert.Equal(t, "1234567890123456789" , string(buf[:__i64toa(&buf[0], 1234567890123456789)]))
assert.Equal(t, "9223372036854775807" , string(buf[:__i64toa(&buf[0], 9223372036854775807)]))
assert.Equal(t, "-1" , string(buf[:__i64toa(&buf[0], -1)]))
assert.Equal(t, "-12" , string(buf[:__i64toa(&buf[0], -12)]))
assert.Equal(t, "-123" , string(buf[:__i64toa(&buf[0], -123)]))
assert.Equal(t, "-1234" , string(buf[:__i64toa(&buf[0], -1234)]))
assert.Equal(t, "-12345" , string(buf[:__i64toa(&buf[0], -12345)]))
assert.Equal(t, "-123456" , string(buf[:__i64toa(&buf[0], -123456)]))
assert.Equal(t, "-1234567" , string(buf[:__i64toa(&buf[0], -1234567)]))
assert.Equal(t, "-12345678" , string(buf[:__i64toa(&buf[0], -12345678)]))
assert.Equal(t, "-123456789" , string(buf[:__i64toa(&buf[0], -123456789)]))
assert.Equal(t, "-1234567890" , string(buf[:__i64toa(&buf[0], -1234567890)]))
assert.Equal(t, "-12345678901" , string(buf[:__i64toa(&buf[0], -12345678901)]))
assert.Equal(t, "-123456789012" , string(buf[:__i64toa(&buf[0], -123456789012)]))
assert.Equal(t, "-1234567890123" , string(buf[:__i64toa(&buf[0], -1234567890123)]))
assert.Equal(t, "-12345678901234" , string(buf[:__i64toa(&buf[0], -12345678901234)]))
assert.Equal(t, "-123456789012345" , string(buf[:__i64toa(&buf[0], -123456789012345)]))
assert.Equal(t, "-1234567890123456" , string(buf[:__i64toa(&buf[0], -1234567890123456)]))
assert.Equal(t, "-12345678901234567" , string(buf[:__i64toa(&buf[0], -12345678901234567)]))
assert.Equal(t, "-123456789012345678" , string(buf[:__i64toa(&buf[0], -123456789012345678)]))
assert.Equal(t, "-1234567890123456789" , string(buf[:__i64toa(&buf[0], -1234567890123456789)]))
assert.Equal(t, "-9223372036854775808" , string(buf[:__i64toa(&buf[0], -9223372036854775808)]))
assert.Equal(t, "0" , string(buf[:i64toa(&buf[0], 0)]))
assert.Equal(t, "1" , string(buf[:i64toa(&buf[0], 1)]))
assert.Equal(t, "12" , string(buf[:i64toa(&buf[0], 12)]))
assert.Equal(t, "123" , string(buf[:i64toa(&buf[0], 123)]))
assert.Equal(t, "1234" , string(buf[:i64toa(&buf[0], 1234)]))
assert.Equal(t, "12345" , string(buf[:i64toa(&buf[0], 12345)]))
assert.Equal(t, "123456" , string(buf[:i64toa(&buf[0], 123456)]))
assert.Equal(t, "1234567" , string(buf[:i64toa(&buf[0], 1234567)]))
assert.Equal(t, "12345678" , string(buf[:i64toa(&buf[0], 12345678)]))
assert.Equal(t, "123456789" , string(buf[:i64toa(&buf[0], 123456789)]))
assert.Equal(t, "1234567890" , string(buf[:i64toa(&buf[0], 1234567890)]))
assert.Equal(t, "12345678901" , string(buf[:i64toa(&buf[0], 12345678901)]))
assert.Equal(t, "123456789012" , string(buf[:i64toa(&buf[0], 123456789012)]))
assert.Equal(t, "1234567890123" , string(buf[:i64toa(&buf[0], 1234567890123)]))
assert.Equal(t, "12345678901234" , string(buf[:i64toa(&buf[0], 12345678901234)]))
assert.Equal(t, "123456789012345" , string(buf[:i64toa(&buf[0], 123456789012345)]))
assert.Equal(t, "1234567890123456" , string(buf[:i64toa(&buf[0], 1234567890123456)]))
assert.Equal(t, "12345678901234567" , string(buf[:i64toa(&buf[0], 12345678901234567)]))
assert.Equal(t, "123456789012345678" , string(buf[:i64toa(&buf[0], 123456789012345678)]))
assert.Equal(t, "1234567890123456789" , string(buf[:i64toa(&buf[0], 1234567890123456789)]))
assert.Equal(t, "9223372036854775807" , string(buf[:i64toa(&buf[0], 9223372036854775807)]))
assert.Equal(t, "-1" , string(buf[:i64toa(&buf[0], -1)]))
assert.Equal(t, "-12" , string(buf[:i64toa(&buf[0], -12)]))
assert.Equal(t, "-123" , string(buf[:i64toa(&buf[0], -123)]))
assert.Equal(t, "-1234" , string(buf[:i64toa(&buf[0], -1234)]))
assert.Equal(t, "-12345" , string(buf[:i64toa(&buf[0], -12345)]))
assert.Equal(t, "-123456" , string(buf[:i64toa(&buf[0], -123456)]))
assert.Equal(t, "-1234567" , string(buf[:i64toa(&buf[0], -1234567)]))
assert.Equal(t, "-12345678" , string(buf[:i64toa(&buf[0], -12345678)]))
assert.Equal(t, "-123456789" , string(buf[:i64toa(&buf[0], -123456789)]))
assert.Equal(t, "-1234567890" , string(buf[:i64toa(&buf[0], -1234567890)]))
assert.Equal(t, "-12345678901" , string(buf[:i64toa(&buf[0], -12345678901)]))
assert.Equal(t, "-123456789012" , string(buf[:i64toa(&buf[0], -123456789012)]))
assert.Equal(t, "-1234567890123" , string(buf[:i64toa(&buf[0], -1234567890123)]))
assert.Equal(t, "-12345678901234" , string(buf[:i64toa(&buf[0], -12345678901234)]))
assert.Equal(t, "-123456789012345" , string(buf[:i64toa(&buf[0], -123456789012345)]))
assert.Equal(t, "-1234567890123456" , string(buf[:i64toa(&buf[0], -1234567890123456)]))
assert.Equal(t, "-12345678901234567" , string(buf[:i64toa(&buf[0], -12345678901234567)]))
assert.Equal(t, "-123456789012345678" , string(buf[:i64toa(&buf[0], -123456789012345678)]))
assert.Equal(t, "-1234567890123456789" , string(buf[:i64toa(&buf[0], -1234567890123456789)]))
assert.Equal(t, "-9223372036854775808" , string(buf[:i64toa(&buf[0], -9223372036854775808)]))
}
func TestFastInt_UintToString(t *testing.T) {
var buf [32]byte
assert.Equal(t, "0" , string(buf[:__u64toa(&buf[0], 0)]))
assert.Equal(t, "1" , string(buf[:__u64toa(&buf[0], 1)]))
assert.Equal(t, "12" , string(buf[:__u64toa(&buf[0], 12)]))
assert.Equal(t, "123" , string(buf[:__u64toa(&buf[0], 123)]))
assert.Equal(t, "1234" , string(buf[:__u64toa(&buf[0], 1234)]))
assert.Equal(t, "12345" , string(buf[:__u64toa(&buf[0], 12345)]))
assert.Equal(t, "123456" , string(buf[:__u64toa(&buf[0], 123456)]))
assert.Equal(t, "1234567" , string(buf[:__u64toa(&buf[0], 1234567)]))
assert.Equal(t, "12345678" , string(buf[:__u64toa(&buf[0], 12345678)]))
assert.Equal(t, "123456789" , string(buf[:__u64toa(&buf[0], 123456789)]))
assert.Equal(t, "1234567890" , string(buf[:__u64toa(&buf[0], 1234567890)]))
assert.Equal(t, "12345678901" , string(buf[:__u64toa(&buf[0], 12345678901)]))
assert.Equal(t, "123456789012" , string(buf[:__u64toa(&buf[0], 123456789012)]))
assert.Equal(t, "1234567890123" , string(buf[:__u64toa(&buf[0], 1234567890123)]))
assert.Equal(t, "12345678901234" , string(buf[:__u64toa(&buf[0], 12345678901234)]))
assert.Equal(t, "123456789012345" , string(buf[:__u64toa(&buf[0], 123456789012345)]))
assert.Equal(t, "1234567890123456" , string(buf[:__u64toa(&buf[0], 1234567890123456)]))
assert.Equal(t, "12345678901234567" , string(buf[:__u64toa(&buf[0], 12345678901234567)]))
assert.Equal(t, "123456789012345678" , string(buf[:__u64toa(&buf[0], 123456789012345678)]))
assert.Equal(t, "1234567890123456789" , string(buf[:__u64toa(&buf[0], 1234567890123456789)]))
assert.Equal(t, "12345678901234567890" , string(buf[:__u64toa(&buf[0], 12345678901234567890)]))
assert.Equal(t, "18446744073709551615" , string(buf[:__u64toa(&buf[0], 18446744073709551615)]))
assert.Equal(t, "0" , string(buf[:u64toa(&buf[0], 0)]))
assert.Equal(t, "1" , string(buf[:u64toa(&buf[0], 1)]))
assert.Equal(t, "12" , string(buf[:u64toa(&buf[0], 12)]))
assert.Equal(t, "123" , string(buf[:u64toa(&buf[0], 123)]))
assert.Equal(t, "1234" , string(buf[:u64toa(&buf[0], 1234)]))
assert.Equal(t, "12345" , string(buf[:u64toa(&buf[0], 12345)]))
assert.Equal(t, "123456" , string(buf[:u64toa(&buf[0], 123456)]))
assert.Equal(t, "1234567" , string(buf[:u64toa(&buf[0], 1234567)]))
assert.Equal(t, "12345678" , string(buf[:u64toa(&buf[0], 12345678)]))
assert.Equal(t, "123456789" , string(buf[:u64toa(&buf[0], 123456789)]))
assert.Equal(t, "1234567890" , string(buf[:u64toa(&buf[0], 1234567890)]))
assert.Equal(t, "12345678901" , string(buf[:u64toa(&buf[0], 12345678901)]))
assert.Equal(t, "123456789012" , string(buf[:u64toa(&buf[0], 123456789012)]))
assert.Equal(t, "1234567890123" , string(buf[:u64toa(&buf[0], 1234567890123)]))
assert.Equal(t, "12345678901234" , string(buf[:u64toa(&buf[0], 12345678901234)]))
assert.Equal(t, "123456789012345" , string(buf[:u64toa(&buf[0], 123456789012345)]))
assert.Equal(t, "1234567890123456" , string(buf[:u64toa(&buf[0], 1234567890123456)]))
assert.Equal(t, "12345678901234567" , string(buf[:u64toa(&buf[0], 12345678901234567)]))
assert.Equal(t, "123456789012345678" , string(buf[:u64toa(&buf[0], 123456789012345678)]))
assert.Equal(t, "1234567890123456789" , string(buf[:u64toa(&buf[0], 1234567890123456789)]))
assert.Equal(t, "12345678901234567890" , string(buf[:u64toa(&buf[0], 12345678901234567890)]))
assert.Equal(t, "18446744073709551615" , string(buf[:u64toa(&buf[0], 18446744073709551615)]))
}
func BenchmarkFastInt_IntToString(b *testing.B) {
benchmarks := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib-Positive",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendInt(buf[:0], int64(i), 10) }},
}, {
name: "StdLib-Negative",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendInt(buf[:0], -int64(i), 10) }},
}, {
name: "FastInt-Positive",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { i64toa(&buf[0], int64(i)) }},
}, {
name: "FastInt-Negative",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { i64toa(&buf[0], -int64(i)) }},
}}
for _, bm := range benchmarks {
b.Run(bm.name, bm.test)
}
}
func BenchmarkFastInt_IntToString(b *testing.B) {
benchmarks := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib-Positive",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendInt(buf[:0], int64(i), 10) }},
}, {
name: "StdLib-Negative",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendInt(buf[:0], -int64(i), 10) }},
}, {
name: "FastInt-Positive",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { __i64toa(&buf[0], int64(i)) }},
}, {
name: "FastInt-Negative",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { __i64toa(&buf[0], -int64(i)) }},
}}
for _, bm := range benchmarks {
b.Run(bm.name, bm.test)
}
}
type utoaBench struct {
name string
num uint64
}
func BenchmarkFastInt_UintToString(b *testing.B) {
maxUint := "18446744073709551615"
benchs := make([]utoaBench, len(maxUint) + 1)
benchs[0].name = "Zero"
benchs[0].num = 0
for i := 1; i <= len(maxUint); i++ {
benchs[i].name = strconv.FormatInt(int64(i), 10) + "-Digs"
benchs[i].num, _ = strconv.ParseUint(string(maxUint[:i]), 10, 64)
}
for _, t := range(benchs) {
benchmarks := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendUint(buf[:0], t.num, 10) }},
}, {
name: "FastInt",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { __u64toa(&buf[0], t.num) }},
}}
for _, bm := range benchmarks {
name := fmt.Sprintf("%s_%s", bm.name, t.name)
b.Run(name, bm.test)
}
}
}
type utoaBench struct {
name string
num uint64
}
func BenchmarkFastInt_UintToString(b *testing.B) {
maxUint := "18446744073709551615"
benchs := make([]utoaBench, len(maxUint) + 1)
benchs[0].name = "Zero"
benchs[0].num = 0
for i := 1; i <= len(maxUint); i++ {
benchs[i].name = strconv.FormatInt(int64(i), 10) + "-Digs"
benchs[i].num, _ = strconv.ParseUint(string(maxUint[:i]), 10, 64)
}
for _, t := range(benchs) {
benchmarks := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendUint(buf[:0], t.num, 10) }},
}, {
name: "FastInt",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { u64toa(&buf[0], t.num) }},
}}
for _, bm := range benchmarks {
name := fmt.Sprintf("%s_%s", bm.name, t.name)
b.Run(name, bm.test)
}
}
}

@ -1,3 +1,5 @@
// Code generated by Makefile, DO NOT EDIT.
/*
* Copyright 2021 ByteDance Inc.
*
@ -20,114 +22,168 @@ import (
`unsafe`
`github.com/bytedance/sonic/internal/native/types`
`github.com/bytedance/sonic/internal/rt`
)
var (
__i64toa func(out unsafe.Pointer, val int64) (ret int)
__u64toa func(out unsafe.Pointer, val uint64) (ret int)
__f64toa func(out unsafe.Pointer, val float64) (ret int)
__f32toa func(out unsafe.Pointer, val float32) (ret int)
__lspace func(sp unsafe.Pointer, nb int, off int) (ret int)
__quote func(sp unsafe.Pointer, nb int, dp unsafe.Pointer, dn unsafe.Pointer, flags uint64) (ret int)
__html_escape func(sp unsafe.Pointer, nb int, dp unsafe.Pointer, dn unsafe.Pointer) (ret int)
__unquote func(sp unsafe.Pointer, nb int, dp unsafe.Pointer, ep unsafe.Pointer, flags uint64) (ret int)
__value func(s unsafe.Pointer, n int, p int, v unsafe.Pointer, flags uint64) (ret int)
__vstring func(s unsafe.Pointer, p unsafe.Pointer, v unsafe.Pointer, flags uint64)
__vnumber func(s unsafe.Pointer, p unsafe.Pointer, v unsafe.Pointer)
__vsigned func(s unsafe.Pointer, p unsafe.Pointer, v unsafe.Pointer)
__vunsigned func(s unsafe.Pointer, p unsafe.Pointer, v unsafe.Pointer)
__skip_one func(s unsafe.Pointer, p unsafe.Pointer, m unsafe.Pointer, flags uint64) (ret int)
__skip_one_fast func(s unsafe.Pointer, p unsafe.Pointer) (ret int)
__skip_array func(s unsafe.Pointer, p unsafe.Pointer, m unsafe.Pointer, flags uint64) (ret int)
__skip_object func(s unsafe.Pointer, p unsafe.Pointer, m unsafe.Pointer, flags uint64) (ret int)
__skip_number func(s unsafe.Pointer, p unsafe.Pointer) (ret int)
__validate_one func(s unsafe.Pointer, p unsafe.Pointer, m unsafe.Pointer) (ret int)
__get_by_path func(s unsafe.Pointer, p unsafe.Pointer, path unsafe.Pointer, m unsafe.Pointer) (ret int)
__validate_utf8 func(s unsafe.Pointer, p unsafe.Pointer, m unsafe.Pointer) (ret int)
__validate_utf8_fast func(s unsafe.Pointer) (ret int)
__fsm_exec func(m unsafe.Pointer, s unsafe.Pointer, p unsafe.Pointer, flags uint64) (ret int)
)
//go:nosplit
func i64toa(out *byte, val int64) (ret int) {
return __i64toa(rt.NoEscape(unsafe.Pointer(out)), val)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __i64toa(out *byte, val int64) (ret int)
func u64toa(out *byte, val uint64) (ret int) {
return __u64toa(rt.NoEscape(unsafe.Pointer(out)), val)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __u64toa(out *byte, val uint64) (ret int)
func f64toa(out *byte, val float64) (ret int) {
return __f64toa(rt.NoEscape(unsafe.Pointer(out)), val)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __f64toa(out *byte, val float64) (ret int)
func f32toa(out *byte, val float32) (ret int) {
return __f32toa(rt.NoEscape(unsafe.Pointer(out)), val)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __f32toa(out *byte, val float32) (ret int)
func lspace(sp unsafe.Pointer, nb int, off int) (ret int) {
return __lspace(rt.NoEscape(sp), nb, off)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __lspace(sp unsafe.Pointer, nb int, off int) (ret int)
func quote(sp unsafe.Pointer, nb int, dp unsafe.Pointer, dn *int, flags uint64) (ret int) {
return __quote(rt.NoEscape(unsafe.Pointer(sp)), nb, rt.NoEscape(unsafe.Pointer(dp)), rt.NoEscape(unsafe.Pointer(dn)), flags)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __quote(sp unsafe.Pointer, nb int, dp unsafe.Pointer, dn *int, flags uint64) (ret int)
func html_escape(sp unsafe.Pointer, nb int, dp unsafe.Pointer, dn *int) (ret int) {
return __html_escape(rt.NoEscape(unsafe.Pointer(sp)), nb, rt.NoEscape(unsafe.Pointer(dp)), rt.NoEscape(unsafe.Pointer(dn)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __html_escape(sp unsafe.Pointer, nb int, dp unsafe.Pointer, dn *int) (ret int)
func unquote(sp unsafe.Pointer, nb int, dp unsafe.Pointer, ep *int, flags uint64) (ret int) {
return __unquote(rt.NoEscape(unsafe.Pointer(sp)), nb, rt.NoEscape(unsafe.Pointer(dp)), rt.NoEscape(unsafe.Pointer(ep)), flags)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __unquote(sp unsafe.Pointer, nb int, dp unsafe.Pointer, ep *int, flags uint64) (ret int)
func value(s unsafe.Pointer, n int, p int, v *types.JsonState, flags uint64) (ret int) {
return __value(rt.NoEscape(unsafe.Pointer(s)), n, p, rt.NoEscape(unsafe.Pointer(v)), flags)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __value(s unsafe.Pointer, n int, p int, v *types.JsonState, flags uint64) (ret int)
func vstring(s *string, p *int, v *types.JsonState, flags uint64) {
__vstring(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(v)), flags)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __vstring(s *string, p *int, v *types.JsonState, flags uint64)
func vnumber(s *string, p *int, v *types.JsonState) {
__vnumber(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(v)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __vnumber(s *string, p *int, v *types.JsonState)
func vsigned(s *string, p *int, v *types.JsonState) {
__vsigned(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(v)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __vsigned(s *string, p *int, v *types.JsonState)
func vunsigned(s *string, p *int, v *types.JsonState) {
__vunsigned(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(v)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __vunsigned(s *string, p *int, v *types.JsonState)
func skip_one(s *string, p *int, m *types.StateMachine, flags uint64) (ret int) {
return __skip_one(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(m)), flags)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __skip_one(s *string, p *int, m *types.StateMachine, flags uint64) (ret int)
func skip_one_fast(s *string, p *int) (ret int) {
return __skip_one_fast(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __skip_one_fast(s *string, p *int) (ret int)
func skip_array(s *string, p *int, m *types.StateMachine, flags uint64) (ret int) {
return __skip_array(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(m)), flags)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __skip_array(s *string, p *int, m *types.StateMachine, flags uint64) (ret int)
func skip_object(s *string, p *int, m *types.StateMachine, flags uint64) (ret int) {
return __skip_object(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(m)), flags)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __skip_object(s *string, p *int, m *types.StateMachine, flags uint64) (ret int)
func skip_number(s *string, p *int) (ret int) {
return __skip_number(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __skip_number(s *string, p *int) (ret int)
func validate_one(s *string, p *int, m *types.StateMachine) (ret int) {
return __validate_one(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(m)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __validate_one(s *string, p *int, m *types.StateMachine) (ret int)
func get_by_path(s *string, p *int, path *[]interface{}, m *types.StateMachine) (ret int) {
return __get_by_path(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(path)), rt.NoEscape(unsafe.Pointer(m)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __get_by_path(s *string, p *int, path *[]interface{}, m *types.StateMachine) (ret int)
func validate_utf8(s *string, p *int, m *types.StateMachine) (ret int) {
return __validate_utf8(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(m)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __validate_utf8(s *string, p *int, m *types.StateMachine) (ret int)
func validate_utf8_fast(s *string) (ret int) {
return __validate_utf8_fast(rt.NoEscape(unsafe.Pointer(s)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __validate_utf8_fast(s *string) (ret int)
func fsm_exec(m *types.StateMachine, s *string, p *int, flags uint64) (ret int) {
return __fsm_exec(rt.NoEscape(unsafe.Pointer(m)), rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), flags)
}

@ -1,3 +1,5 @@
// Code generated by Makefile, DO NOT EDIT.
/*
* Copyright 2021 ByteDance Inc.
*
@ -20,6 +22,7 @@ import (
`encoding/hex`
`fmt`
`math`
`strings`
`testing`
`unsafe`
@ -34,7 +37,7 @@ func TestNative_Value(t *testing.T) {
var v types.JsonState
s := ` -12345`
p := (*rt.GoString)(unsafe.Pointer(&s))
x := __value(p.Ptr, p.Len, 0, &v, 0)
x := value(p.Ptr, p.Len, 0, &v, 0)
assert.Equal(t, 9, x)
assert.Equal(t, types.V_INTEGER, v.Vt)
assert.Equal(t, int64(-12345), v.Iv)
@ -46,7 +49,7 @@ func TestNative_Value_OutOfBound(t *testing.T) {
mem := []byte{'"', '"'}
s := rt.Mem2Str(mem[:1])
p := (*rt.GoString)(unsafe.Pointer(&s))
x := __value(p.Ptr, p.Len, 0, &v, 0)
x := value(p.Ptr, p.Len, 0, &v, 0)
assert.Equal(t, 1, x)
assert.Equal(t, -int(types.ERR_EOF), int(v.Vt))
}
@ -56,7 +59,7 @@ func TestNative_Quote(t *testing.T) {
d := make([]byte, 256)
dp := (*rt.GoSlice)(unsafe.Pointer(&d))
sp := (*rt.GoString)(unsafe.Pointer(&s))
rv := __quote(sp.Ptr, sp.Len, dp.Ptr, &dp.Len, 0)
rv := quote(sp.Ptr, sp.Len, dp.Ptr, &dp.Len, 0)
if rv < 0 {
require.NoError(t, types.ParsingError(-rv))
}
@ -70,7 +73,7 @@ func TestNative_QuoteNoMem(t *testing.T) {
d := make([]byte, 10)
dp := (*rt.GoSlice)(unsafe.Pointer(&d))
sp := (*rt.GoString)(unsafe.Pointer(&s))
rv := __quote(sp.Ptr, sp.Len, dp.Ptr, &dp.Len, 0)
rv := quote(sp.Ptr, sp.Len, dp.Ptr, &dp.Len, 0)
assert.Equal(t, -6, rv)
assert.Equal(t, 5, len(d))
assert.Equal(t, `hello`, string(d))
@ -81,7 +84,7 @@ func TestNative_DoubleQuote(t *testing.T) {
d := make([]byte, 256)
dp := (*rt.GoSlice)(unsafe.Pointer(&d))
sp := (*rt.GoString)(unsafe.Pointer(&s))
rv := __quote(sp.Ptr, sp.Len, dp.Ptr, &dp.Len, types.F_DOUBLE_UNQUOTE)
rv := quote(sp.Ptr, sp.Len, dp.Ptr, &dp.Len, types.F_DOUBLE_UNQUOTE)
if rv < 0 {
require.NoError(t, types.ParsingError(-rv))
}
@ -96,7 +99,7 @@ func TestNative_Unquote(t *testing.T) {
ep := -1
dp := (*rt.GoSlice)(unsafe.Pointer(&d))
sp := (*rt.GoString)(unsafe.Pointer(&s))
rv := __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, 0)
rv := unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, 0)
if rv < 0 {
require.NoError(t, types.ParsingError(-rv))
}
@ -111,7 +114,7 @@ func TestNative_UnquoteError(t *testing.T) {
ep := -1
dp := (*rt.GoSlice)(unsafe.Pointer(&d))
sp := (*rt.GoString)(unsafe.Pointer(&s))
rv := __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, 0)
rv := unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, 0)
assert.Equal(t, -int(types.ERR_EOF), rv)
assert.Equal(t, 5, ep)
s = `asdf\gqwer`
@ -119,7 +122,7 @@ func TestNative_UnquoteError(t *testing.T) {
ep = -1
dp = (*rt.GoSlice)(unsafe.Pointer(&d))
sp = (*rt.GoString)(unsafe.Pointer(&s))
rv = __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, 0)
rv = unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, 0)
assert.Equal(t, -int(types.ERR_INVALID_ESCAPE), rv)
assert.Equal(t, 5, ep)
s = `asdf\u1gggqwer`
@ -127,7 +130,7 @@ func TestNative_UnquoteError(t *testing.T) {
ep = -1
dp = (*rt.GoSlice)(unsafe.Pointer(&d))
sp = (*rt.GoString)(unsafe.Pointer(&s))
rv = __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, 0)
rv = unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, 0)
assert.Equal(t, -int(types.ERR_INVALID_CHAR), rv)
assert.Equal(t, 7, ep)
s = `asdf\ud800qwer`
@ -135,7 +138,7 @@ func TestNative_UnquoteError(t *testing.T) {
ep = -1
dp = (*rt.GoSlice)(unsafe.Pointer(&d))
sp = (*rt.GoString)(unsafe.Pointer(&s))
rv = __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, 0)
rv = unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, 0)
assert.Equal(t, -int(types.ERR_INVALID_UNICODE), rv)
assert.Equal(t, 6, ep)
s = `asdf\\ud800qwer`
@ -143,7 +146,7 @@ func TestNative_UnquoteError(t *testing.T) {
ep = -1
dp = (*rt.GoSlice)(unsafe.Pointer(&d))
sp = (*rt.GoString)(unsafe.Pointer(&s))
rv = __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, types.F_DOUBLE_UNQUOTE)
rv = unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, types.F_DOUBLE_UNQUOTE)
assert.Equal(t, -int(types.ERR_INVALID_UNICODE), rv)
assert.Equal(t, 7, ep)
s = `asdf\ud800\ud800qwer`
@ -151,7 +154,7 @@ func TestNative_UnquoteError(t *testing.T) {
ep = -1
dp = (*rt.GoSlice)(unsafe.Pointer(&d))
sp = (*rt.GoString)(unsafe.Pointer(&s))
rv = __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, 0)
rv = unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, 0)
assert.Equal(t, -int(types.ERR_INVALID_UNICODE), rv)
assert.Equal(t, 12, ep)
s = `asdf\\ud800\\ud800qwer`
@ -159,7 +162,7 @@ func TestNative_UnquoteError(t *testing.T) {
ep = -1
dp = (*rt.GoSlice)(unsafe.Pointer(&d))
sp = (*rt.GoString)(unsafe.Pointer(&s))
rv = __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, types.F_DOUBLE_UNQUOTE)
rv = unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, types.F_DOUBLE_UNQUOTE)
assert.Equal(t, -int(types.ERR_INVALID_UNICODE), rv)
assert.Equal(t, 14, ep)
}
@ -170,7 +173,7 @@ func TestNative_DoubleUnquote(t *testing.T) {
ep := -1
dp := (*rt.GoSlice)(unsafe.Pointer(&d))
sp := (*rt.GoString)(unsafe.Pointer(&s))
rv := __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, types.F_DOUBLE_UNQUOTE)
rv := unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, types.F_DOUBLE_UNQUOTE)
if rv < 0 {
require.NoError(t, types.ParsingError(-rv))
}
@ -185,7 +188,7 @@ func TestNative_UnquoteUnicodeReplacement(t *testing.T) {
ep := -1
dp := (*rt.GoSlice)(unsafe.Pointer(&d))
sp := (*rt.GoString)(unsafe.Pointer(&s))
rv := __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, types.F_UNICODE_REPLACE)
rv := unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, types.F_UNICODE_REPLACE)
if rv < 0 {
require.NoError(t, types.ParsingError(-rv))
}
@ -197,7 +200,7 @@ func TestNative_UnquoteUnicodeReplacement(t *testing.T) {
ep = -1
dp = (*rt.GoSlice)(unsafe.Pointer(&d))
sp = (*rt.GoString)(unsafe.Pointer(&s))
rv = __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, types.F_UNICODE_REPLACE)
rv = unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, types.F_UNICODE_REPLACE)
if rv < 0 {
require.NoError(t, types.ParsingError(-rv))
}
@ -211,7 +214,7 @@ func TestNative_HTMLEscape(t *testing.T) {
d := make([]byte, 256)
dp := (*rt.GoSlice)(unsafe.Pointer(&d))
sp := (*rt.GoString)(unsafe.Pointer(&s))
rv := __html_escape(sp.Ptr, sp.Len, dp.Ptr, &dp.Len)
rv := html_escape(sp.Ptr, sp.Len, dp.Ptr, &dp.Len)
if rv < 0 {
require.NoError(t, types.ParsingError(-rv))
}
@ -225,7 +228,7 @@ func TestNative_HTMLEscapeNoMem(t *testing.T) {
d := make([]byte, 10)
dp := (*rt.GoSlice)(unsafe.Pointer(&d))
sp := (*rt.GoString)(unsafe.Pointer(&s))
rv := __html_escape(sp.Ptr, sp.Len, dp.Ptr, &dp.Len)
rv := html_escape(sp.Ptr, sp.Len, dp.Ptr, &dp.Len)
assert.Equal(t, -6, rv)
assert.Equal(t, 5, len(d))
assert.Equal(t, `hello`, string(d))
@ -235,11 +238,11 @@ func TestNative_Vstring(t *testing.T) {
var v types.JsonState
i := 0
s := `test"test\n2"`
__vstring(&s, &i, &v, 0)
vstring(&s, &i, &v, 0)
assert.Equal(t, 5, i)
assert.Equal(t, -1, v.Ep)
assert.Equal(t, int64(0), v.Iv)
__vstring(&s, &i, &v, 0)
vstring(&s, &i, &v, 0)
assert.Equal(t, 13, i)
assert.Equal(t, 9, v.Ep)
assert.Equal(t, int64(5), v.Iv)
@ -250,7 +253,7 @@ func TestNative_Vstring_ValidUnescapedChars(t *testing.T) {
valid := uint64(types.F_VALIDATE_STRING)
i := 0
s := "test\x1f\""
__vstring(&s, &i, &v, valid)
vstring(&s, &i, &v, valid)
assert.Equal(t, -int(types.ERR_INVALID_CHAR), int(v.Vt))
}
@ -258,7 +261,7 @@ func TestNative_VstringEscapeEOF(t *testing.T) {
var v types.JsonState
i := 0
s := `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"x`
__vstring(&s, &i, &v, 0)
vstring(&s, &i, &v, 0)
assert.Equal(t, 95, i)
assert.Equal(t, 63, v.Ep)
assert.Equal(t, int64(0), v.Iv)
@ -274,7 +277,7 @@ func TestNative_VstringHangUpOnRandomData(t *testing.T) {
p := 1
s := rt.Mem2Str(v)
var js types.JsonState
__vstring(&s, &p, &js, 0)
vstring(&s, &p, &js, 0)
fmt.Printf("js: %s\n", spew.Sdump(js))
}
@ -282,49 +285,49 @@ func TestNative_Vnumber(t *testing.T) {
var v types.JsonState
i := 0
s := "1234"
__vnumber(&s, &i, &v)
vnumber(&s, &i, &v)
assert.Equal(t, 4, i)
assert.Equal(t, 0, v.Ep)
assert.Equal(t, int64(1234), v.Iv)
assert.Equal(t, types.V_INTEGER, v.Vt)
i = 0
s = "1.234"
__vnumber(&s, &i, &v)
vnumber(&s, &i, &v)
assert.Equal(t, 5, i)
assert.Equal(t, 0, v.Ep)
assert.Equal(t, 1.234, v.Dv)
assert.Equal(t, types.V_DOUBLE, v.Vt)
i = 0
s = "1.234e5"
__vnumber(&s, &i, &v)
vnumber(&s, &i, &v)
assert.Equal(t, 7, i)
assert.Equal(t, 0, v.Ep)
assert.Equal(t, 1.234e5, v.Dv)
assert.Equal(t, types.V_DOUBLE, v.Vt)
i = 0
s = "0.0125"
__vnumber(&s, &i, &v)
vnumber(&s, &i, &v)
assert.Equal(t, 6, i)
assert.Equal(t, 0, v.Ep)
assert.Equal(t, 0.0125, v.Dv)
assert.Equal(t, types.V_DOUBLE, v.Vt)
i = 0
s = "100000000000000000000"
__vnumber(&s, &i, &v)
vnumber(&s, &i, &v)
assert.Equal(t, 21, i)
assert.Equal(t, 0, v.Ep)
assert.Equal(t, 100000000000000000000.0, v.Dv)
assert.Equal(t, types.V_DOUBLE, v.Vt)
i = 0
s = "999999999999999900000"
__vnumber(&s, &i, &v)
vnumber(&s, &i, &v)
assert.Equal(t, 21, i)
assert.Equal(t, 0, v.Ep)
assert.Equal(t, 999999999999999900000.0, v.Dv)
assert.Equal(t, types.V_DOUBLE, v.Vt)
i = 0
s = "-1.234"
__vnumber(&s, &i, &v)
vnumber(&s, &i, &v)
assert.Equal(t, 6, i)
assert.Equal(t, 0, v.Ep)
assert.Equal(t, -1.234, v.Dv)
@ -335,65 +338,65 @@ func TestNative_Vsigned(t *testing.T) {
var v types.JsonState
i := 0
s := "1234"
__vsigned(&s, &i, &v)
vsigned(&s, &i, &v)
assert.Equal(t, 4, i)
assert.Equal(t, 0, v.Ep)
assert.Equal(t, int64(1234), v.Iv)
assert.Equal(t, types.V_INTEGER, v.Vt)
i = 0
s = "-1234"
__vsigned(&s, &i, &v)
vsigned(&s, &i, &v)
assert.Equal(t, 5, i)
assert.Equal(t, 0, v.Ep)
assert.Equal(t, int64(-1234), v.Iv)
assert.Equal(t, types.V_INTEGER, v.Vt)
i = 0
s = "9223372036854775807"
__vsigned(&s, &i, &v)
vsigned(&s, &i, &v)
assert.Equal(t, 19, i)
assert.Equal(t, 0, v.Ep)
assert.Equal(t, int64(math.MaxInt64), v.Iv)
assert.Equal(t, types.V_INTEGER, v.Vt)
i = 0
s = "-9223372036854775808"
__vsigned(&s, &i, &v)
vsigned(&s, &i, &v)
assert.Equal(t, 20, i)
assert.Equal(t, 0, v.Ep)
assert.Equal(t, int64(math.MinInt64), v.Iv)
assert.Equal(t, types.V_INTEGER, v.Vt)
i = 0
s = "9223372036854775808"
__vsigned(&s, &i, &v)
vsigned(&s, &i, &v)
assert.Equal(t, 18, i)
assert.Equal(t, 0, v.Ep)
assert.Equal(t, types.ValueType(-int(types.ERR_INTEGER_OVERFLOW)), v.Vt)
i = 0
s = "-9223372036854775809"
__vsigned(&s, &i, &v)
vsigned(&s, &i, &v)
assert.Equal(t, 19, i)
assert.Equal(t, 0, v.Ep)
assert.Equal(t, types.ValueType(-int(types.ERR_INTEGER_OVERFLOW)), v.Vt)
i = 0
s = "1.234"
__vsigned(&s, &i, &v)
vsigned(&s, &i, &v)
assert.Equal(t, 1, i)
assert.Equal(t, 0, v.Ep)
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
i = 0
s = "0.0125"
__vsigned(&s, &i, &v)
vsigned(&s, &i, &v)
assert.Equal(t, 1, i)
assert.Equal(t, 0, v.Ep)
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
i = 0
s = "-1234e5"
__vsigned(&s, &i, &v)
vsigned(&s, &i, &v)
assert.Equal(t, 5, i)
assert.Equal(t, 0, v.Ep)
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
i = 0
s = "-1234e-5"
__vsigned(&s, &i, &v)
vsigned(&s, &i, &v)
assert.Equal(t, 5, i)
assert.Equal(t, 0, v.Ep)
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
@ -403,63 +406,63 @@ func TestNative_Vunsigned(t *testing.T) {
var v types.JsonState
i := 0
s := "1234"
__vunsigned(&s, &i, &v)
vunsigned(&s, &i, &v)
assert.Equal(t, 4, i)
assert.Equal(t, 0, v.Ep)
assert.Equal(t, int64(1234), v.Iv)
assert.Equal(t, types.V_INTEGER, v.Vt)
i = 0
s = "18446744073709551615"
__vunsigned(&s, &i, &v)
vunsigned(&s, &i, &v)
assert.Equal(t, 20, i)
assert.Equal(t, 0, v.Ep)
assert.Equal(t, ^int64(0), v.Iv)
assert.Equal(t, types.V_INTEGER, v.Vt)
i = 0
s = "18446744073709551616"
__vunsigned(&s, &i, &v)
vunsigned(&s, &i, &v)
assert.Equal(t, 19, i)
assert.Equal(t, 0, v.Ep)
assert.Equal(t, types.ValueType(-int(types.ERR_INTEGER_OVERFLOW)), v.Vt)
i = 0
s = "-1234"
__vunsigned(&s, &i, &v)
vunsigned(&s, &i, &v)
assert.Equal(t, 0, i)
assert.Equal(t, 0, v.Ep)
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
i = 0
s = "1.234"
__vunsigned(&s, &i, &v)
vunsigned(&s, &i, &v)
assert.Equal(t, 1, i)
assert.Equal(t, 0, v.Ep)
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
i = 0
s = "0.0125"
__vunsigned(&s, &i, &v)
vunsigned(&s, &i, &v)
assert.Equal(t, 1, i)
assert.Equal(t, 0, v.Ep)
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
i = 0
s = "1234e5"
__vunsigned(&s, &i, &v)
vunsigned(&s, &i, &v)
assert.Equal(t, 4, i)
assert.Equal(t, 0, v.Ep)
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
i = 0
s = "-1234e5"
__vunsigned(&s, &i, &v)
vunsigned(&s, &i, &v)
assert.Equal(t, 0, i)
assert.Equal(t, 0, v.Ep)
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
i = 0
s = "-1.234e5"
__vunsigned(&s, &i, &v)
vunsigned(&s, &i, &v)
assert.Equal(t, 0, i)
assert.Equal(t, 0, v.Ep)
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
i = 0
s = "-1.234e-5"
__vunsigned(&s, &i, &v)
vunsigned(&s, &i, &v)
assert.Equal(t, 0, i)
assert.Equal(t, 0, v.Ep)
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
@ -468,36 +471,36 @@ func TestNative_Vunsigned(t *testing.T) {
func TestNative_SkipOne(t *testing.T) {
p := 0
s := ` {"asdf": [null, true, false, 1, 2.0, -3]}, 1234.5`
q := __skip_one(&s, &p, &types.StateMachine{}, uint64(0))
q := skip_one(&s, &p, &types.StateMachine{}, uint64(0))
assert.Equal(t, 42, p)
assert.Equal(t, 1, q)
p = 0
s = `1 2.5 -3 "asdf\nqwer" true false null {} []`
q = __skip_one(&s, &p, &types.StateMachine{}, uint64(0))
q = skip_one(&s, &p, &types.StateMachine{}, uint64(0))
assert.Equal(t, 1, p)
assert.Equal(t, 0, q)
q = __skip_one(&s, &p, &types.StateMachine{}, uint64(0))
q = skip_one(&s, &p, &types.StateMachine{}, uint64(0))
assert.Equal(t, 5, p)
assert.Equal(t, 2, q)
q = __skip_one(&s, &p, &types.StateMachine{}, uint64(0))
q = skip_one(&s, &p, &types.StateMachine{}, uint64(0))
assert.Equal(t, 8, p)
assert.Equal(t, 6, q)
q = __skip_one(&s, &p, &types.StateMachine{}, uint64(0))
q = skip_one(&s, &p, &types.StateMachine{}, uint64(0))
assert.Equal(t, 21, p)
assert.Equal(t, 9, q)
q = __skip_one(&s, &p, &types.StateMachine{}, uint64(0))
q = skip_one(&s, &p, &types.StateMachine{}, uint64(0))
assert.Equal(t, 26, p)
assert.Equal(t, 22, q)
q = __skip_one(&s, &p, &types.StateMachine{}, uint64(0))
q = skip_one(&s, &p, &types.StateMachine{}, uint64(0))
assert.Equal(t, 32, p)
assert.Equal(t, 27, q)
q = __skip_one(&s, &p, &types.StateMachine{}, uint64(0))
q = skip_one(&s, &p, &types.StateMachine{}, uint64(0))
assert.Equal(t, 37, p)
assert.Equal(t, 33, q)
q = __skip_one(&s, &p, &types.StateMachine{}, uint64(0))
q = skip_one(&s, &p, &types.StateMachine{}, uint64(0))
assert.Equal(t, 40, p)
assert.Equal(t, 38, q)
q = __skip_one(&s, &p, &types.StateMachine{}, uint64(0))
q = skip_one(&s, &p, &types.StateMachine{}, uint64(0))
assert.Equal(t, 43, p)
assert.Equal(t, 41, q)
}
@ -509,7 +512,7 @@ func TestNative_SkipOne_Error(t *testing.T) {
`"asdf`, `"\\\"`,
}) {
p := 0
q := __skip_one(&s, &p, &types.StateMachine{}, uint64(0))
q := skip_one(&s, &p, &types.StateMachine{}, uint64(0))
assert.True(t, q < 0)
}
}
@ -517,21 +520,21 @@ func TestNative_SkipOne_Error(t *testing.T) {
func TestNative_SkipArray(t *testing.T) {
p := 0
s := `null, true, false, 1, 2.0, -3, {"asdf": "wqer"}],`
__skip_array(&s, &p, &types.StateMachine{}, uint64(0))
skip_array(&s, &p, &types.StateMachine{}, uint64(0))
assert.Equal(t, p, 48)
}
func TestNative_SkipObject(t *testing.T) {
p := 0
s := `"asdf": "wqer"},`
__skip_object(&s, &p, &types.StateMachine{}, uint64(0))
skip_object(&s, &p, &types.StateMachine{}, uint64(0))
assert.Equal(t, p, 15)
}
func TestNative_SkipNumber(t *testing.T) {
p := 0
s := `-1.23e+12`
q := __skip_number(&s, &p)
q := skip_number(&s, &p)
assert.Equal(t, 9, p)
assert.Equal(t, 0, q)
}
@ -539,44 +542,44 @@ func TestNative_SkipNumber(t *testing.T) {
func TestNative_SkipOneFast(t *testing.T) {
p := 0
s := ` {"asdf": [null, true, false, 1, 2.0, -3]}, 1234.5`
q := __skip_one_fast(&s, &p)
q := skip_one_fast(&s, &p)
assert.Equal(t, 42, p)
assert.Equal(t, 1, q)
p = 0
s = `1, 2.5, -3, "asdf\nqwer", true, false, null, {}, [],`
q = __skip_one_fast(&s, &p)
q = skip_one_fast(&s, &p)
assert.Equal(t, 1, p)
assert.Equal(t, 0, q)
p += 1
q = __skip_one_fast(&s, &p)
q = skip_one_fast(&s, &p)
assert.Equal(t, 6, p)
assert.Equal(t, 3, q)
p += 1
q = __skip_one_fast(&s, &p)
q = skip_one_fast(&s, &p)
assert.Equal(t, 10, p)
assert.Equal(t, 8, q)
p += 1
q = __skip_one_fast(&s, &p)
q = skip_one_fast(&s, &p)
assert.Equal(t, 24, p)
assert.Equal(t, 12, q)
p += 1
q = __skip_one_fast(&s, &p)
q = skip_one_fast(&s, &p)
assert.Equal(t, 30, p)
assert.Equal(t, 26, q)
p += 1
q = __skip_one_fast(&s, &p)
q = skip_one_fast(&s, &p)
assert.Equal(t, 37, p)
assert.Equal(t, 32, q)
p += 1
q = __skip_one_fast(&s, &p)
q = skip_one_fast(&s, &p)
assert.Equal(t, 43, p)
assert.Equal(t, 39, q)
p += 1
q = __skip_one_fast(&s, &p)
q = skip_one_fast(&s, &p)
assert.Equal(t, 47, p)
assert.Equal(t, 45, q)
p += 1
q = __skip_one_fast(&s, &p)
q = skip_one_fast(&s, &p)
assert.Equal(t, 51, p)
assert.Equal(t, 49, q)
}
@ -587,7 +590,36 @@ func TestNative_SkipOneFast_Error(t *testing.T) {
`"asdf`, `"\\\"`,
}) {
p := 0
q := __skip_one_fast(&s, &p)
q := skip_one_fast(&s, &p)
assert.True(t, q < 0)
}
}
func TestNative_GetByPath(t *testing.T) {
s := `{"asdf": [null, true, false, 1, 2.0, -3]}, 1234.5`
p := 0
path := []interface{}{"asdf", 4}
ret := get_by_path(&s, &p, &path, types.NewStateMachine())
assert.Equal(t, strings.Index(s, "2.0"), ret)
}
func BenchmarkNative_SkipOneFast(b *testing.B) {
b.ResetTimer()
for i:=0; i<b.N; i++ {
s := `{"asdf": [null, true, false, 1, 2.0, -3]}, 1234.5`
p := 0
_ = skip_one_fast(&s, &p)
}
}
func BenchmarkNative_GetByPath(b *testing.B) {
b.ResetTimer()
for i:=0; i<b.N; i++ {
s := `{"asdf": [null, true, false, 1, 2.0, -3]}, 1234.5`
p := 0
path := []interface{}{"asdf", 3}
sm := types.NewStateMachine()
_ = get_by_path(&s, &p, &path, sm)
types.FreeStateMachine(sm)
}
}

@ -1,47 +0,0 @@
/*
* Copyright 2021 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package {{PACKAGE}}
var (
S_f64toa = _subr__f64toa
S_f32toa = _subr__f32toa
S_i64toa = _subr__i64toa
S_u64toa = _subr__u64toa
S_lspace = _subr__lspace
)
var (
S_quote = _subr__quote
S_unquote = _subr__unquote
)
var (
S_value = _subr__value
S_vstring = _subr__vstring
S_vnumber = _subr__vnumber
S_vsigned = _subr__vsigned
S_vunsigned = _subr__vunsigned
)
var (
S_skip_one = _subr__skip_one
S_skip_one_fast = _subr__skip_one_fast
S_skip_array = _subr__skip_array
S_skip_object = _subr__skip_object
S_skip_number = _subr__skip_number
S_get_by_path = _subr__get_by_path
)

@ -0,0 +1,697 @@
/**
* Copyright 2023 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package {{PACKAGE}}
import (
`os`
`runtime`
`runtime/debug`
`testing`
`time`
`unsafe`
`github.com/bytedance/sonic/internal/native/types`
`github.com/bytedance/sonic/loader`
)
var (
debugAsyncGC = os.Getenv("SONIC_NO_ASYNC_GC") == ""
)
var stubs = []loader.GoC{
{"_f32toa", nil, &__f32toa},
{"_f64toa", nil, &__f64toa},
{"_fsm_exec", nil, &__fsm_exec},
{"_get_by_path", nil, &__get_by_path},
{"_html_escape", nil, &__html_escape},
{"_i64toa", nil, &__i64toa},
{"_lspace", nil, &__lspace},
{"_quote", nil, &__quote},
{"_skip_array", nil, &__skip_array},
{"_skip_number", nil, &__skip_number},
{"_skip_object", nil, &__skip_object},
{"_skip_one", nil, &__skip_one},
{"_skip_one_fast", nil, &__skip_one_fast},
{"_u64toa", nil, &__u64toa},
{"_unquote", nil, &__unquote},
{"_validate_one", nil, &__validate_one},
{"_validate_utf8", nil, &__validate_utf8},
{"_validate_utf8_fast", nil, &__validate_utf8_fast},
{"_value", nil, &__value},
{"_vnumber", nil, &__vnumber},
{"_vsigned", nil, &__vsigned},
{"_vstring", nil, &__vstring},
{"_vunsigned", nil, &__vunsigned},
}
func TestMain(m *testing.M) {
loader.WrapGoC(Text__native_entry__, Funcs, stubs, "{{PACKAGE}}", "{{PACKAGE}}/native.c")
go func () {
if !debugAsyncGC {
return
}
println("Begin GC looping...")
for {
runtime.GC()
debug.FreeOSMemory()
}
println("stop GC looping!")
}()
time.Sleep(time.Millisecond*100)
m.Run()
}
func TestRecover_f64toa(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = f64toa(nil, 123)
}
func TestRecover_f32toa(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = f32toa(nil, 123)
}
func TestRecover_i64toa(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = i64toa(nil, 123)
}
func TestRecover_u64toa(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = u64toa(nil, 123)
}
func TestRecover_lspace(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = lspace(nil, 2, 0)
}
func TestRecover_quote(t *testing.T) {
var dn = 10
var dp = make([]byte, dn)
var sp = []byte("123")
t.Run("sp", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = quote(nil, 3, unsafe.Pointer(&dp[0]), &dn, 0)
})
t.Run("dp", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = quote(unsafe.Pointer(&sp[0]), 3, nil, &dn, 0)
})
t.Run("dn", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = quote(unsafe.Pointer(&sp[0]), 3, unsafe.Pointer(&dp[0]), nil, 0)
})
}
func TestRecover_html_escape(t *testing.T) {
var dn = 10
var dp = make([]byte, dn)
var sp = []byte("123")
t.Run("sp", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = html_escape(nil, 3, unsafe.Pointer(&dp[0]), &dn)
})
t.Run("dp", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = html_escape(unsafe.Pointer(&sp[0]), 3, nil, &dn)
})
t.Run("dn", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = html_escape(unsafe.Pointer(&sp[0]), 3, unsafe.Pointer(&dp[0]), nil)
})
}
func TestRecover_unquote(t *testing.T) {
var ep = 0
var dp = make([]byte, 10)
var sp = []byte("12\\x\"3\"4")
t.Run("sp", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = unquote(nil, len(sp), unsafe.Pointer(&dp[0]), &ep, 0)
})
t.Run("dp", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = unquote(unsafe.Pointer(&sp[0]), len(sp), nil, &ep, 0)
})
t.Run("ep", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = unquote(unsafe.Pointer(&sp[0]), len(sp), unsafe.Pointer(&dp[0]), nil, 0)
})
}
func TestRecover_value(t *testing.T) {
var v = new(types.JsonState)
var sp = []byte("123")
t.Run("sp", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = value(nil, 3, 0, v, 0)
})
t.Run("v", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = value(unsafe.Pointer(&sp[0]), 3, 0, nil, 0)
})
}
func TestRecover_vstring(t *testing.T) {
var v = new(types.JsonState)
var sp = "123"
var p = 0
t.Run("sp", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
vstring(nil, &p, v, 0)
})
t.Run("p", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
vstring(&sp, nil, v, 0)
})
t.Run("v", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
vstring(&sp, &p, nil, 0)
})
}
func TestRecover_vnumber(t *testing.T) {
var v = new(types.JsonState)
var sp = "123"
var p = 0
t.Run("sp", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
vnumber(nil, &p, v)
})
t.Run("p", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
vnumber(&sp, nil, v)
})
t.Run("v", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
vnumber(&sp, &p, nil)
})
}
func TestRecover_vsigned(t *testing.T) {
var v = new(types.JsonState)
var sp = "123"
var p = 0
t.Run("sp", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
vsigned(nil, &p, v)
})
t.Run("p", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
vsigned(&sp, nil, v)
})
t.Run("v", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
vsigned(&sp, &p, nil)
})
}
func TestRecover_vunsigned(t *testing.T) {
var v = new(types.JsonState)
var sp = "123"
var p = 0
t.Run("sp", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
vunsigned(nil, &p, v)
})
t.Run("p", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
vunsigned(&sp, nil, v)
})
t.Run("v", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
vunsigned(&sp, &p, nil)
})
}
func TestRecover_skip_one(t *testing.T) {
var v = types.NewStateMachine()
var sp = "123"
var p = 0
t.Run("sp", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = skip_one(nil, &p, v, 0)
})
t.Run("p", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = skip_one(&sp, nil, v, 0)
})
t.Run("v", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = skip_one(&sp, &p, nil, 0)
})
}
func TestRecover_skip_one_fast(t *testing.T) {
var sp = "123"
var p = 0
t.Run("sp", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = skip_one_fast(nil, &p)
})
t.Run("p", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = skip_one_fast(&sp, nil)
})
}
func TestRecover_skip_array(t *testing.T) {
var v = types.NewStateMachine()
var sp = "123"
var p = 0
t.Run("sp", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = skip_array(nil, &p, v, 0)
})
t.Run("p", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = skip_array(&sp, nil, v, 0)
})
t.Run("v", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = skip_array(&sp, &p, nil, 0)
})
}
func TestRecover_skip_object(t *testing.T) {
var v = types.NewStateMachine()
var sp = "123"
var p = 0
t.Run("sp", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = skip_object(nil, &p, v, 0)
})
t.Run("p", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = skip_object(&sp, nil, v, 0)
})
t.Run("v", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = skip_object(&sp, &p, nil, 0)
})
}
func TestRecover_skip_number(t *testing.T) {
var sp = "123"
var p = 0
t.Run("sp", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = skip_number(nil, &p)
})
t.Run("p", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = skip_number(&sp, nil)
})
}
func TestRecover_get_by_path(t *testing.T) {
var v = []interface{}{}
var sp = "123"
var p = 0
var m = types.NewStateMachine()
t.Run("sp", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = get_by_path(nil, &p, &v, m)
})
t.Run("p", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = get_by_path(&sp, nil, &v, m)
})
t.Run("path", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = get_by_path(&sp, &p, nil, m)
})
t.Run("m", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = get_by_path(&sp, &p, &v, nil)
})
}
func TestRecover_validate_one(t *testing.T) {
var v = types.NewStateMachine()
var sp = "123"
var p = 0
t.Run("sp", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = validate_one(nil, &p, v)
})
t.Run("p", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = validate_one(&sp, nil, v)
})
t.Run("v", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = validate_one(&sp, &p, nil)
})
}
func TestRecover_validate_utf8(t *testing.T) {
var v = types.NewStateMachine()
var sp = string([]byte{0xff, 0xff, 0xff})
var p = 0
t.Run("sp", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = validate_utf8(nil, &p, v)
})
t.Run("p", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = validate_utf8(&sp, nil, v)
})
t.Run("v", func(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = validate_utf8(&sp, &p, nil)
})
}
func TestRecover_validate_utf8_fast(t *testing.T) {
defer func() {
if r := recover(); r!= nil {
t.Log("recover: ", r)
} else {
t.Fatal("no panic")
}
}()
_ = validate_utf8_fast(nil)
}

@ -1,5 +1,7 @@
// Code generated by Makefile, DO NOT EDIT.
// Code generated by Makefile, DO NOT EDIT.
/*
* Copyright 2021 ByteDance Inc.
*
@ -22,114 +24,168 @@ import (
`unsafe`
`github.com/bytedance/sonic/internal/native/types`
`github.com/bytedance/sonic/internal/rt`
)
var (
__i64toa func(out unsafe.Pointer, val int64) (ret int)
__u64toa func(out unsafe.Pointer, val uint64) (ret int)
__f64toa func(out unsafe.Pointer, val float64) (ret int)
__f32toa func(out unsafe.Pointer, val float32) (ret int)
__lspace func(sp unsafe.Pointer, nb int, off int) (ret int)
__quote func(sp unsafe.Pointer, nb int, dp unsafe.Pointer, dn unsafe.Pointer, flags uint64) (ret int)
__html_escape func(sp unsafe.Pointer, nb int, dp unsafe.Pointer, dn unsafe.Pointer) (ret int)
__unquote func(sp unsafe.Pointer, nb int, dp unsafe.Pointer, ep unsafe.Pointer, flags uint64) (ret int)
__value func(s unsafe.Pointer, n int, p int, v unsafe.Pointer, flags uint64) (ret int)
__vstring func(s unsafe.Pointer, p unsafe.Pointer, v unsafe.Pointer, flags uint64)
__vnumber func(s unsafe.Pointer, p unsafe.Pointer, v unsafe.Pointer)
__vsigned func(s unsafe.Pointer, p unsafe.Pointer, v unsafe.Pointer)
__vunsigned func(s unsafe.Pointer, p unsafe.Pointer, v unsafe.Pointer)
__skip_one func(s unsafe.Pointer, p unsafe.Pointer, m unsafe.Pointer, flags uint64) (ret int)
__skip_one_fast func(s unsafe.Pointer, p unsafe.Pointer) (ret int)
__skip_array func(s unsafe.Pointer, p unsafe.Pointer, m unsafe.Pointer, flags uint64) (ret int)
__skip_object func(s unsafe.Pointer, p unsafe.Pointer, m unsafe.Pointer, flags uint64) (ret int)
__skip_number func(s unsafe.Pointer, p unsafe.Pointer) (ret int)
__validate_one func(s unsafe.Pointer, p unsafe.Pointer, m unsafe.Pointer) (ret int)
__get_by_path func(s unsafe.Pointer, p unsafe.Pointer, path unsafe.Pointer, m unsafe.Pointer) (ret int)
__validate_utf8 func(s unsafe.Pointer, p unsafe.Pointer, m unsafe.Pointer) (ret int)
__validate_utf8_fast func(s unsafe.Pointer) (ret int)
__fsm_exec func(m unsafe.Pointer, s unsafe.Pointer, p unsafe.Pointer, flags uint64) (ret int)
)
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __i64toa(out *byte, val int64) (ret int)
func i64toa(out *byte, val int64) (ret int) {
return __i64toa(rt.NoEscape(unsafe.Pointer(out)), val)
}
//go:nosplit
func u64toa(out *byte, val uint64) (ret int) {
return __u64toa(rt.NoEscape(unsafe.Pointer(out)), val)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __u64toa(out *byte, val uint64) (ret int)
func f64toa(out *byte, val float64) (ret int) {
return __f64toa(rt.NoEscape(unsafe.Pointer(out)), val)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __f64toa(out *byte, val float64) (ret int)
func f32toa(out *byte, val float32) (ret int) {
return __f32toa(rt.NoEscape(unsafe.Pointer(out)), val)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __f32toa(out *byte, val float32) (ret int)
func lspace(sp unsafe.Pointer, nb int, off int) (ret int) {
return __lspace(rt.NoEscape(sp), nb, off)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __lspace(sp unsafe.Pointer, nb int, off int) (ret int)
func quote(sp unsafe.Pointer, nb int, dp unsafe.Pointer, dn *int, flags uint64) (ret int) {
return __quote(rt.NoEscape(unsafe.Pointer(sp)), nb, rt.NoEscape(unsafe.Pointer(dp)), rt.NoEscape(unsafe.Pointer(dn)), flags)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __quote(sp unsafe.Pointer, nb int, dp unsafe.Pointer, dn *int, flags uint64) (ret int)
func html_escape(sp unsafe.Pointer, nb int, dp unsafe.Pointer, dn *int) (ret int) {
return __html_escape(rt.NoEscape(unsafe.Pointer(sp)), nb, rt.NoEscape(unsafe.Pointer(dp)), rt.NoEscape(unsafe.Pointer(dn)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __html_escape(sp unsafe.Pointer, nb int, dp unsafe.Pointer, dn *int) (ret int)
func unquote(sp unsafe.Pointer, nb int, dp unsafe.Pointer, ep *int, flags uint64) (ret int) {
return __unquote(rt.NoEscape(unsafe.Pointer(sp)), nb, rt.NoEscape(unsafe.Pointer(dp)), rt.NoEscape(unsafe.Pointer(ep)), flags)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __unquote(sp unsafe.Pointer, nb int, dp unsafe.Pointer, ep *int, flags uint64) (ret int)
func value(s unsafe.Pointer, n int, p int, v *types.JsonState, flags uint64) (ret int) {
return __value(rt.NoEscape(unsafe.Pointer(s)), n, p, rt.NoEscape(unsafe.Pointer(v)), flags)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __value(s unsafe.Pointer, n int, p int, v *types.JsonState, flags uint64) (ret int)
func vstring(s *string, p *int, v *types.JsonState, flags uint64) {
__vstring(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(v)), flags)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __vstring(s *string, p *int, v *types.JsonState, flags uint64)
func vnumber(s *string, p *int, v *types.JsonState) {
__vnumber(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(v)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __vnumber(s *string, p *int, v *types.JsonState)
func vsigned(s *string, p *int, v *types.JsonState) {
__vsigned(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(v)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __vsigned(s *string, p *int, v *types.JsonState)
func vunsigned(s *string, p *int, v *types.JsonState) {
__vunsigned(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(v)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __vunsigned(s *string, p *int, v *types.JsonState)
func skip_one(s *string, p *int, m *types.StateMachine, flags uint64) (ret int) {
return __skip_one(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(m)), flags)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __skip_one(s *string, p *int, m *types.StateMachine, flags uint64) (ret int)
func skip_one_fast(s *string, p *int) (ret int) {
return __skip_one_fast(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __skip_one_fast(s *string, p *int) (ret int)
func skip_array(s *string, p *int, m *types.StateMachine, flags uint64) (ret int) {
return __skip_array(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(m)), flags)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __skip_array(s *string, p *int, m *types.StateMachine, flags uint64) (ret int)
func skip_object(s *string, p *int, m *types.StateMachine, flags uint64) (ret int) {
return __skip_object(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(m)), flags)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __skip_object(s *string, p *int, m *types.StateMachine, flags uint64) (ret int)
func skip_number(s *string, p *int) (ret int) {
return __skip_number(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __skip_number(s *string, p *int) (ret int)
func validate_one(s *string, p *int, m *types.StateMachine) (ret int) {
return __validate_one(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(m)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __validate_one(s *string, p *int, m *types.StateMachine) (ret int)
func get_by_path(s *string, p *int, path *[]interface{}, m *types.StateMachine) (ret int) {
return __get_by_path(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(path)), rt.NoEscape(unsafe.Pointer(m)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __get_by_path(s *string, p *int, path *[]interface{}, m *types.StateMachine) (ret int)
func validate_utf8(s *string, p *int, m *types.StateMachine) (ret int) {
return __validate_utf8(rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), rt.NoEscape(unsafe.Pointer(m)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __validate_utf8(s *string, p *int, m *types.StateMachine) (ret int)
func validate_utf8_fast(s *string) (ret int) {
return __validate_utf8_fast(rt.NoEscape(unsafe.Pointer(s)))
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __validate_utf8_fast(s *string) (ret int)
func fsm_exec(m *types.StateMachine, s *string, p *int, flags uint64) (ret int) {
return __fsm_exec(rt.NoEscape(unsafe.Pointer(m)), rt.NoEscape(unsafe.Pointer(s)), rt.NoEscape(unsafe.Pointer(p)), flags)
}

File diff suppressed because it is too large Load Diff

@ -1,49 +0,0 @@
// Code generated by Makefile, DO NOT EDIT.
/*
* Copyright 2021 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sse
var (
S_f64toa = _subr__f64toa
S_f32toa = _subr__f32toa
S_i64toa = _subr__i64toa
S_u64toa = _subr__u64toa
S_lspace = _subr__lspace
)
var (
S_quote = _subr__quote
S_unquote = _subr__unquote
)
var (
S_value = _subr__value
S_vstring = _subr__vstring
S_vnumber = _subr__vnumber
S_vsigned = _subr__vsigned
S_vunsigned = _subr__vunsigned
)
var (
S_skip_one = _subr__skip_one
S_skip_one_fast = _subr__skip_one_fast
S_skip_array = _subr__skip_array
S_skip_object = _subr__skip_object
S_skip_number = _subr__skip_number
S_get_by_path = _subr__get_by_path
)

@ -3,107 +3,602 @@
package sse
//go:nosplit
//go:noescape
//goland:noinspection ALL
func __native_entry__() uintptr
import (
`github.com/bytedance/sonic/loader`
)
var (
_subr__f32toa = __native_entry__() + 31760
_subr__f64toa = __native_entry__() + 160
_subr__get_by_path = __native_entry__() + 26384
_subr__html_escape = __native_entry__() + 9072
_subr__i64toa = __native_entry__() + 3424
_subr__lspace = __native_entry__() + 16
_subr__quote = __native_entry__() + 4864
_subr__skip_array = __native_entry__() + 18112
_subr__skip_number = __native_entry__() + 22128
_subr__skip_object = __native_entry__() + 20512
_subr__skip_one = __native_entry__() + 22288
_subr__skip_one_fast = __native_entry__() + 22512
_subr__u64toa = __native_entry__() + 3552
_subr__unquote = __native_entry__() + 6704
_subr__validate_one = __native_entry__() + 22336
_subr__validate_utf8 = __native_entry__() + 30528
_subr__validate_utf8_fast = __native_entry__() + 31200
_subr__value = __native_entry__() + 12272
_subr__vnumber = __native_entry__() + 15728
_subr__vsigned = __native_entry__() + 17376
_subr__vstring = __native_entry__() + 14112
_subr__vunsigned = __native_entry__() + 17760
const (
_entry__f32toa = 31616
_entry__f64toa = 160
_entry__format_significand = 35888
_entry__format_integer = 2960
_entry__fsm_exec = 18016
_entry__advance_string = 14352
_entry__advance_string_default = 37280
_entry__do_skip_number = 20608
_entry__get_by_path = 26176
_entry__skip_one_fast = 22272
_entry__html_escape = 8912
_entry__i64toa = 3392
_entry__u64toa = 3520
_entry__lspace = 16
_entry__quote = 4832
_entry__skip_array = 17984
_entry__skip_number = 21904
_entry__skip_object = 20256
_entry__skip_one = 22048
_entry__unquote = 6576
_entry__validate_one = 22096
_entry__validate_utf8 = 30384
_entry__validate_utf8_fast = 31056
_entry__value = 12352
_entry__vnumber = 15744
_entry__atof_eisel_lemire64 = 10192
_entry__atof_native = 11744
_entry__decimal_to_f64 = 10560
_entry__right_shift = 36848
_entry__left_shift = 36352
_entry__vsigned = 17296
_entry__vstring = 14176
_entry__vunsigned = 17632
)
const (
_stack__f32toa = 48
_stack__f64toa = 80
_stack__get_by_path = 240
_stack__html_escape = 64
_stack__format_significand = 24
_stack__format_integer = 16
_stack__fsm_exec = 168
_stack__advance_string = 64
_stack__advance_string_default = 64
_stack__do_skip_number = 48
_stack__get_by_path = 272
_stack__skip_one_fast = 136
_stack__html_escape = 72
_stack__i64toa = 16
_stack__u64toa = 8
_stack__lspace = 8
_stack__quote = 64
_stack__skip_array = 128
_stack__skip_number = 72
_stack__skip_object = 128
_stack__skip_one = 128
_stack__skip_one_fast = 136
_stack__u64toa = 8
_stack__skip_array = 176
_stack__skip_number = 88
_stack__skip_object = 176
_stack__skip_one = 176
_stack__unquote = 88
_stack__validate_one = 128
_stack__validate_one = 176
_stack__validate_utf8 = 48
_stack__validate_utf8_fast = 24
_stack__value = 328
_stack__vnumber = 240
_stack__atof_eisel_lemire64 = 32
_stack__atof_native = 136
_stack__decimal_to_f64 = 80
_stack__right_shift = 8
_stack__left_shift = 24
_stack__vsigned = 16
_stack__vstring = 136
_stack__vunsigned = 16
_stack__vstring = 120
_stack__vunsigned = 8
)
var (
_ = _subr__f32toa
_ = _subr__f64toa
_ = _subr__get_by_path
_ = _subr__html_escape
_ = _subr__i64toa
_ = _subr__lspace
_ = _subr__quote
_ = _subr__skip_array
_ = _subr__skip_number
_ = _subr__skip_object
_ = _subr__skip_one
_ = _subr__skip_one_fast
_ = _subr__u64toa
_ = _subr__unquote
_ = _subr__validate_one
_ = _subr__validate_utf8
_ = _subr__validate_utf8_fast
_ = _subr__value
_ = _subr__vnumber
_ = _subr__vsigned
_ = _subr__vstring
_ = _subr__vunsigned
const (
_size__f32toa = 3328
_size__f64toa = 2800
_size__format_significand = 464
_size__format_integer = 432
_size__fsm_exec = 1692
_size__advance_string = 1344
_size__advance_string_default = 960
_size__do_skip_number = 956
_size__get_by_path = 4208
_size__skip_one_fast = 3404
_size__html_escape = 1280
_size__i64toa = 48
_size__u64toa = 1264
_size__lspace = 128
_size__quote = 1728
_size__skip_array = 32
_size__skip_number = 144
_size__skip_object = 32
_size__skip_one = 48
_size__unquote = 2272
_size__validate_one = 48
_size__validate_utf8 = 672
_size__validate_utf8_fast = 544
_size__value = 1316
_size__vnumber = 1552
_size__atof_eisel_lemire64 = 368
_size__atof_native = 608
_size__decimal_to_f64 = 1184
_size__right_shift = 400
_size__left_shift = 496
_size__vsigned = 336
_size__vstring = 128
_size__vunsigned = 336
)
const (
_ = _stack__f32toa
_ = _stack__f64toa
_ = _stack__get_by_path
_ = _stack__html_escape
_ = _stack__i64toa
_ = _stack__lspace
_ = _stack__quote
_ = _stack__skip_array
_ = _stack__skip_number
_ = _stack__skip_object
_ = _stack__skip_one
_ = _stack__skip_one_fast
_ = _stack__u64toa
_ = _stack__unquote
_ = _stack__validate_one
_ = _stack__validate_utf8
_ = _stack__validate_utf8_fast
_ = _stack__value
_ = _stack__vnumber
_ = _stack__vsigned
_ = _stack__vstring
_ = _stack__vunsigned
var (
_pcsp__f32toa = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{3286, 48},
{3287, 40},
{3289, 32},
{3291, 24},
{3293, 16},
{3295, 8},
{3296, 0},
{3318, 48},
}
_pcsp__f64toa = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{13, 48},
{2740, 56},
{2744, 48},
{2745, 40},
{2747, 32},
{2749, 24},
{2751, 16},
{2753, 8},
{2754, 0},
{2792, 56},
}
_pcsp__format_significand = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{452, 24},
{453, 16},
{455, 8},
{457, 0},
}
_pcsp__format_integer = [][2]uint32{
{1, 0},
{4, 8},
{412, 16},
{413, 8},
{414, 0},
{423, 16},
{424, 8},
{426, 0},
}
_pcsp__fsm_exec = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{13, 48},
{1342, 104},
{1346, 48},
{1347, 40},
{1349, 32},
{1351, 24},
{1353, 16},
{1355, 8},
{1356, 0},
{1692, 104},
}
_pcsp__advance_string = [][2]uint32{
{14, 0},
{18, 8},
{20, 16},
{22, 24},
{24, 32},
{26, 40},
{27, 48},
{614, 56},
{618, 48},
{619, 40},
{621, 32},
{623, 24},
{625, 16},
{627, 8},
{628, 0},
{1339, 56},
}
_pcsp__advance_string_default = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{13, 48},
{576, 64},
{580, 48},
{581, 40},
{583, 32},
{585, 24},
{587, 16},
{589, 8},
{590, 0},
{955, 64},
}
_pcsp__do_skip_number = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{881, 48},
{882, 40},
{884, 32},
{886, 24},
{888, 16},
{890, 8},
{891, 0},
{956, 48},
}
_pcsp__get_by_path = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{13, 48},
{4012, 104},
{4016, 48},
{4017, 40},
{4019, 32},
{4021, 24},
{4023, 16},
{4025, 8},
{4026, 0},
{4194, 104},
}
_pcsp__skip_one_fast = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{13, 48},
{658, 136},
{662, 48},
{663, 40},
{665, 32},
{667, 24},
{669, 16},
{671, 8},
{672, 0},
{3404, 136},
}
_pcsp__html_escape = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{13, 48},
{1256, 72},
{1260, 48},
{1261, 40},
{1263, 32},
{1265, 24},
{1267, 16},
{1269, 8},
{1271, 0},
}
_pcsp__i64toa = [][2]uint32{
{14, 0},
{34, 8},
{36, 0},
}
_pcsp__u64toa = [][2]uint32{
{1, 0},
{161, 8},
{162, 0},
{457, 8},
{458, 0},
{772, 8},
{773, 0},
{1249, 8},
{1251, 0},
}
_pcsp__lspace = [][2]uint32{
{1, 0},
{89, 8},
{90, 0},
{103, 8},
{104, 0},
{111, 8},
{113, 0},
}
_pcsp__quote = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{13, 48},
{1681, 64},
{1685, 48},
{1686, 40},
{1688, 32},
{1690, 24},
{1692, 16},
{1694, 8},
{1695, 0},
{1722, 64},
}
_pcsp__skip_array = [][2]uint32{
{1, 0},
{26, 8},
{32, 0},
}
_pcsp__skip_number = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{100, 40},
{101, 32},
{103, 24},
{105, 16},
{107, 8},
{108, 0},
{139, 40},
}
_pcsp__skip_object = [][2]uint32{
{1, 0},
{26, 8},
{32, 0},
}
_pcsp__skip_one = [][2]uint32{
{1, 0},
{30, 8},
{36, 0},
}
_pcsp__unquote = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{13, 48},
{1684, 88},
{1688, 48},
{1689, 40},
{1691, 32},
{1693, 24},
{1695, 16},
{1697, 8},
{1698, 0},
{2270, 88},
}
_pcsp__validate_one = [][2]uint32{
{1, 0},
{35, 8},
{41, 0},
}
_pcsp__validate_utf8 = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{11, 40},
{623, 48},
{627, 40},
{628, 32},
{630, 24},
{632, 16},
{634, 8},
{635, 0},
{666, 48},
}
_pcsp__validate_utf8_fast = [][2]uint32{
{1, 0},
{4, 8},
{5, 16},
{247, 24},
{251, 16},
{252, 8},
{253, 0},
{527, 24},
{531, 16},
{532, 8},
{534, 0},
}
_pcsp__value = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{13, 48},
{495, 88},
{499, 48},
{500, 40},
{502, 32},
{504, 24},
{506, 16},
{508, 8},
{509, 0},
{1316, 88},
}
_pcsp__vnumber = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{13, 48},
{803, 104},
{807, 48},
{808, 40},
{810, 32},
{812, 24},
{814, 16},
{816, 8},
{817, 0},
{1551, 104},
}
_pcsp__atof_eisel_lemire64 = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{292, 32},
{293, 24},
{295, 16},
{297, 8},
{298, 0},
{362, 32},
}
_pcsp__atof_native = [][2]uint32{
{1, 0},
{4, 8},
{587, 56},
{591, 8},
{593, 0},
}
_pcsp__decimal_to_f64 = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{13, 48},
{1144, 56},
{1148, 48},
{1149, 40},
{1151, 32},
{1153, 24},
{1155, 16},
{1157, 8},
{1158, 0},
{1169, 56},
}
_pcsp__right_shift = [][2]uint32{
{1, 0},
{318, 8},
{319, 0},
{387, 8},
{388, 0},
{396, 8},
{398, 0},
}
_pcsp__left_shift = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{363, 24},
{364, 16},
{366, 8},
{367, 0},
{470, 24},
{471, 16},
{473, 8},
{474, 0},
{486, 24},
}
_pcsp__vsigned = [][2]uint32{
{1, 0},
{4, 8},
{119, 16},
{120, 8},
{121, 0},
{132, 16},
{133, 8},
{134, 0},
{276, 16},
{277, 8},
{278, 0},
{282, 16},
{283, 8},
{284, 0},
{322, 16},
{323, 8},
{324, 0},
{332, 16},
{333, 8},
{335, 0},
}
_pcsp__vstring = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{11, 40},
{105, 56},
{109, 40},
{110, 32},
{112, 24},
{114, 16},
{116, 8},
{118, 0},
}
_pcsp__vunsigned = [][2]uint32{
{1, 0},
{78, 8},
{79, 0},
{90, 8},
{91, 0},
{114, 8},
{115, 0},
{273, 8},
{274, 0},
{312, 8},
{313, 0},
{320, 8},
{322, 0},
}
)
var Funcs = []loader.CFunc{
{"__native_entry__", 0, 67, 0, nil},
{"_f32toa", _entry__f32toa, _size__f32toa, _stack__f32toa, _pcsp__f32toa},
{"_f64toa", _entry__f64toa, _size__f64toa, _stack__f64toa, _pcsp__f64toa},
{"_format_significand", _entry__format_significand, _size__format_significand, _stack__format_significand, _pcsp__format_significand},
{"_format_integer", _entry__format_integer, _size__format_integer, _stack__format_integer, _pcsp__format_integer},
{"_fsm_exec", _entry__fsm_exec, _size__fsm_exec, _stack__fsm_exec, _pcsp__fsm_exec},
{"_advance_string", _entry__advance_string, _size__advance_string, _stack__advance_string, _pcsp__advance_string},
{"_advance_string_default", _entry__advance_string_default, _size__advance_string_default, _stack__advance_string_default, _pcsp__advance_string_default},
{"_do_skip_number", _entry__do_skip_number, _size__do_skip_number, _stack__do_skip_number, _pcsp__do_skip_number},
{"_get_by_path", _entry__get_by_path, _size__get_by_path, _stack__get_by_path, _pcsp__get_by_path},
{"_skip_one_fast", _entry__skip_one_fast, _size__skip_one_fast, _stack__skip_one_fast, _pcsp__skip_one_fast},
{"_html_escape", _entry__html_escape, _size__html_escape, _stack__html_escape, _pcsp__html_escape},
{"_i64toa", _entry__i64toa, _size__i64toa, _stack__i64toa, _pcsp__i64toa},
{"_u64toa", _entry__u64toa, _size__u64toa, _stack__u64toa, _pcsp__u64toa},
{"_lspace", _entry__lspace, _size__lspace, _stack__lspace, _pcsp__lspace},
{"_quote", _entry__quote, _size__quote, _stack__quote, _pcsp__quote},
{"_skip_array", _entry__skip_array, _size__skip_array, _stack__skip_array, _pcsp__skip_array},
{"_skip_number", _entry__skip_number, _size__skip_number, _stack__skip_number, _pcsp__skip_number},
{"_skip_object", _entry__skip_object, _size__skip_object, _stack__skip_object, _pcsp__skip_object},
{"_skip_one", _entry__skip_one, _size__skip_one, _stack__skip_one, _pcsp__skip_one},
{"_unquote", _entry__unquote, _size__unquote, _stack__unquote, _pcsp__unquote},
{"_validate_one", _entry__validate_one, _size__validate_one, _stack__validate_one, _pcsp__validate_one},
{"_validate_utf8", _entry__validate_utf8, _size__validate_utf8, _stack__validate_utf8, _pcsp__validate_utf8},
{"_validate_utf8_fast", _entry__validate_utf8_fast, _size__validate_utf8_fast, _stack__validate_utf8_fast, _pcsp__validate_utf8_fast},
{"_value", _entry__value, _size__value, _stack__value, _pcsp__value},
{"_vnumber", _entry__vnumber, _size__vnumber, _stack__vnumber, _pcsp__vnumber},
{"_atof_eisel_lemire64", _entry__atof_eisel_lemire64, _size__atof_eisel_lemire64, _stack__atof_eisel_lemire64, _pcsp__atof_eisel_lemire64},
{"_atof_native", _entry__atof_native, _size__atof_native, _stack__atof_native, _pcsp__atof_native},
{"_decimal_to_f64", _entry__decimal_to_f64, _size__decimal_to_f64, _stack__decimal_to_f64, _pcsp__decimal_to_f64},
{"_right_shift", _entry__right_shift, _size__right_shift, _stack__right_shift, _pcsp__right_shift},
{"_left_shift", _entry__left_shift, _size__left_shift, _stack__left_shift, _pcsp__left_shift},
{"_vsigned", _entry__vsigned, _size__vsigned, _stack__vsigned, _pcsp__vsigned},
{"_vstring", _entry__vstring, _size__vstring, _stack__vstring, _pcsp__vstring},
{"_vunsigned", _entry__vunsigned, _size__vunsigned, _stack__vunsigned, _pcsp__vunsigned},
}

File diff suppressed because it is too large Load Diff

@ -19,6 +19,7 @@ package types
import (
`fmt`
`sync`
`unsafe`
)
type ValueType int
@ -46,15 +47,23 @@ const (
)
const (
// for native.Unquote() flags
B_DOUBLE_UNQUOTE = 0
B_UNICODE_REPLACE = 1
// for native.Value() flags
B_USE_NUMBER = 1
B_VALIDATE_STRING = 5
B_ALLOW_CONTROL = 31
)
const (
F_DOUBLE_UNQUOTE = 1 << B_DOUBLE_UNQUOTE
F_UNICODE_REPLACE = 1 << B_UNICODE_REPLACE
F_USE_NUMBER = 1 << B_USE_NUMBER
F_VALIDATE_STRING = 1 << B_VALIDATE_STRING
F_ALLOW_CONTROL = 1 << B_ALLOW_CONTROL
)
const (
@ -136,3 +145,18 @@ func FreeStateMachine(fsm *StateMachine) {
stackPool.Put(fsm)
}
const MaxDigitNums = 800
var digitPool = sync.Pool{
New: func() interface{} {
return (*byte)(unsafe.Pointer(&[MaxDigitNums]byte{}))
},
}
func NewDbuf() *byte {
return digitPool.Get().(*byte)
}
func FreeDbuf(p *byte) {
digitPool.Put(p)
}

@ -109,4 +109,16 @@ func StrFrom(p unsafe.Pointer, n int64) (s string) {
(*GoString)(unsafe.Pointer(&s)).Ptr = p
(*GoString)(unsafe.Pointer(&s)).Len = int(n)
return
}
// NoEscape hides a pointer from escape analysis. NoEscape is
// the identity function but escape analysis doesn't think the
// output depends on the input. NoEscape is inlined and currently
// compiles down to zero instructions.
// USE CAREFULLY!
//go:nosplit
//goland:noinspection GoVetUnsafePointer
func NoEscape(p unsafe.Pointer) unsafe.Pointer {
x := uintptr(p)
return unsafe.Pointer(x ^ 0)
}

@ -1,46 +0,0 @@
//go:build !go1.16
// +build !go1.16
/*
* Copyright 2021 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package loader
import (
`github.com/bytedance/sonic/internal/loader`
)
// LoadFuncs loads only one function as module, and returns the function pointer
// - text: machine code
// - funcName: function name
// - frameSize: stack frame size.
// - argSize: argument total size (in bytes)
// - argPtrs: indicates if a slot (8 Bytes) of arguments memory stores pointer, from low to high
// - localPtrs: indicates if a slot (8 Bytes) of local variants memory stores pointer, from low to high
//
// WARN:
// - the function MUST has fixed SP offset equaling to this, otherwise it go.gentraceback will fail
// - the function MUST has only one stack map for all arguments and local variants
func (self Loader) LoadOne(text []byte, funcName string, frameSize int, argSize int, argPtrs []bool, localPtrs []bool) Function {
return Function(loader.Loader(text).Load(funcName, frameSize, argSize, argPtrs, localPtrs))
}
// Load loads given machine codes and corresponding function information into go moduledata
// and returns runnable function pointer
// WARN: this API is experimental, use it carefully
func Load(text []byte, funcs []Func, modulename string, filenames []string) (out []Function) {
panic("not implemented")
}

@ -0,0 +1,185 @@
/**
* Copyright 2023 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package loader
import (
`reflect`
`unsafe`
`github.com/bytedance/sonic/internal/abi`
`github.com/bytedance/sonic/internal/rt`
)
var _C_Redzone = []bool{false, false, false, false}
// CFunc is a function information for C func
type CFunc struct {
// C function name
Name string
// entry pc relative to entire text segment
EntryOff uint32
// function text size in bytes
TextSize uint32
// maximum stack depth of the function
MaxStack uintptr
// PC->SP delta lists of the function
Pcsp [][2]uint32
}
// GoC is the wrapper for Go calls to C
type GoC struct {
// CName is the name of corresponding C function
CName string
// CEntry points out where to store the entry address of corresponding C function.
// It won't be set if nil
CEntry *uintptr
// GoFunc is the POINTER of corresponding go stub function.
// It is used to generate Go-C ABI conversion wrapper and receive the wrapper's address
// eg. &func(a int, b int) int
// FOR
// int add(int a, int b)
// It won't be set if nil
GoFunc interface{}
}
// WrapGoC wraps C functions and loader it into Go stubs
func WrapGoC(text []byte, natives []CFunc, stubs []GoC, modulename string, filename string) {
funcs := make([]Func, len(natives))
// register C funcs
for i, f := range natives {
fn := Func{
Flag: FuncFlag_ASM,
EntryOff: f.EntryOff,
TextSize: f.TextSize,
Name: f.Name,
}
if len(f.Pcsp) != 0 {
fn.Pcsp = (*Pcdata)(unsafe.Pointer(&natives[i].Pcsp))
}
// NOTICE: always forbid async preempt
fn.PcUnsafePoint = &Pcdata{
{PC: f.TextSize, Val: PCDATA_UnsafePointUnsafe},
}
// NOTICE: always refer to first file
fn.Pcfile = &Pcdata{
{PC: f.TextSize, Val: 0},
}
// NOTICE: always refer to first line
fn.Pcline = &Pcdata{
{PC: f.TextSize, Val: 1},
}
// NOTICE: copystack need locals stackmap
fn.PcStackMapIndex = &Pcdata{
{PC: f.TextSize, Val: 0},
}
sm := rt.StackMapBuilder{}
sm.AddField(false)
fn.ArgsPointerMaps = sm.Build()
fn.LocalsPointerMaps = sm.Build()
funcs[i] = fn
}
rets := Load(text, funcs, modulename, []string{filename})
// got absolute entry address
native_entry := **(**uintptr)(unsafe.Pointer(&rets[0]))
// println("native_entry: ", native_entry)
wraps := make([]Func, 0, len(stubs))
wrapIds := make([]int, 0, len(stubs))
code := make([]byte, 0, len(wraps))
entryOff := uint32(0)
// register go wrappers
for i := range stubs {
for j := range natives {
if stubs[i].CName != natives[j].Name {
continue
}
// calculate corresponding C entry
pc := uintptr(native_entry + uintptr(natives[j].EntryOff))
if stubs[i].CEntry != nil {
*stubs[i].CEntry = pc
}
// no need to generate wrapper, continue next
if stubs[i].GoFunc == nil {
continue
}
// assemble wrapper codes
layout := abi.NewFunctionLayout(reflect.TypeOf(stubs[i].GoFunc).Elem())
frame := abi.NewFrame(&layout, _C_Redzone, true)
tcode := abi.CallC(pc, frame, natives[j].MaxStack)
code = append(code, tcode...)
size := uint32(len(tcode))
fn := Func{
Flag: FuncFlag_ASM,
ArgsSize: int32(layout.ArgSize()),
EntryOff: entryOff,
TextSize: size,
Name: stubs[i].CName + "_go",
}
// add check-stack and grow-stack texts' pcsp
fn.Pcsp = &Pcdata{
{PC: uint32(frame.StackCheckTextSize()), Val: 0},
{PC: size - uint32(frame.GrowStackTextSize()), Val: int32(frame.Size())},
{PC: size, Val: 0},
}
// NOTICE: always refer to first file
fn.Pcfile = &Pcdata{
{PC: size, Val: 0},
}
// NOTICE: always refer to first line
fn.Pcline = &Pcdata{
{PC: size, Val: 1},
}
// NOTICE: always forbid async preempt
fn.PcUnsafePoint = &Pcdata{
{PC: size, Val: PCDATA_UnsafePointUnsafe},
}
// register pointer stackmaps
fn.PcStackMapIndex = &Pcdata{
{PC: size, Val: 0},
}
fn.ArgsPointerMaps = frame.ArgPtrs()
fn.LocalsPointerMaps = frame.LocalPtrs()
entryOff += size
wraps = append(wraps, fn)
wrapIds = append(wrapIds, i)
}
}
gofuncs := Load(code, wraps, modulename+"/go", []string{filename+".go"})
// set go func value
for i := range gofuncs {
idx := wrapIds[i]
w := rt.UnpackEface(stubs[idx].GoFunc)
*(*Function)(w.Value) = gofuncs[i]
}
}

@ -1,4 +1,4 @@
// +build amd64,go1.15,!go1.21
// +build amd64,go1.16,!go1.21
/*
* Copyright 2021 ByteDance Inc.

@ -19,10 +19,11 @@ NATIVE_SRC += $(wildcard native/*.c)
all: native_amd64.s
clean:
rm -vf native_amd64.s output/*.s
rm -vf native_text_amd64.go native_subr_amd64.go output/*.s
native_amd64.s: ${NATIVE_SRC} ${NATIVE_ASM} native_amd64.go
mkdir -p output
clang ${CFLAGS} -S -o output/native.s native/native.c
python3 tools/asm2asm/asm2asm.py native_amd64.s output/native.s ${NATIVE_ASM}
asmfmt -w native_amd64.s
python3 tools/asm2asm/asm2asm.py -r native_amd64.go output/native.s ${NATIVE_ASM}
awk '{gsub(/Text__native_entry__/, "text__native_entry__")}1' native_text_amd64.go > native_text_amd64.go.tmp && mv native_text_amd64.go.tmp native_text_amd64.go
awk '{gsub(/Funcs/, "funcs")}1' native_subr_amd64.go > native_subr_amd64.go.tmp && mv native_subr_amd64.go.tmp native_subr_amd64.go

@ -71,7 +71,7 @@ func (self Encoding) Encode(out []byte, src []byte) {
//
// It will also update the length of out.
func (self Encoding) EncodeUnsafe(out *[]byte, src []byte) {
__b64encode(out, &src, int(self) | archFlags)
b64encode(out, &src, int(self) | archFlags)
}
// EncodeToString returns the base64 encoding of src.
@ -120,7 +120,7 @@ func (self Encoding) Decode(out []byte, src []byte) (int, error) {
//
// It will also update the length of out.
func (self Encoding) DecodeUnsafe(out *[]byte, src []byte) (int, error) {
if n := __b64decode(out, mem2addr(src), len(src), int(self) | archFlags); n >= 0 {
if n := b64decode(out, mem2addr(src), len(src), int(self) | archFlags); n >= 0 {
return n, nil
} else {
return 0, base64.CorruptInputError(-n - 1)
@ -149,9 +149,3 @@ func (self Encoding) DecodedLen(n int) int {
return n * 6 / 8
}
}
func init() {
if hasAVX2() {
archFlags = _MODE_AVX2
}
}

@ -14,4 +14,4 @@ func hasAVX2() bool {
case "noavx2" : return false
default : panic(fmt.Sprintf("invalid mode: '%s', should be one of 'auto', 'noavx2'", v))
}
}
}

@ -21,3 +21,15 @@ func str2mem(s string) (v []byte) {
func mem2addr(v []byte) unsafe.Pointer {
return *(*unsafe.Pointer)(unsafe.Pointer(&v))
}
// NoEscape hides a pointer from escape analysis. NoEscape is
// the identity function but escape analysis doesn't think the
// output depends on the input. NoEscape is inlined and currently
// compiles down to zero instructions.
// USE CAREFULLY!
//go:nosplit
//goland:noinspection GoVetUnsafePointer
func noEscape(p unsafe.Pointer) unsafe.Pointer {
x := uintptr(p)
return unsafe.Pointer(x ^ 0)
}

@ -3,14 +3,40 @@ package base64x
import (
`unsafe`
`github.com/bytedance/sonic/loader`
)
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __b64encode(out *[]byte, src *[]byte, mode int)
func b64encode(out *[]byte, src *[]byte, mode int) {
__b64encode(noEscape(unsafe.Pointer(out)), noEscape(unsafe.Pointer(src)), mode)
}
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __b64decode(out *[]byte, src unsafe.Pointer, len int, mode int) (ret int)
func b64decode(out *[]byte, src unsafe.Pointer, len int, mode int) (ret int) {
return __b64decode(noEscape(unsafe.Pointer(out)), noEscape(unsafe.Pointer(src)), len, mode)
}
// asm2asm templates
var (
__b64encode func(out unsafe.Pointer, src unsafe.Pointer, mod int)
__b64decode func(out unsafe.Pointer, src unsafe.Pointer, len int, mod int) (ret int)
)
// directly jump PCs
var (
_subr__b64encode uintptr
_subr__b64decode uintptr
)
var stubs = []loader.GoC{
{"_b64encode", &_subr__b64encode, &__b64encode},
{"_b64decode", &_subr__b64decode, &__b64decode},
}
func init() {
if hasAVX2() {
archFlags = _MODE_AVX2
}
loader.WrapGoC(text__native_entry__, funcs, stubs, "base64x", "base64x/native.c")
}

File diff suppressed because it is too large Load Diff

@ -3,27 +3,61 @@
package base64x
//go:nosplit
//go:noescape
//goland:noinspection ALL
func __native_entry__() uintptr
import (
`github.com/bytedance/sonic/loader`
)
var (
_subr__b64decode = __native_entry__() + 1563
_subr__b64encode = __native_entry__() + 301
const (
_entry__b64decode = 1328
_entry__b64encode = 256
)
const (
_stack__b64decode = 128
_stack__b64decode = 152
_stack__b64encode = 40
)
var (
_ = _subr__b64decode
_ = _subr__b64encode
const (
_size__b64decode = 17616
_size__b64encode = 864
)
const (
_ = _stack__b64decode
_ = _stack__b64encode
var (
_pcsp__b64decode = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{12, 40},
{13, 48},
{17560, 152},
{17564, 48},
{17565, 40},
{17567, 32},
{17569, 24},
{17571, 16},
{17573, 8},
{17577, 0},
{17608, 152},
}
_pcsp__b64encode = [][2]uint32{
{1, 0},
{4, 8},
{6, 16},
{8, 24},
{10, 32},
{852, 40},
{853, 32},
{855, 24},
{857, 16},
{859, 8},
{864, 0},
}
)
var funcs = []loader.CFunc{
{"__native_entry__", 0, 67, 0, nil},
{"_b64decode", _entry__b64decode, _size__b64decode, _stack__b64decode, _pcsp__b64decode},
{"_b64encode", _entry__b64encode, _size__b64encode, _stack__b64encode, _pcsp__b64encode},
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

@ -0,0 +1,245 @@
package expr
import (
`fmt`
)
// Type is tyep expression type.
type Type int
const (
// CONST indicates that the expression is a constant.
CONST Type = iota
// TERM indicates that the expression is a Term reference.
TERM
// EXPR indicates that the expression is a unary or binary expression.
EXPR
)
var typeNames = map[Type]string {
EXPR : "Expr",
TERM : "Term",
CONST : "Const",
}
// String returns the string representation of a Type.
func (self Type) String() string {
if v, ok := typeNames[self]; ok {
return v
} else {
return fmt.Sprintf("expr.Type(%d)", self)
}
}
// Operator represents an operation to perform when Type is EXPR.
type Operator uint8
const (
// ADD performs "Add Expr.Left and Expr.Right".
ADD Operator = iota
// SUB performs "Subtract Expr.Left by Expr.Right".
SUB
// MUL performs "Multiply Expr.Left by Expr.Right".
MUL
// DIV performs "Divide Expr.Left by Expr.Right".
DIV
// MOD performs "Modulo Expr.Left by Expr.Right".
MOD
// AND performs "Bitwise AND Expr.Left and Expr.Right".
AND
// OR performs "Bitwise OR Expr.Left and Expr.Right".
OR
// XOR performs "Bitwise XOR Expr.Left and Expr.Right".
XOR
// SHL performs "Bitwise Shift Expr.Left to the Left by Expr.Right Bits".
SHL
// SHR performs "Bitwise Shift Expr.Left to the Right by Expr.Right Bits".
SHR
// POW performs "Raise Expr.Left to the power of Expr.Right"
POW
// NOT performs "Bitwise Invert Expr.Left".
NOT
// NEG performs "Negate Expr.Left".
NEG
)
var operatorNames = map[Operator]string {
ADD : "Add",
SUB : "Subtract",
MUL : "Multiply",
DIV : "Divide",
MOD : "Modulo",
AND : "And",
OR : "Or",
XOR : "ExclusiveOr",
SHL : "ShiftLeft",
SHR : "ShiftRight",
POW : "Power",
NOT : "Invert",
NEG : "Negate",
}
// String returns the string representation of a Type.
func (self Operator) String() string {
if v, ok := operatorNames[self]; ok {
return v
} else {
return fmt.Sprintf("expr.Operator(%d)", self)
}
}
// Expr represents an expression node.
type Expr struct {
Type Type
Term Term
Op Operator
Left *Expr
Right *Expr
Const int64
}
// Ref creates an expression from a Term.
func Ref(t Term) (p *Expr) {
p = newExpression()
p.Term = t
p.Type = TERM
return
}
// Int creates an expression from an integer.
func Int(v int64) (p *Expr) {
p = newExpression()
p.Type = CONST
p.Const = v
return
}
func (self *Expr) clear() {
if self.Term != nil { self.Term.Free() }
if self.Left != nil { self.Left.Free() }
if self.Right != nil { self.Right.Free() }
}
// Free returns the Expr into pool.
// Any operation performed after Free is undefined behavior.
func (self *Expr) Free() {
self.clear()
freeExpression(self)
}
// Evaluate evaluates the expression into an integer.
// It also implements the Term interface.
func (self *Expr) Evaluate() (int64, error) {
switch self.Type {
case EXPR : return self.eval()
case TERM : return self.Term.Evaluate()
case CONST : return self.Const, nil
default : panic("invalid expression type: " + self.Type.String())
}
}
/** Expression Combinator **/
func combine(a *Expr, op Operator, b *Expr) (r *Expr) {
r = newExpression()
r.Op = op
r.Type = EXPR
r.Left = a
r.Right = b
return
}
func (self *Expr) Add(v *Expr) *Expr { return combine(self, ADD, v) }
func (self *Expr) Sub(v *Expr) *Expr { return combine(self, SUB, v) }
func (self *Expr) Mul(v *Expr) *Expr { return combine(self, MUL, v) }
func (self *Expr) Div(v *Expr) *Expr { return combine(self, DIV, v) }
func (self *Expr) Mod(v *Expr) *Expr { return combine(self, MOD, v) }
func (self *Expr) And(v *Expr) *Expr { return combine(self, AND, v) }
func (self *Expr) Or (v *Expr) *Expr { return combine(self, OR , v) }
func (self *Expr) Xor(v *Expr) *Expr { return combine(self, XOR, v) }
func (self *Expr) Shl(v *Expr) *Expr { return combine(self, SHL, v) }
func (self *Expr) Shr(v *Expr) *Expr { return combine(self, SHR, v) }
func (self *Expr) Pow(v *Expr) *Expr { return combine(self, POW, v) }
func (self *Expr) Not() *Expr { return combine(self, NOT, nil) }
func (self *Expr) Neg() *Expr { return combine(self, NEG, nil) }
/** Expression Evaluator **/
var binaryEvaluators = [256]func(int64, int64) (int64, error) {
ADD: func(a, b int64) (int64, error) { return a + b, nil },
SUB: func(a, b int64) (int64, error) { return a - b, nil },
MUL: func(a, b int64) (int64, error) { return a * b, nil },
DIV: idiv,
MOD: imod,
AND: func(a, b int64) (int64, error) { return a & b, nil },
OR: func(a, b int64) (int64, error) { return a | b, nil },
XOR: func(a, b int64) (int64, error) { return a ^ b, nil },
SHL: func(a, b int64) (int64, error) { return a << b, nil },
SHR: func(a, b int64) (int64, error) { return a >> b, nil },
POW: ipow,
}
func (self *Expr) eval() (int64, error) {
var lhs int64
var rhs int64
var err error
var vfn func(int64, int64) (int64, error)
/* evaluate LHS */
if lhs, err = self.Left.Evaluate(); err != nil {
return 0, err
}
/* check for unary operators */
switch self.Op {
case NOT: return self.unaryNot(lhs)
case NEG: return self.unaryNeg(lhs)
}
/* check for operators */
if vfn = binaryEvaluators[self.Op]; vfn == nil {
panic("invalid operator: " + self.Op.String())
}
/* must be a binary expression */
if self.Right == nil {
panic("operator " + self.Op.String() + " is a binary operator")
}
/* evaluate RHS, and call the operator */
if rhs, err = self.Right.Evaluate(); err != nil {
return 0, err
} else {
return vfn(lhs, rhs)
}
}
func (self *Expr) unaryNot(v int64) (int64, error) {
if self.Right == nil {
return ^v, nil
} else {
panic("operator Invert is an unary operator")
}
}
func (self *Expr) unaryNeg(v int64) (int64, error) {
if self.Right == nil {
return -v, nil
} else {
panic("operator Negate is an unary operator")
}
}

@ -0,0 +1,37 @@
package expr
import (
`fmt`
)
// SyntaxError represents a syntax error in the expression.
type SyntaxError struct {
Pos int
Reason string
}
func newSyntaxError(pos int, reason string) *SyntaxError {
return &SyntaxError {
Pos : pos,
Reason : reason,
}
}
func (self *SyntaxError) Error() string {
return fmt.Sprintf("Syntax error at position %d: %s", self.Pos, self.Reason)
}
// RuntimeError is an error which would occure at run time.
type RuntimeError struct {
Reason string
}
func newRuntimeError(reason string) *RuntimeError {
return &RuntimeError {
Reason: reason,
}
}
func (self *RuntimeError) Error() string {
return "Runtime error: " + self.Reason
}

@ -0,0 +1,51 @@
package expr
import (
`fmt`
)
func idiv(v int64, d int64) (int64, error) {
if d != 0 {
return v / d, nil
} else {
return 0, newRuntimeError("division by zero")
}
}
func imod(v int64, d int64) (int64, error) {
if d != 0 {
return v % d, nil
} else {
return 0, newRuntimeError("division by zero")
}
}
func ipow(v int64, e int64) (int64, error) {
mul := v
ret := int64(1)
/* value must be 0 or positive */
if v < 0 {
return 0, newRuntimeError(fmt.Sprintf("negative base value: %d", v))
}
/* exponent must be non-negative */
if e < 0 {
return 0, newRuntimeError(fmt.Sprintf("negative exponent: %d", e))
}
/* fast power first round */
if (e & 1) != 0 {
ret *= mul
}
/* fast power remaining rounds */
for e >>= 1; e != 0; e >>= 1 {
if mul *= mul; (e & 1) != 0 {
ret *= mul
}
}
/* all done */
return ret, nil
}

@ -0,0 +1,313 @@
package expr
import (
`strconv`
`unicode`
`unsafe`
)
type _TokenKind uint8
const (
_T_end _TokenKind = iota + 1
_T_int
_T_punc
_T_name
)
const (
_OP2 = 0x80
_POW = _OP2 | '*'
_SHL = _OP2 | '<'
_SHR = _OP2 | '>'
)
type _Slice struct {
p unsafe.Pointer
n int
c int
}
type _Token struct {
pos int
ptr *rune
u64 uint64
tag _TokenKind
}
func (self _Token) str() (v string) {
return string(self.rbuf())
}
func (self _Token) rbuf() (v []rune) {
(*_Slice)(unsafe.Pointer(&v)).c = int(self.u64)
(*_Slice)(unsafe.Pointer(&v)).n = int(self.u64)
(*_Slice)(unsafe.Pointer(&v)).p = unsafe.Pointer(self.ptr)
return
}
func tokenEnd(p int) _Token {
return _Token {
pos: p,
tag: _T_end,
}
}
func tokenInt(p int, v uint64) _Token {
return _Token {
pos: p,
u64: v,
tag: _T_int,
}
}
func tokenPunc(p int, v rune) _Token {
return _Token {
pos: p,
tag: _T_punc,
u64: uint64(v),
}
}
func tokenName(p int, v []rune) _Token {
return _Token {
pos: p,
ptr: &v[0],
tag: _T_name,
u64: uint64(len(v)),
}
}
// Repository represents a repository of Term's.
type Repository interface {
Get(name string) (Term, error)
}
// Parser parses an expression string to it's AST representation.
type Parser struct {
pos int
src []rune
}
var binaryOps = [...]func(*Expr, *Expr) *Expr {
'+' : (*Expr).Add,
'-' : (*Expr).Sub,
'*' : (*Expr).Mul,
'/' : (*Expr).Div,
'%' : (*Expr).Mod,
'&' : (*Expr).And,
'^' : (*Expr).Xor,
'|' : (*Expr).Or,
_SHL : (*Expr).Shl,
_SHR : (*Expr).Shr,
_POW : (*Expr).Pow,
}
var precedence = [...]map[int]bool {
{_SHL: true, _SHR: true},
{'|' : true},
{'^' : true},
{'&' : true},
{'+' : true, '-': true},
{'*' : true, '/': true, '%': true},
{_POW: true},
}
func (self *Parser) ch() rune {
return self.src[self.pos]
}
func (self *Parser) eof() bool {
return self.pos >= len(self.src)
}
func (self *Parser) rch() (v rune) {
v, self.pos = self.src[self.pos], self.pos + 1
return
}
func (self *Parser) hex(ss []rune) bool {
if len(ss) == 1 && ss[0] == '0' {
return unicode.ToLower(self.ch()) == 'x'
} else if len(ss) <= 1 || unicode.ToLower(ss[1]) != 'x' {
return unicode.IsDigit(self.ch())
} else {
return ishexdigit(self.ch())
}
}
func (self *Parser) int(p int, ss []rune) (_Token, error) {
var err error
var val uint64
/* find all the digits */
for !self.eof() && self.hex(ss) {
ss = append(ss, self.rch())
}
/* parse the value */
if val, err = strconv.ParseUint(string(ss), 0, 64); err != nil {
return _Token{}, err
} else {
return tokenInt(p, val), nil
}
}
func (self *Parser) name(p int, ss []rune) _Token {
for !self.eof() && isident(self.ch()) { ss = append(ss, self.rch()) }
return tokenName(p, ss)
}
func (self *Parser) read(p int, ch rune) (_Token, error) {
if isdigit(ch) {
return self.int(p, []rune { ch })
} else if isident0(ch) {
return self.name(p, []rune { ch }), nil
} else if isop2ch(ch) && !self.eof() && self.ch() == ch {
return tokenPunc(p, _OP2 | self.rch()), nil
} else if isop1ch(ch) {
return tokenPunc(p, ch), nil
} else {
return _Token{}, newSyntaxError(self.pos, "invalid character " + strconv.QuoteRuneToASCII(ch))
}
}
func (self *Parser) next() (_Token, error) {
for {
var p int
var c rune
/* check for EOF */
if self.eof() {
return tokenEnd(self.pos), nil
}
/* read the next char */
p = self.pos
c = self.rch()
/* parse the token if not a space */
if !unicode.IsSpace(c) {
return self.read(p, c)
}
}
}
func (self *Parser) grab(tk _Token, repo Repository) (*Expr, error) {
if repo == nil {
return nil, newSyntaxError(tk.pos, "unresolved symbol: " + tk.str())
} else if term, err := repo.Get(tk.str()); err != nil {
return nil, err
} else {
return Ref(term), nil
}
}
func (self *Parser) nest(nest int, repo Repository) (*Expr, error) {
var err error
var ret *Expr
var ntk _Token
/* evaluate the nested expression */
if ret, err = self.expr(0, nest + 1, repo); err != nil {
return nil, err
}
/* must follows with a ')' */
if ntk, err = self.next(); err != nil {
return nil, err
} else if ntk.tag != _T_punc || ntk.u64 != ')' {
return nil, newSyntaxError(ntk.pos, "')' expected")
} else {
return ret, nil
}
}
func (self *Parser) unit(nest int, repo Repository) (*Expr, error) {
if tk, err := self.next(); err != nil {
return nil, err
} else if tk.tag == _T_int {
return Int(int64(tk.u64)), nil
} else if tk.tag == _T_name {
return self.grab(tk, repo)
} else if tk.tag == _T_punc && tk.u64 == '(' {
return self.nest(nest, repo)
} else if tk.tag == _T_punc && tk.u64 == '+' {
return self.unit(nest, repo)
} else if tk.tag == _T_punc && tk.u64 == '-' {
return neg2(self.unit(nest, repo))
} else if tk.tag == _T_punc && tk.u64 == '~' {
return not2(self.unit(nest, repo))
} else {
return nil, newSyntaxError(tk.pos, "integer, unary operator or nested expression expected")
}
}
func (self *Parser) term(prec int, nest int, repo Repository) (*Expr, error) {
var err error
var val *Expr
/* parse the LHS operand */
if val, err = self.expr(prec + 1, nest, repo); err != nil {
return nil, err
}
/* parse all the operators of the same precedence */
for {
var op int
var rv *Expr
var tk _Token
/* peek the next token */
pp := self.pos
tk, err = self.next()
/* check for errors */
if err != nil {
return nil, err
}
/* encountered EOF */
if tk.tag == _T_end {
return val, nil
}
/* must be an operator */
if tk.tag != _T_punc {
return nil, newSyntaxError(tk.pos, "operators expected")
}
/* check for the operator precedence */
if op = int(tk.u64); !precedence[prec][op] {
self.pos = pp
return val, nil
}
/* evaluate the RHS operand, and combine the value */
if rv, err = self.expr(prec + 1, nest, repo); err != nil {
return nil, err
} else {
val = binaryOps[op](val, rv)
}
}
}
func (self *Parser) expr(prec int, nest int, repo Repository) (*Expr, error) {
if prec >= len(precedence) {
return self.unit(nest, repo)
} else {
return self.term(prec, nest, repo)
}
}
// Parse parses the expression, and returns it's AST tree.
func (self *Parser) Parse(repo Repository) (*Expr, error) {
return self.expr(0, 0, repo)
}
// SetSource resets the expression parser and sets the expression source.
func (self *Parser) SetSource(src string) *Parser {
self.pos = 0
self.src = []rune(src)
return self
}

@ -0,0 +1,26 @@
package expr
import (
`sync`
)
var (
expressionPool sync.Pool
)
func newExpression() *Expr {
if v := expressionPool.Get(); v == nil {
return new(Expr)
} else {
return resetExpression(v.(*Expr))
}
}
func freeExpression(p *Expr) {
expressionPool.Put(p)
}
func resetExpression(p *Expr) *Expr {
*p = Expr{}
return p
}

@ -0,0 +1,7 @@
package expr
// Term represents a value that can Evaluate() into an integer.
type Term interface {
Free()
Evaluate() (int64, error)
}

@ -0,0 +1,61 @@
package expr
var op1ch = [...]bool {
'+': true,
'-': true,
'*': true,
'/': true,
'%': true,
'&': true,
'|': true,
'^': true,
'~': true,
'(': true,
')': true,
}
var op2ch = [...]bool {
'*': true,
'<': true,
'>': true,
}
func neg2(v *Expr, err error) (*Expr, error) {
if err != nil {
return nil, err
} else {
return v.Neg(), nil
}
}
func not2(v *Expr, err error) (*Expr, error) {
if err != nil {
return nil, err
} else {
return v.Not(), nil
}
}
func isop1ch(ch rune) bool {
return ch >= 0 && int(ch) < len(op1ch) && op1ch[ch]
}
func isop2ch(ch rune) bool {
return ch >= 0 && int(ch) < len(op2ch) && op2ch[ch]
}
func isdigit(ch rune) bool {
return ch >= '0' && ch <= '9'
}
func isident(ch rune) bool {
return isdigit(ch) || isident0(ch)
}
func isident0(ch rune) bool {
return (ch == '_') || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')
}
func ishexdigit(ch rune) bool {
return isdigit(ch) || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')
}

@ -0,0 +1,235 @@
package x86_64
import (
`fmt`
)
// ISA represents an extension to x86-64 instruction set.
type ISA uint64
const (
ISA_CPUID ISA = 1 << iota
ISA_RDTSC
ISA_RDTSCP
ISA_CMOV
ISA_MOVBE
ISA_POPCNT
ISA_LZCNT
ISA_TBM
ISA_BMI
ISA_BMI2
ISA_ADX
ISA_MMX
ISA_MMX_PLUS
ISA_FEMMS
ISA_3DNOW
ISA_3DNOW_PLUS
ISA_SSE
ISA_SSE2
ISA_SSE3
ISA_SSSE3
ISA_SSE4A
ISA_SSE4_1
ISA_SSE4_2
ISA_FMA3
ISA_FMA4
ISA_XOP
ISA_F16C
ISA_AVX
ISA_AVX2
ISA_AVX512F
ISA_AVX512BW
ISA_AVX512DQ
ISA_AVX512VL
ISA_AVX512PF
ISA_AVX512ER
ISA_AVX512CD
ISA_AVX512VBMI
ISA_AVX512IFMA
ISA_AVX512VPOPCNTDQ
ISA_AVX512_4VNNIW
ISA_AVX512_4FMAPS
ISA_PREFETCH
ISA_PREFETCHW
ISA_PREFETCHWT1
ISA_CLFLUSH
ISA_CLFLUSHOPT
ISA_CLWB
ISA_CLZERO
ISA_RDRAND
ISA_RDSEED
ISA_PCLMULQDQ
ISA_AES
ISA_SHA
ISA_MONITOR
ISA_MONITORX
ISA_ALL = ^ISA(0)
)
var _ISA_NAMES = map[ISA]string {
ISA_CPUID : "CPUID",
ISA_RDTSC : "RDTSC",
ISA_RDTSCP : "RDTSCP",
ISA_CMOV : "CMOV",
ISA_MOVBE : "MOVBE",
ISA_POPCNT : "POPCNT",
ISA_LZCNT : "LZCNT",
ISA_TBM : "TBM",
ISA_BMI : "BMI",
ISA_BMI2 : "BMI2",
ISA_ADX : "ADX",
ISA_MMX : "MMX",
ISA_MMX_PLUS : "MMX+",
ISA_FEMMS : "FEMMS",
ISA_3DNOW : "3dnow!",
ISA_3DNOW_PLUS : "3dnow!+",
ISA_SSE : "SSE",
ISA_SSE2 : "SSE2",
ISA_SSE3 : "SSE3",
ISA_SSSE3 : "SSSE3",
ISA_SSE4A : "SSE4A",
ISA_SSE4_1 : "SSE4.1",
ISA_SSE4_2 : "SSE4.2",
ISA_FMA3 : "FMA3",
ISA_FMA4 : "FMA4",
ISA_XOP : "XOP",
ISA_F16C : "F16C",
ISA_AVX : "AVX",
ISA_AVX2 : "AVX2",
ISA_AVX512F : "AVX512F",
ISA_AVX512BW : "AVX512BW",
ISA_AVX512DQ : "AVX512DQ",
ISA_AVX512VL : "AVX512VL",
ISA_AVX512PF : "AVX512PF",
ISA_AVX512ER : "AVX512ER",
ISA_AVX512CD : "AVX512CD",
ISA_AVX512VBMI : "AVX512VBMI",
ISA_AVX512IFMA : "AVX512IFMA",
ISA_AVX512VPOPCNTDQ : "AVX512VPOPCNTDQ",
ISA_AVX512_4VNNIW : "AVX512_4VNNIW",
ISA_AVX512_4FMAPS : "AVX512_4FMAPS",
ISA_PREFETCH : "PREFETCH",
ISA_PREFETCHW : "PREFETCHW",
ISA_PREFETCHWT1 : "PREFETCHWT1",
ISA_CLFLUSH : "CLFLUSH",
ISA_CLFLUSHOPT : "CLFLUSHOPT",
ISA_CLWB : "CLWB",
ISA_CLZERO : "CLZERO",
ISA_RDRAND : "RDRAND",
ISA_RDSEED : "RDSEED",
ISA_PCLMULQDQ : "PCLMULQDQ",
ISA_AES : "AES",
ISA_SHA : "SHA",
ISA_MONITOR : "MONITOR",
ISA_MONITORX : "MONITORX",
}
var _ISA_MAPPING = map[string]ISA {
"CPUID" : ISA_CPUID,
"RDTSC" : ISA_RDTSC,
"RDTSCP" : ISA_RDTSCP,
"CMOV" : ISA_CMOV,
"MOVBE" : ISA_MOVBE,
"POPCNT" : ISA_POPCNT,
"LZCNT" : ISA_LZCNT,
"TBM" : ISA_TBM,
"BMI" : ISA_BMI,
"BMI2" : ISA_BMI2,
"ADX" : ISA_ADX,
"MMX" : ISA_MMX,
"MMX+" : ISA_MMX_PLUS,
"FEMMS" : ISA_FEMMS,
"3dnow!" : ISA_3DNOW,
"3dnow!+" : ISA_3DNOW_PLUS,
"SSE" : ISA_SSE,
"SSE2" : ISA_SSE2,
"SSE3" : ISA_SSE3,
"SSSE3" : ISA_SSSE3,
"SSE4A" : ISA_SSE4A,
"SSE4.1" : ISA_SSE4_1,
"SSE4.2" : ISA_SSE4_2,
"FMA3" : ISA_FMA3,
"FMA4" : ISA_FMA4,
"XOP" : ISA_XOP,
"F16C" : ISA_F16C,
"AVX" : ISA_AVX,
"AVX2" : ISA_AVX2,
"AVX512F" : ISA_AVX512F,
"AVX512BW" : ISA_AVX512BW,
"AVX512DQ" : ISA_AVX512DQ,
"AVX512VL" : ISA_AVX512VL,
"AVX512PF" : ISA_AVX512PF,
"AVX512ER" : ISA_AVX512ER,
"AVX512CD" : ISA_AVX512CD,
"AVX512VBMI" : ISA_AVX512VBMI,
"AVX512IFMA" : ISA_AVX512IFMA,
"AVX512VPOPCNTDQ" : ISA_AVX512VPOPCNTDQ,
"AVX512_4VNNIW" : ISA_AVX512_4VNNIW,
"AVX512_4FMAPS" : ISA_AVX512_4FMAPS,
"PREFETCH" : ISA_PREFETCH,
"PREFETCHW" : ISA_PREFETCHW,
"PREFETCHWT1" : ISA_PREFETCHWT1,
"CLFLUSH" : ISA_CLFLUSH,
"CLFLUSHOPT" : ISA_CLFLUSHOPT,
"CLWB" : ISA_CLWB,
"CLZERO" : ISA_CLZERO,
"RDRAND" : ISA_RDRAND,
"RDSEED" : ISA_RDSEED,
"PCLMULQDQ" : ISA_PCLMULQDQ,
"AES" : ISA_AES,
"SHA" : ISA_SHA,
"MONITOR" : ISA_MONITOR,
"MONITORX" : ISA_MONITORX,
}
func (self ISA) String() string {
if v, ok := _ISA_NAMES[self]; ok {
return v
} else {
return fmt.Sprintf("(invalid: %#x)", uint64(self))
}
}
// ParseISA parses name into ISA, it will panic if the name is invalid.
func ParseISA(name string) ISA {
if v, ok := _ISA_MAPPING[name]; ok {
return v
} else {
panic("invalid ISA name: " + name)
}
}
// Arch represents the x86_64 architecture.
type Arch struct {
isa ISA
}
// DefaultArch is the default architecture with all ISA enabled.
var DefaultArch = CreateArch()
// CreateArch creates a new Arch with all ISA enabled.
func CreateArch() *Arch {
return new(Arch).EnableISA(ISA_ALL)
}
// HasISA checks if a particular ISA was enabled.
func (self *Arch) HasISA(isa ISA) bool {
return (self.isa & isa) != 0
}
// EnableISA enables a particular ISA.
func (self *Arch) EnableISA(isa ISA) *Arch {
self.isa |= isa
return self
}
// DisableISA disables a particular ISA.
func (self *Arch) DisableISA(isa ISA) *Arch {
self.isa &^= isa
return self
}
// CreateProgram creates a new empty program.
func (self *Arch) CreateProgram() *Program {
return newProgram(self)
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,33 @@
package x86_64
func alias_INT3(p *Program, vv ...interface{}) *Instruction {
if len(vv) == 0 {
return p.INT(3)
} else {
panic("instruction INT3 takes no operands")
}
}
func alias_VCMPEQPS(p *Program, vv ...interface{}) *Instruction {
if len(vv) >= 3 {
return p.VCMPPS(0x00, vv[0], vv[1], vv[2], vv[3:]...)
} else {
panic("instruction VCMPEQPS takes 3 or 4 operands")
}
}
func alias_VCMPTRUEPS(p *Program, vv ...interface{}) *Instruction {
if len(vv) >= 3 {
return p.VCMPPS(0x0f, vv[0], vv[1], vv[2], vv[3:]...)
} else {
panic("instruction VCMPTRUEPS takes 3 or 4 operands")
}
}
var _InstructionAliases = map[string]_InstructionEncoder {
"int3" : alias_INT3,
"retq" : Instructions["ret"],
"movabsq" : Instructions["movq"],
"vcmpeqps" : alias_VCMPEQPS,
"vcmptrueps" : alias_VCMPTRUEPS,
}

@ -0,0 +1,63 @@
package x86_64
import (
`reflect`
`unsafe`
)
type _GoType struct {
size uintptr
pdata uintptr
hash uint32
flags uint8
align uint8
falign uint8
kflags uint8
traits unsafe.Pointer
gcdata *byte
str int32
ptrx int32
}
const (
_KindMask = (1 << 5) - 1
)
func (self *_GoType) kind() reflect.Kind {
return reflect.Kind(self.kflags & _KindMask)
}
type _GoSlice struct {
ptr unsafe.Pointer
len int
cap int
}
type _GoEface struct {
vt *_GoType
ptr unsafe.Pointer
}
func (self *_GoEface) kind() reflect.Kind {
if self.vt != nil {
return self.vt.kind()
} else {
return reflect.Invalid
}
}
func (self *_GoEface) toInt64() int64 {
if self.vt.size == 8 {
return *(*int64)(self.ptr)
} else if self.vt.size == 4 {
return int64(*(*int32)(self.ptr))
} else if self.vt.size == 2 {
return int64(*(*int16)(self.ptr))
} else {
return int64(*(*int8)(self.ptr))
}
}
func efaceOf(v interface{}) _GoEface {
return *(*_GoEface)(unsafe.Pointer(&v))
}

@ -0,0 +1,675 @@
package x86_64
import (
`encoding/binary`
`math`
)
/** Operand Encoding Helpers **/
func imml(v interface{}) byte {
return byte(toImmAny(v) & 0x0f)
}
func relv(v interface{}) int64 {
switch r := v.(type) {
case *Label : return 0
case RelativeOffset : return int64(r)
default : panic("invalid relative offset")
}
}
func addr(v interface{}) interface{} {
switch a := v.(*MemoryOperand).Addr; a.Type {
case Memory : return a.Memory
case Offset : return a.Offset
case Reference : return a.Reference
default : panic("invalid memory operand type")
}
}
func bcode(v interface{}) byte {
if m, ok := v.(*MemoryOperand); !ok {
panic("v is not a memory operand")
} else if m.Broadcast == 0 {
return 0
} else {
return 1
}
}
func vcode(v interface{}) byte {
switch r := v.(type) {
case XMMRegister : return byte(r)
case YMMRegister : return byte(r)
case ZMMRegister : return byte(r)
case MaskedRegister : return vcode(r.Reg)
default : panic("v is not a vector register")
}
}
func kcode(v interface{}) byte {
switch r := v.(type) {
case KRegister : return byte(r)
case XMMRegister : return 0
case YMMRegister : return 0
case ZMMRegister : return 0
case RegisterMask : return byte(r.K)
case MaskedRegister : return byte(r.Mask.K)
case *MemoryOperand : return toKcodeMem(r)
default : panic("v is not a maskable operand")
}
}
func zcode(v interface{}) byte {
switch r := v.(type) {
case KRegister : return 0
case XMMRegister : return 0
case YMMRegister : return 0
case ZMMRegister : return 0
case RegisterMask : return toZcodeRegM(r)
case MaskedRegister : return toZcodeRegM(r.Mask)
case *MemoryOperand : return toZcodeMem(r)
default : panic("v is not a maskable operand")
}
}
func lcode(v interface{}) byte {
switch r := v.(type) {
case Register8 : return byte(r & 0x07)
case Register16 : return byte(r & 0x07)
case Register32 : return byte(r & 0x07)
case Register64 : return byte(r & 0x07)
case KRegister : return byte(r & 0x07)
case MMRegister : return byte(r & 0x07)
case XMMRegister : return byte(r & 0x07)
case YMMRegister : return byte(r & 0x07)
case ZMMRegister : return byte(r & 0x07)
case MaskedRegister : return lcode(r.Reg)
default : panic("v is not a register")
}
}
func hcode(v interface{}) byte {
switch r := v.(type) {
case Register8 : return byte(r >> 3) & 1
case Register16 : return byte(r >> 3) & 1
case Register32 : return byte(r >> 3) & 1
case Register64 : return byte(r >> 3) & 1
case KRegister : return byte(r >> 3) & 1
case MMRegister : return byte(r >> 3) & 1
case XMMRegister : return byte(r >> 3) & 1
case YMMRegister : return byte(r >> 3) & 1
case ZMMRegister : return byte(r >> 3) & 1
case MaskedRegister : return hcode(r.Reg)
default : panic("v is not a register")
}
}
func ecode(v interface{}) byte {
switch r := v.(type) {
case Register8 : return byte(r >> 4) & 1
case Register16 : return byte(r >> 4) & 1
case Register32 : return byte(r >> 4) & 1
case Register64 : return byte(r >> 4) & 1
case KRegister : return byte(r >> 4) & 1
case MMRegister : return byte(r >> 4) & 1
case XMMRegister : return byte(r >> 4) & 1
case YMMRegister : return byte(r >> 4) & 1
case ZMMRegister : return byte(r >> 4) & 1
case MaskedRegister : return ecode(r.Reg)
default : panic("v is not a register")
}
}
func hlcode(v interface{}) byte {
switch r := v.(type) {
case Register8 : return toHLcodeReg8(r)
case Register16 : return byte(r & 0x0f)
case Register32 : return byte(r & 0x0f)
case Register64 : return byte(r & 0x0f)
case KRegister : return byte(r & 0x0f)
case MMRegister : return byte(r & 0x0f)
case XMMRegister : return byte(r & 0x0f)
case YMMRegister : return byte(r & 0x0f)
case ZMMRegister : return byte(r & 0x0f)
case MaskedRegister : return hlcode(r.Reg)
default : panic("v is not a register")
}
}
func ehcode(v interface{}) byte {
switch r := v.(type) {
case Register8 : return byte(r >> 3) & 0x03
case Register16 : return byte(r >> 3) & 0x03
case Register32 : return byte(r >> 3) & 0x03
case Register64 : return byte(r >> 3) & 0x03
case KRegister : return byte(r >> 3) & 0x03
case MMRegister : return byte(r >> 3) & 0x03
case XMMRegister : return byte(r >> 3) & 0x03
case YMMRegister : return byte(r >> 3) & 0x03
case ZMMRegister : return byte(r >> 3) & 0x03
case MaskedRegister : return ehcode(r.Reg)
default : panic("v is not a register")
}
}
func toImmAny(v interface{}) int64 {
if x, ok := asInt64(v); ok {
return x
} else {
panic("value is not an integer")
}
}
func toHcodeOpt(v interface{}) byte {
if v == nil {
return 0
} else {
return hcode(v)
}
}
func toEcodeVMM(v interface{}, x byte) byte {
switch r := v.(type) {
case XMMRegister : return ecode(r)
case YMMRegister : return ecode(r)
case ZMMRegister : return ecode(r)
default : return x
}
}
func toKcodeMem(v *MemoryOperand) byte {
if !v.Masked {
return 0
} else {
return byte(v.Mask.K)
}
}
func toZcodeMem(v *MemoryOperand) byte {
if !v.Masked || v.Mask.Z {
return 0
} else {
return 1
}
}
func toZcodeRegM(v RegisterMask) byte {
if v.Z {
return 1
} else {
return 0
}
}
func toHLcodeReg8(v Register8) byte {
switch v {
case AH: fallthrough
case BH: fallthrough
case CH: fallthrough
case DH: panic("ah/bh/ch/dh registers never use 4-bit encoding")
default: return byte(v & 0x0f)
}
}
/** Instruction Encoding Helpers **/
const (
_N_inst = 16
)
const (
_F_rel1 = 1 << iota
_F_rel4
)
type _Encoding struct {
len int
flags int
bytes [_N_inst]byte
encoder func(m *_Encoding, v []interface{})
}
// buf ensures len + n <= len(bytes).
func (self *_Encoding) buf(n int) []byte {
if i := self.len; i + n > _N_inst {
panic("instruction too long")
} else {
return self.bytes[i:]
}
}
// emit encodes a single byte.
func (self *_Encoding) emit(v byte) {
self.buf(1)[0] = v
self.len++
}
// imm1 encodes a single byte immediate value.
func (self *_Encoding) imm1(v int64) {
self.emit(byte(v))
}
// imm2 encodes a two-byte immediate value in little-endian.
func (self *_Encoding) imm2(v int64) {
binary.LittleEndian.PutUint16(self.buf(2), uint16(v))
self.len += 2
}
// imm4 encodes a 4-byte immediate value in little-endian.
func (self *_Encoding) imm4(v int64) {
binary.LittleEndian.PutUint32(self.buf(4), uint32(v))
self.len += 4
}
// imm8 encodes an 8-byte immediate value in little-endian.
func (self *_Encoding) imm8(v int64) {
binary.LittleEndian.PutUint64(self.buf(8), uint64(v))
self.len += 8
}
// vex2 encodes a 2-byte or 3-byte VEX prefix.
//
// 2-byte VEX prefix:
// Requires: VEX.W = 0, VEX.mmmmm = 0b00001 and VEX.B = VEX.X = 0
// +----------------+
// Byte 0: | Bits 0-7: 0xc5 |
// +----------------+
//
// +-----------+----------------+----------+--------------+
// Byte 1: | Bit 7: ~R | Bits 3-6 ~vvvv | Bit 2: L | Bits 0-1: pp |
// +-----------+----------------+----------+--------------+
//
// 3-byte VEX prefix:
// +----------------+
// Byte 0: | Bits 0-7: 0xc4 |
// +----------------+
//
// +-----------+-----------+-----------+-------------------+
// Byte 1: | Bit 7: ~R | Bit 6: ~X | Bit 5: ~B | Bits 0-4: 0b00001 |
// +-----------+-----------+-----------+-------------------+
//
// +----------+-----------------+----------+--------------+
// Byte 2: | Bit 7: 0 | Bits 3-6: ~vvvv | Bit 2: L | Bits 0-1: pp |
// +----------+-----------------+----------+--------------+
//
func (self *_Encoding) vex2(lpp byte, r byte, rm interface{}, vvvv byte) {
var b byte
var x byte
/* VEX.R must be a single-bit mask */
if r > 1 {
panic("VEX.R must be a 1-bit mask")
}
/* VEX.Lpp must be a 3-bit mask */
if lpp &^ 0b111 != 0 {
panic("VEX.Lpp must be a 3-bit mask")
}
/* VEX.vvvv must be a 4-bit mask */
if vvvv &^ 0b1111 != 0 {
panic("VEX.vvvv must be a 4-bit mask")
}
/* encode the RM bits if any */
if rm != nil {
switch v := rm.(type) {
case *Label : break
case Register : b = hcode(v)
case MemoryAddress : b, x = toHcodeOpt(v.Base), toHcodeOpt(v.Index)
case RelativeOffset : break
default : panic("rm is expected to be a register or a memory address")
}
}
/* if VEX.B and VEX.X are zeroes, 2-byte VEX prefix can be used */
if x == 0 && b == 0 {
self.emit(0xc5)
self.emit(0xf8 ^ (r << 7) ^ (vvvv << 3) ^ lpp)
} else {
self.emit(0xc4)
self.emit(0xe1 ^ (r << 7) ^ (x << 6) ^ (b << 5))
self.emit(0x78 ^ (vvvv << 3) ^ lpp)
}
}
// vex3 encodes a 3-byte VEX or XOP prefix.
//
// 3-byte VEX/XOP prefix
// +-----------------------------------+
// Byte 0: | Bits 0-7: 0xc4 (VEX) / 0x8f (XOP) |
// +-----------------------------------+
//
// +-----------+-----------+-----------+-----------------+
// Byte 1: | Bit 7: ~R | Bit 6: ~X | Bit 5: ~B | Bits 0-4: mmmmm |
// +-----------+-----------+-----------+-----------------+
//
// +----------+-----------------+----------+--------------+
// Byte 2: | Bit 7: W | Bits 3-6: ~vvvv | Bit 2: L | Bits 0-1: pp |
// +----------+-----------------+----------+--------------+
//
func (self *_Encoding) vex3(esc byte, mmmmm byte, wlpp byte, r byte, rm interface{}, vvvv byte) {
var b byte
var x byte
/* VEX.R must be a single-bit mask */
if r > 1 {
panic("VEX.R must be a 1-bit mask")
}
/* VEX.vvvv must be a 4-bit mask */
if vvvv &^ 0b1111 != 0 {
panic("VEX.vvvv must be a 4-bit mask")
}
/* escape must be a 3-byte VEX (0xc4) or XOP (0x8f) prefix */
if esc != 0xc4 && esc != 0x8f {
panic("escape must be a 3-byte VEX (0xc4) or XOP (0x8f) prefix")
}
/* VEX.W____Lpp is expected to have no bits set except 0, 1, 2 and 7 */
if wlpp &^ 0b10000111 != 0 {
panic("VEX.W____Lpp is expected to have no bits set except 0, 1, 2 and 7")
}
/* VEX.m-mmmm is expected to be a 5-bit mask */
if mmmmm &^ 0b11111 != 0 {
panic("VEX.m-mmmm is expected to be a 5-bit mask")
}
/* encode the RM bits */
switch v := rm.(type) {
case *Label : break
case MemoryAddress : b, x = toHcodeOpt(v.Base), toHcodeOpt(v.Index)
case RelativeOffset : break
default : panic("rm is expected to be a register or a memory address")
}
/* encode the 3-byte VEX or XOP prefix */
self.emit(esc)
self.emit(0xe0 ^ (r << 7) ^ (x << 6) ^ (b << 5) ^ mmmmm)
self.emit(0x78 ^ (vvvv << 3) ^ wlpp)
}
// evex encodes a 4-byte EVEX prefix.
func (self *_Encoding) evex(mm byte, w1pp byte, ll byte, rr byte, rm interface{}, vvvvv byte, aaa byte, zz byte, bb byte) {
var b byte
var x byte
/* EVEX.b must be a single-bit mask */
if bb > 1 {
panic("EVEX.b must be a 1-bit mask")
}
/* EVEX.z must be a single-bit mask */
if zz > 1 {
panic("EVEX.z must be a 1-bit mask")
}
/* EVEX.mm must be a 2-bit mask */
if mm &^ 0b11 != 0 {
panic("EVEX.mm must be a 2-bit mask")
}
/* EVEX.L'L must be a 2-bit mask */
if ll &^ 0b11 != 0 {
panic("EVEX.L'L must be a 2-bit mask")
}
/* EVEX.R'R must be a 2-bit mask */
if rr &^ 0b11 != 0 {
panic("EVEX.R'R must be a 2-bit mask")
}
/* EVEX.aaa must be a 3-bit mask */
if aaa &^ 0b111 != 0 {
panic("EVEX.aaa must be a 3-bit mask")
}
/* EVEX.v'vvvv must be a 5-bit mask */
if vvvvv &^ 0b11111 != 0 {
panic("EVEX.v'vvvv must be a 5-bit mask")
}
/* EVEX.W____1pp is expected to have no bits set except 0, 1, 2, and 7 */
if w1pp &^ 0b10000011 != 0b100 {
panic("EVEX.W____1pp is expected to have no bits set except 0, 1, 2, and 7")
}
/* extract bits from EVEX.R'R and EVEX.v'vvvv */
r1, r0 := rr >> 1, rr & 1
v1, v0 := vvvvv >> 4, vvvvv & 0b1111
/* encode the RM bits if any */
if rm != nil {
switch m := rm.(type) {
case *Label : break
case Register : b, x = hcode(m), ecode(m)
case MemoryAddress : b, x, v1 = toHcodeOpt(m.Base), toHcodeOpt(m.Index), toEcodeVMM(m.Index, v1)
case RelativeOffset : break
default : panic("rm is expected to be a register or a memory address")
}
}
/* EVEX prefix bytes */
p0 := (r0 << 7) | (x << 6) | (b << 5) | (r1 << 4) | mm
p1 := (v0 << 3) | w1pp
p2 := (zz << 7) | (ll << 5) | (b << 4) | (v1 << 3) | aaa
/* p0: invert RXBR' (bits 4-7)
* p1: invert vvvv (bits 3-6)
* p2: invert V' (bit 3) */
self.emit(0x62)
self.emit(p0 ^ 0xf0)
self.emit(p1 ^ 0x78)
self.emit(p2 ^ 0x08)
}
// rexm encodes a mandatory REX prefix.
func (self *_Encoding) rexm(w byte, r byte, rm interface{}) {
var b byte
var x byte
/* REX.R must be 0 or 1 */
if r != 0 && r != 1 {
panic("REX.R must be 0 or 1")
}
/* REX.W must be 0 or 1 */
if w != 0 && w != 1 {
panic("REX.W must be 0 or 1")
}
/* encode the RM bits */
switch v := rm.(type) {
case *Label : break
case MemoryAddress : b, x = toHcodeOpt(v.Base), toHcodeOpt(v.Index)
case RelativeOffset : break
default : panic("rm is expected to be a register or a memory address")
}
/* encode the REX prefix */
self.emit(0x40 | (w << 3) | (r << 2) | (x << 1) | b)
}
// rexo encodes an optional REX prefix.
func (self *_Encoding) rexo(r byte, rm interface{}, force bool) {
var b byte
var x byte
/* REX.R must be 0 or 1 */
if r != 0 && r != 1 {
panic("REX.R must be 0 or 1")
}
/* encode the RM bits */
switch v := rm.(type) {
case *Label : break
case Register : b = hcode(v)
case MemoryAddress : b, x = toHcodeOpt(v.Base), toHcodeOpt(v.Index)
case RelativeOffset : break
default : panic("rm is expected to be a register or a memory address")
}
/* if REX.R, REX.X, and REX.B are all zeroes, REX prefix can be omitted */
if force || r != 0 || x != 0 || b != 0 {
self.emit(0x40 | (r << 2) | (x << 1) | b)
}
}
// mrsd encodes ModR/M, SIB and Displacement.
//
// ModR/M byte
// +----------------+---------------+---------------+
// | Bits 6-7: Mode | Bits 3-5: Reg | Bits 0-2: R/M |
// +----------------+---------------+---------------+
//
// SIB byte
// +-----------------+-----------------+----------------+
// | Bits 6-7: Scale | Bits 3-5: Index | Bits 0-2: Base |
// +-----------------+-----------------+----------------+
//
func (self *_Encoding) mrsd(reg byte, rm interface{}, disp8v int32) {
var ok bool
var mm MemoryAddress
var ro RelativeOffset
/* ModRM encodes the lower 3-bit of the register */
if reg > 7 {
panic("invalid register bits")
}
/* check the displacement scale */
switch disp8v {
case 1: break
case 2: break
case 4: break
case 8: break
case 16: break
case 32: break
case 64: break
default: panic("invalid displacement size")
}
/* special case: unresolved labels, assuming a zero offset */
if _, ok = rm.(*Label); ok {
self.emit(0x05 | (reg << 3))
self.imm4(0)
return
}
/* special case: RIP-relative offset
* ModRM.Mode == 0 and ModeRM.R/M == 5 indicates (rip + disp32) addressing */
if ro, ok = rm.(RelativeOffset); ok {
self.emit(0x05 | (reg << 3))
self.imm4(int64(ro))
return
}
/* must be a generic memory address */
if mm, ok = rm.(MemoryAddress); !ok {
panic("rm must be a memory address")
}
/* absolute addressing, encoded as disp(%rbp,%rsp,1) */
if mm.Base == nil && mm.Index == nil {
self.emit(0x04 | (reg << 3))
self.emit(0x25)
self.imm4(int64(mm.Displacement))
return
}
/* no SIB byte */
if mm.Index == nil && lcode(mm.Base) != 0b100 {
cc := lcode(mm.Base)
dv := mm.Displacement
/* ModRM.Mode == 0 (no displacement) */
if dv == 0 && mm.Base != RBP && mm.Base != R13 {
if cc == 0b101 {
panic("rbp/r13 is not encodable as a base register (interpreted as disp32 address)")
} else {
self.emit((reg << 3) | cc)
return
}
}
/* ModRM.Mode == 1 (8-bit displacement) */
if dq := dv / disp8v; dq >= math.MinInt8 && dq <= math.MaxInt8 && dv % disp8v == 0 {
self.emit(0x40 | (reg << 3) | cc)
self.imm1(int64(dq))
return
}
/* ModRM.Mode == 2 (32-bit displacement) */
self.emit(0x80 | (reg << 3) | cc)
self.imm4(int64(mm.Displacement))
return
}
/* all encodings below use ModRM.R/M = 4 (0b100) to indicate the presence of SIB */
if mm.Index == RSP {
panic("rsp is not encodable as an index register (interpreted as no index)")
}
/* index = 4 (0b100) denotes no-index encoding */
var scale byte
var index byte = 0x04
/* encode the scale byte */
if mm.Scale != 0 {
switch mm.Scale {
case 1 : scale = 0
case 2 : scale = 1
case 4 : scale = 2
case 8 : scale = 3
default : panic("invalid scale value")
}
}
/* encode the index byte */
if mm.Index != nil {
index = lcode(mm.Index)
}
/* SIB.Base = 5 (0b101) and ModRM.Mode = 0 indicates no-base encoding with disp32 */
if mm.Base == nil {
self.emit((reg << 3) | 0b100)
self.emit((scale << 6) | (index << 3) | 0b101)
self.imm4(int64(mm.Displacement))
return
}
/* base L-code & displacement value */
cc := lcode(mm.Base)
dv := mm.Displacement
/* ModRM.Mode == 0 (no displacement) */
if dv == 0 && cc != 0b101 {
self.emit((reg << 3) | 0b100)
self.emit((scale << 6) | (index << 3) | cc)
return
}
/* ModRM.Mode == 1 (8-bit displacement) */
if dq := dv / disp8v; dq >= math.MinInt8 && dq <= math.MaxInt8 && dv % disp8v == 0 {
self.emit(0x44 | (reg << 3))
self.emit((scale << 6) | (index << 3) | cc)
self.imm1(int64(dq))
return
}
/* ModRM.Mode == 2 (32-bit displacement) */
self.emit(0x84 | (reg << 3))
self.emit((scale << 6) | (index << 3) | cc)
self.imm4(int64(mm.Displacement))
}
// encode invokes the encoder to encode this instruction.
func (self *_Encoding) encode(v []interface{}) int {
self.len = 0
self.encoder(self, v)
return self.len
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,510 @@
package x86_64
import (
`errors`
`fmt`
`math`
`reflect`
`strconv`
`strings`
`sync/atomic`
)
// RelativeOffset represents an RIP-relative offset.
type RelativeOffset int32
// String implements the fmt.Stringer interface.
func (self RelativeOffset) String() string {
if self == 0 {
return "(%rip)"
} else {
return fmt.Sprintf("%d(%%rip)", self)
}
}
// RoundingControl represents a floating-point rounding option.
type RoundingControl uint8
const (
// RN_SAE represents "Round Nearest", which is the default rounding option.
RN_SAE RoundingControl = iota
// RD_SAE represents "Round Down".
RD_SAE
// RU_SAE represents "Round Up".
RU_SAE
// RZ_SAE represents "Round towards Zero".
RZ_SAE
)
var _RC_NAMES = map[RoundingControl]string {
RN_SAE: "rn-sae",
RD_SAE: "rd-sae",
RU_SAE: "ru-sae",
RZ_SAE: "rz-sae",
}
func (self RoundingControl) String() string {
if v, ok := _RC_NAMES[self]; ok {
return v
} else {
panic("invalid RoundingControl value")
}
}
// ExceptionControl represents the "Suppress All Exceptions" flag.
type ExceptionControl uint8
const (
// SAE represents the flag "Suppress All Exceptions" for floating point operations.
SAE ExceptionControl = iota
)
func (ExceptionControl) String() string {
return "sae"
}
// AddressType indicates which kind of value that an Addressable object contains.
type AddressType uint
const (
// None indicates the Addressable does not contain any addressable value.
None AddressType = iota
// Memory indicates the Addressable contains a memory address.
Memory
// Offset indicates the Addressable contains an RIP-relative offset.
Offset
// Reference indicates the Addressable contains a label reference.
Reference
)
// Disposable is a type of object that can be Free'd manually.
type Disposable interface {
Free()
}
// Label represents a location within the program.
type Label struct {
refs int64
Name string
Dest *Instruction
}
func (self *Label) offset(p uintptr, n int) RelativeOffset {
if self.Dest == nil {
panic("unresolved label: " + self.Name)
} else {
return RelativeOffset(self.Dest.pc - p - uintptr(n))
}
}
// Free decreases the reference count of a Label, if the
// refcount drops to 0, the Label will be recycled.
func (self *Label) Free() {
if atomic.AddInt64(&self.refs, -1) == 0 {
freeLabel(self)
}
}
// String implements the fmt.Stringer interface.
func (self *Label) String() string {
if self.Dest == nil {
return fmt.Sprintf("%s(%%rip)", self.Name)
} else {
return fmt.Sprintf("%s(%%rip)@%#x", self.Name, self.Dest.pc)
}
}
// Retain increases the reference count of a Label.
func (self *Label) Retain() *Label {
atomic.AddInt64(&self.refs, 1)
return self
}
// Evaluate implements the interface expr.Term.
func (self *Label) Evaluate() (int64, error) {
if self.Dest != nil {
return int64(self.Dest.pc), nil
} else {
return 0, errors.New("unresolved label: " + self.Name)
}
}
// Addressable is a union to represent an addressable operand.
type Addressable struct {
Type AddressType
Memory MemoryAddress
Offset RelativeOffset
Reference *Label
}
// String implements the fmt.Stringer interface.
func (self *Addressable) String() string {
switch self.Type {
case None : return "(not addressable)"
case Memory : return self.Memory.String()
case Offset : return self.Offset.String()
case Reference : return self.Reference.String()
default : return "(invalid addressable)"
}
}
// MemoryOperand represents a memory operand for an instruction.
type MemoryOperand struct {
refs int64
Size int
Addr Addressable
Mask RegisterMask
Masked bool
Broadcast uint8
}
const (
_Sizes = 0b10000000100010111 // bit-mask for valid sizes (0, 1, 2, 4, 8, 16)
)
func (self *MemoryOperand) isVMX(evex bool) bool {
return self.Addr.Type == Memory && self.Addr.Memory.isVMX(evex)
}
func (self *MemoryOperand) isVMY(evex bool) bool {
return self.Addr.Type == Memory && self.Addr.Memory.isVMY(evex)
}
func (self *MemoryOperand) isVMZ() bool {
return self.Addr.Type == Memory && self.Addr.Memory.isVMZ()
}
func (self *MemoryOperand) isMem() bool {
if (_Sizes & (1 << self.Broadcast)) == 0 {
return false
} else if self.Addr.Type == Memory {
return self.Addr.Memory.isMem()
} else if self.Addr.Type == Offset {
return true
} else if self.Addr.Type == Reference {
return true
} else {
return false
}
}
func (self *MemoryOperand) isSize(n int) bool {
return self.Size == 0 || self.Size == n
}
func (self *MemoryOperand) isBroadcast(n int, b uint8) bool {
return self.Size == n && self.Broadcast == b
}
func (self *MemoryOperand) formatMask() string {
if !self.Masked {
return ""
} else {
return self.Mask.String()
}
}
func (self *MemoryOperand) formatBroadcast() string {
if self.Broadcast == 0 {
return ""
} else {
return fmt.Sprintf("{1to%d}", self.Broadcast)
}
}
func (self *MemoryOperand) ensureAddrValid() {
switch self.Addr.Type {
case None : break
case Memory : self.Addr.Memory.EnsureValid()
case Offset : break
case Reference : break
default : panic("invalid address type")
}
}
func (self *MemoryOperand) ensureSizeValid() {
if (_Sizes & (1 << self.Size)) == 0 {
panic("invalid memory operand size")
}
}
func (self *MemoryOperand) ensureBroadcastValid() {
if (_Sizes & (1 << self.Broadcast)) == 0 {
panic("invalid memory operand broadcast")
}
}
// Free decreases the reference count of a MemoryOperand, if the
// refcount drops to 0, the Label will be recycled.
func (self *MemoryOperand) Free() {
if atomic.AddInt64(&self.refs, -1) == 0 {
freeMemoryOperand(self)
}
}
// String implements the fmt.Stringer interface.
func (self *MemoryOperand) String() string {
return self.Addr.String() + self.formatMask() + self.formatBroadcast()
}
// Retain increases the reference count of a MemoryOperand.
func (self *MemoryOperand) Retain() *MemoryOperand {
atomic.AddInt64(&self.refs, 1)
return self
}
// EnsureValid checks if the memory operand is valid, if not, it panics.
func (self *MemoryOperand) EnsureValid() {
self.ensureAddrValid()
self.ensureSizeValid()
self.ensureBroadcastValid()
}
// MemoryAddress represents a memory address.
type MemoryAddress struct {
Base Register
Index Register
Scale uint8
Displacement int32
}
const (
_Scales = 0b100010111 // bit-mask for valid scales (0, 1, 2, 4, 8)
)
func (self *MemoryAddress) isVMX(evex bool) bool {
return self.isMemBase() && (self.Index == nil || isXMM(self.Index) || (evex && isEVEXXMM(self.Index)))
}
func (self *MemoryAddress) isVMY(evex bool) bool {
return self.isMemBase() && (self.Index == nil || isYMM(self.Index) || (evex && isEVEXYMM(self.Index)))
}
func (self *MemoryAddress) isVMZ() bool {
return self.isMemBase() && (self.Index == nil || isZMM(self.Index))
}
func (self *MemoryAddress) isMem() bool {
return self.isMemBase() && (self.Index == nil || isReg64(self.Index))
}
func (self *MemoryAddress) isMemBase() bool {
return (self.Base == nil || isReg64(self.Base)) && // `Base` must be 64-bit if present
(self.Scale == 0) == (self.Index == nil) && // `Scale` and `Index` depends on each other
(_Scales & (1 << self.Scale)) != 0 // `Scale` can only be 0, 1, 2, 4 or 8
}
// String implements the fmt.Stringer interface.
func (self *MemoryAddress) String() string {
var dp int
var sb strings.Builder
/* the displacement part */
if dp = int(self.Displacement); dp != 0 {
sb.WriteString(strconv.Itoa(dp))
}
/* the base register */
if sb.WriteByte('('); self.Base != nil {
sb.WriteByte('%')
sb.WriteString(self.Base.String())
}
/* index is optional */
if self.Index != nil {
sb.WriteString(",%")
sb.WriteString(self.Index.String())
/* scale is also optional */
if self.Scale >= 2 {
sb.WriteByte(',')
sb.WriteString(strconv.Itoa(int(self.Scale)))
}
}
/* close the bracket */
sb.WriteByte(')')
return sb.String()
}
// EnsureValid checks if the memory address is valid, if not, it panics.
func (self *MemoryAddress) EnsureValid() {
if !self.isMemBase() || (self.Index != nil && !isIndexable(self.Index)) {
panic("not a valid memory address")
}
}
// Ref constructs a memory reference to a label.
func Ref(ref *Label) (v *MemoryOperand) {
v = CreateMemoryOperand()
v.Addr.Type = Reference
v.Addr.Reference = ref
return
}
// Abs construct a simple memory address that represents absolute addressing.
func Abs(disp int32) *MemoryOperand {
return Sib(nil, nil, 0, disp)
}
// Ptr constructs a simple memory operand with base and displacement.
func Ptr(base Register, disp int32) *MemoryOperand {
return Sib(base, nil, 0, disp)
}
// Sib constructs a simple memory operand that represents a complete memory address.
func Sib(base Register, index Register, scale uint8, disp int32) (v *MemoryOperand) {
v = CreateMemoryOperand()
v.Addr.Type = Memory
v.Addr.Memory.Base = base
v.Addr.Memory.Index = index
v.Addr.Memory.Scale = scale
v.Addr.Memory.Displacement = disp
v.EnsureValid()
return
}
/** Operand Matching Helpers **/
const _IntMask =
(1 << reflect.Int ) |
(1 << reflect.Int8 ) |
(1 << reflect.Int16 ) |
(1 << reflect.Int32 ) |
(1 << reflect.Int64 ) |
(1 << reflect.Uint ) |
(1 << reflect.Uint8 ) |
(1 << reflect.Uint16 ) |
(1 << reflect.Uint32 ) |
(1 << reflect.Uint64 ) |
(1 << reflect.Uintptr)
func isInt(k reflect.Kind) bool {
return (_IntMask & (1 << k)) != 0
}
func asInt64(v interface{}) (int64, bool) {
if isSpecial(v) {
return 0, false
} else if x := efaceOf(v); isInt(x.kind()) {
return x.toInt64(), true
} else {
return 0, false
}
}
func inRange(v interface{}, low int64, high int64) bool {
x, ok := asInt64(v)
return ok && x >= low && x <= high
}
func isSpecial(v interface{}) bool {
switch v.(type) {
case Register8 : return true
case Register16 : return true
case Register32 : return true
case Register64 : return true
case KRegister : return true
case MMRegister : return true
case XMMRegister : return true
case YMMRegister : return true
case ZMMRegister : return true
case RelativeOffset : return true
case RoundingControl : return true
case ExceptionControl : return true
default : return false
}
}
func isIndexable(v interface{}) bool {
return isZMM(v) || isReg64(v) || isEVEXXMM(v) || isEVEXYMM(v)
}
func isImm4 (v interface{}) bool { return inRange(v, 0, 15) }
func isImm8 (v interface{}) bool { return inRange(v, math.MinInt8, math.MaxUint8) }
func isImm16 (v interface{}) bool { return inRange(v, math.MinInt16, math.MaxUint16) }
func isImm32 (v interface{}) bool { return inRange(v, math.MinInt32, math.MaxUint32) }
func isImm64 (v interface{}) bool { _, r := asInt64(v) ; return r }
func isConst1 (v interface{}) bool { x, r := asInt64(v) ; return r && x == 1 }
func isConst3 (v interface{}) bool { x, r := asInt64(v) ; return r && x == 3 }
func isRel8 (v interface{}) bool { x, r := v.(RelativeOffset) ; return r && x >= math.MinInt8 && x <= math.MaxInt8 }
func isRel32 (v interface{}) bool { _, r := v.(RelativeOffset) ; return r }
func isLabel (v interface{}) bool { _, r := v.(*Label) ; return r }
func isReg8 (v interface{}) bool { _, r := v.(Register8) ; return r }
func isReg8REX (v interface{}) bool { x, r := v.(Register8) ; return r && (x & 0x80) == 0 && x >= SPL }
func isReg16 (v interface{}) bool { _, r := v.(Register16) ; return r }
func isReg32 (v interface{}) bool { _, r := v.(Register32) ; return r }
func isReg64 (v interface{}) bool { _, r := v.(Register64) ; return r }
func isMM (v interface{}) bool { _, r := v.(MMRegister) ; return r }
func isXMM (v interface{}) bool { x, r := v.(XMMRegister) ; return r && x <= XMM15 }
func isEVEXXMM (v interface{}) bool { _, r := v.(XMMRegister) ; return r }
func isXMMk (v interface{}) bool { x, r := v.(MaskedRegister) ; return isXMM(v) || (r && isXMM(x.Reg) && !x.Mask.Z) }
func isXMMkz (v interface{}) bool { x, r := v.(MaskedRegister) ; return isXMM(v) || (r && isXMM(x.Reg)) }
func isYMM (v interface{}) bool { x, r := v.(YMMRegister) ; return r && x <= YMM15 }
func isEVEXYMM (v interface{}) bool { _, r := v.(YMMRegister) ; return r }
func isYMMk (v interface{}) bool { x, r := v.(MaskedRegister) ; return isYMM(v) || (r && isYMM(x.Reg) && !x.Mask.Z) }
func isYMMkz (v interface{}) bool { x, r := v.(MaskedRegister) ; return isYMM(v) || (r && isYMM(x.Reg)) }
func isZMM (v interface{}) bool { _, r := v.(ZMMRegister) ; return r }
func isZMMk (v interface{}) bool { x, r := v.(MaskedRegister) ; return isZMM(v) || (r && isZMM(x.Reg) && !x.Mask.Z) }
func isZMMkz (v interface{}) bool { x, r := v.(MaskedRegister) ; return isZMM(v) || (r && isZMM(x.Reg)) }
func isK (v interface{}) bool { _, r := v.(KRegister) ; return r }
func isKk (v interface{}) bool { x, r := v.(MaskedRegister) ; return isK(v) || (r && isK(x.Reg) && !x.Mask.Z) }
func isM (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isMem() && x.Broadcast == 0 && !x.Masked }
func isMk (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isMem() && x.Broadcast == 0 && !(x.Masked && x.Mask.Z) }
func isMkz (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isMem() && x.Broadcast == 0 }
func isM8 (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isM(v) && x.isSize(1) }
func isM16 (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isM(v) && x.isSize(2) }
func isM16kz (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isMkz(v) && x.isSize(2) }
func isM32 (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isM(v) && x.isSize(4) }
func isM32k (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isMk(v) && x.isSize(4) }
func isM32kz (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isMkz(v) && x.isSize(4) }
func isM64 (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isM(v) && x.isSize(8) }
func isM64k (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isMk(v) && x.isSize(8) }
func isM64kz (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isMkz(v) && x.isSize(8) }
func isM128 (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isM(v) && x.isSize(16) }
func isM128kz (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isMkz(v) && x.isSize(16) }
func isM256 (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isM(v) && x.isSize(32) }
func isM256kz (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isMkz(v) && x.isSize(32) }
func isM512 (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isM(v) && x.isSize(64) }
func isM512kz (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isMkz(v) && x.isSize(64) }
func isM64M32bcst (v interface{}) bool { x, r := v.(*MemoryOperand) ; return isM64(v) || (r && x.isBroadcast(4, 2)) }
func isM128M32bcst (v interface{}) bool { x, r := v.(*MemoryOperand) ; return isM128(v) || (r && x.isBroadcast(4, 4)) }
func isM256M32bcst (v interface{}) bool { x, r := v.(*MemoryOperand) ; return isM256(v) || (r && x.isBroadcast(4, 8)) }
func isM512M32bcst (v interface{}) bool { x, r := v.(*MemoryOperand) ; return isM512(v) || (r && x.isBroadcast(4, 16)) }
func isM128M64bcst (v interface{}) bool { x, r := v.(*MemoryOperand) ; return isM128(v) || (r && x.isBroadcast(8, 2)) }
func isM256M64bcst (v interface{}) bool { x, r := v.(*MemoryOperand) ; return isM256(v) || (r && x.isBroadcast(8, 4)) }
func isM512M64bcst (v interface{}) bool { x, r := v.(*MemoryOperand) ; return isM512(v) || (r && x.isBroadcast(8, 8)) }
func isVMX (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isVMX(false) && !x.Masked }
func isEVEXVMX (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isVMX(true) && !x.Masked }
func isVMXk (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isVMX(true) }
func isVMY (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isVMY(false) && !x.Masked }
func isEVEXVMY (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isVMY(true) && !x.Masked }
func isVMYk (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isVMY(true) }
func isVMZ (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isVMZ() && !x.Masked }
func isVMZk (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isVMZ() }
func isSAE (v interface{}) bool { _, r := v.(ExceptionControl) ; return r }
func isER (v interface{}) bool { _, r := v.(RoundingControl) ; return r }
func isImmExt(v interface{}, ext int, min int64, max int64) bool {
if x, ok := asInt64(v); !ok {
return false
} else if m := int64(1) << (8 * ext); x < m && x >= m + min {
return true
} else {
return x <= max && x >= min
}
}
func isImm8Ext(v interface{}, ext int) bool {
return isImmExt(v, ext, math.MinInt8, math.MaxInt8)
}
func isImm32Ext(v interface{}, ext int) bool {
return isImmExt(v, ext, math.MinInt32, math.MaxInt32)
}

@ -0,0 +1,117 @@
package x86_64
import (
`sync`
)
var (
labelPool sync.Pool
programPool sync.Pool
instructionPool sync.Pool
memoryOperandPool sync.Pool
)
func freeLabel(v *Label) {
labelPool.Put(v)
}
func clearLabel(p *Label) *Label {
*p = Label{}
return p
}
// CreateLabel creates a new Label, it may allocate a new one or grab one from a pool.
func CreateLabel(name string) *Label {
var p *Label
var v interface{}
/* attempt to grab from the pool */
if v = labelPool.Get(); v == nil {
p = new(Label)
} else {
p = clearLabel(v.(*Label))
}
/* initialize the label */
p.refs = 1
p.Name = name
return p
}
func newProgram(arch *Arch) *Program {
var p *Program
var v interface{}
/* attempt to grab from the pool */
if v = programPool.Get(); v == nil {
p = new(Program)
} else {
p = clearProgram(v.(*Program))
}
/* initialize the program */
p.arch = arch
return p
}
func freeProgram(p *Program) {
programPool.Put(p)
}
func clearProgram(p *Program) *Program {
*p = Program{}
return p
}
func newInstruction(name string, argc int, argv Operands) *Instruction {
var v interface{}
var p *Instruction
/* attempt to grab from the pool */
if v = instructionPool.Get(); v == nil {
p = new(Instruction)
} else {
p = clearInstruction(v.(*Instruction))
}
/* initialize the instruction */
p.name = name
p.argc = argc
p.argv = argv
return p
}
func freeInstruction(v *Instruction) {
instructionPool.Put(v)
}
func clearInstruction(p *Instruction) *Instruction {
*p = Instruction { prefix: p.prefix[:0] }
return p
}
func freeMemoryOperand(m *MemoryOperand) {
memoryOperandPool.Put(m)
}
func clearMemoryOperand(m *MemoryOperand) *MemoryOperand {
*m = MemoryOperand{}
return m
}
// CreateMemoryOperand creates a new MemoryOperand, it may allocate a new one or grab one from a pool.
func CreateMemoryOperand() *MemoryOperand {
var v interface{}
var p *MemoryOperand
/* attempt to grab from the pool */
if v = memoryOperandPool.Get(); v == nil {
p = new(MemoryOperand)
} else {
p = clearMemoryOperand(v.(*MemoryOperand))
}
/* initialize the memory operand */
p.refs = 1
return p
}

@ -0,0 +1,542 @@
package x86_64
import (
`fmt`
`math`
`math/bits`
`github.com/chenzhuoyu/iasm/expr`
)
type (
_PseudoType int
_InstructionEncoder func(*Program, ...interface{}) *Instruction
)
const (
_PseudoNop _PseudoType = iota + 1
_PseudoByte
_PseudoWord
_PseudoLong
_PseudoQuad
_PseudoData
_PseudoAlign
)
func (self _PseudoType) String() string {
switch self {
case _PseudoNop : return ".nop"
case _PseudoByte : return ".byte"
case _PseudoWord : return ".word"
case _PseudoLong : return ".long"
case _PseudoQuad : return ".quad"
case _PseudoData : return ".data"
case _PseudoAlign : return ".align"
default : panic("unreachable")
}
}
type _Pseudo struct {
kind _PseudoType
data []byte
uint uint64
expr *expr.Expr
}
func (self *_Pseudo) free() {
if self.expr != nil {
self.expr.Free()
}
}
func (self *_Pseudo) encode(m *[]byte, pc uintptr) int {
switch self.kind {
case _PseudoNop : return 0
case _PseudoByte : self.encodeByte(m) ; return 1
case _PseudoWord : self.encodeWord(m) ; return 2
case _PseudoLong : self.encodeLong(m) ; return 4
case _PseudoQuad : self.encodeQuad(m) ; return 8
case _PseudoData : self.encodeData(m) ; return len(self.data)
case _PseudoAlign : self.encodeAlign(m, pc) ; return self.alignSize(pc)
default : panic("invalid pseudo instruction")
}
}
func (self *_Pseudo) evalExpr(low int64, high int64) int64 {
if v, err := self.expr.Evaluate(); err != nil {
panic(err)
} else if v < low || v > high {
panic(fmt.Sprintf("expression out of range [%d, %d]: %d", low, high, v))
} else {
return v
}
}
func (self *_Pseudo) alignSize(pc uintptr) int {
if !ispow2(self.uint) {
panic(fmt.Sprintf("aligment should be a power of 2, not %d", self.uint))
} else {
return align(int(pc), bits.TrailingZeros64(self.uint)) - int(pc)
}
}
func (self *_Pseudo) encodeData(m *[]byte) {
if m != nil {
*m = append(*m, self.data...)
}
}
func (self *_Pseudo) encodeByte(m *[]byte) {
if m != nil {
append8(m, byte(self.evalExpr(math.MinInt8, math.MaxUint8)))
}
}
func (self *_Pseudo) encodeWord(m *[]byte) {
if m != nil {
append16(m, uint16(self.evalExpr(math.MinInt16, math.MaxUint16)))
}
}
func (self *_Pseudo) encodeLong(m *[]byte) {
if m != nil {
append32(m, uint32(self.evalExpr(math.MinInt32, math.MaxUint32)))
}
}
func (self *_Pseudo) encodeQuad(m *[]byte) {
if m != nil {
if v, err := self.expr.Evaluate(); err != nil {
panic(err)
} else {
append64(m, uint64(v))
}
}
}
func (self *_Pseudo) encodeAlign(m *[]byte, pc uintptr) {
if m != nil {
if self.expr == nil {
expandmm(m, self.alignSize(pc), 0)
} else {
expandmm(m, self.alignSize(pc), byte(self.evalExpr(math.MinInt8, math.MaxUint8)))
}
}
}
// Operands represents a sequence of operand required by an instruction.
type Operands [_N_args]interface{}
// InstructionDomain represents the domain of an instruction.
type InstructionDomain uint8
const (
DomainGeneric InstructionDomain = iota
DomainMMXSSE
DomainAVX
DomainFMA
DomainCrypto
DomainMask
DomainAMDSpecific
DomainMisc
DomainPseudo
)
type (
_BranchType uint8
)
const (
_B_none _BranchType = iota
_B_conditional
_B_unconditional
)
// Instruction represents an unencoded instruction.
type Instruction struct {
next *Instruction
pc uintptr
nb int
len int
argc int
name string
argv Operands
forms [_N_forms]_Encoding
pseudo _Pseudo
branch _BranchType
domain InstructionDomain
prefix []byte
}
func (self *Instruction) add(flags int, encoder func(m *_Encoding, v []interface{})) {
self.forms[self.len].flags = flags
self.forms[self.len].encoder = encoder
self.len++
}
func (self *Instruction) free() {
self.clear()
self.pseudo.free()
freeInstruction(self)
}
func (self *Instruction) clear() {
for i := 0; i < self.argc; i++ {
if v, ok := self.argv[i].(Disposable); ok {
v.Free()
}
}
}
func (self *Instruction) check(e *_Encoding) bool {
if (e.flags & _F_rel1) != 0 {
return isRel8(self.argv[0])
} else if (e.flags & _F_rel4) != 0 {
return isRel32(self.argv[0]) || isLabel(self.argv[0])
} else {
return true
}
}
func (self *Instruction) encode(m *[]byte) int {
n := math.MaxInt64
p := (*_Encoding)(nil)
/* encode prefixes if any */
if self.nb = len(self.prefix); m != nil {
*m = append(*m, self.prefix...)
}
/* check for pseudo-instructions */
if self.pseudo.kind != 0 {
self.nb += self.pseudo.encode(m, self.pc)
return self.nb
}
/* find the shortest encoding */
for i := 0; i < self.len; i++ {
if e := &self.forms[i]; self.check(e) {
if v := e.encode(self.argv[:self.argc]); v < n {
n = v
p = e
}
}
}
/* add to buffer if needed */
if m != nil {
*m = append(*m, p.bytes[:n]...)
}
/* update the instruction length */
self.nb += n
return self.nb
}
/** Instruction Prefixes **/
const (
_P_cs = 0x2e
_P_ds = 0x3e
_P_es = 0x26
_P_fs = 0x64
_P_gs = 0x65
_P_ss = 0x36
_P_lock = 0xf0
)
// CS overrides the memory operation of this instruction to CS.
func (self *Instruction) CS() *Instruction {
self.prefix = append(self.prefix, _P_cs)
return self
}
// DS overrides the memory operation of this instruction to DS,
// this is the default section for most instructions if not specified.
func (self *Instruction) DS() *Instruction {
self.prefix = append(self.prefix, _P_ds)
return self
}
// ES overrides the memory operation of this instruction to ES.
func (self *Instruction) ES() *Instruction {
self.prefix = append(self.prefix, _P_es)
return self
}
// FS overrides the memory operation of this instruction to FS.
func (self *Instruction) FS() *Instruction {
self.prefix = append(self.prefix, _P_fs)
return self
}
// GS overrides the memory operation of this instruction to GS.
func (self *Instruction) GS() *Instruction {
self.prefix = append(self.prefix, _P_gs)
return self
}
// SS overrides the memory operation of this instruction to SS.
func (self *Instruction) SS() *Instruction {
self.prefix = append(self.prefix, _P_ss)
return self
}
// LOCK causes the processor's LOCK# signal to be asserted during execution of
// the accompanying instruction (turns the instruction into an atomic instruction).
// In a multiprocessor environment, the LOCK# signal insures that the processor
// has exclusive use of any shared memory while the signal is asserted.
func (self *Instruction) LOCK() *Instruction {
self.prefix = append(self.prefix, _P_lock)
return self
}
/** Basic Instruction Properties **/
// Name returns the instruction name.
func (self *Instruction) Name() string {
return self.name
}
// Domain returns the domain of this instruction.
func (self *Instruction) Domain() InstructionDomain {
return self.domain
}
// Operands returns the operands of this instruction.
func (self *Instruction) Operands() []interface{} {
return self.argv[:self.argc]
}
// Program represents a sequence of instructions.
type Program struct {
arch *Arch
head *Instruction
tail *Instruction
}
const (
_N_near = 2 // near-branch (-128 ~ +127) takes 2 bytes to encode
_N_far_cond = 6 // conditional far-branch takes 6 bytes to encode
_N_far_uncond = 5 // unconditional far-branch takes 5 bytes to encode
)
func (self *Program) clear() {
for p, q := self.head, self.head; p != nil; p = q {
q = p.next
p.free()
}
}
func (self *Program) alloc(name string, argc int, argv Operands) *Instruction {
p := self.tail
q := newInstruction(name, argc, argv)
/* attach to tail if any */
if p != nil {
p.next = q
} else {
self.head = q
}
/* set the new tail */
self.tail = q
return q
}
func (self *Program) pseudo(kind _PseudoType) (p *Instruction) {
p = self.alloc(kind.String(), 0, Operands{})
p.domain = DomainPseudo
p.pseudo.kind = kind
return
}
func (self *Program) require(isa ISA) {
if !self.arch.HasISA(isa) {
panic("ISA '" + isa.String() + "' was not enabled")
}
}
func (self *Program) branchSize(p *Instruction) int {
switch p.branch {
case _B_none : panic("p is not a branch")
case _B_conditional : return _N_far_cond
case _B_unconditional : return _N_far_uncond
default : panic("invalid instruction")
}
}
/** Pseudo-Instructions **/
// Byte is a pseudo-instruction to add raw byte to the assembled code.
func (self *Program) Byte(v *expr.Expr) (p *Instruction) {
p = self.pseudo(_PseudoByte)
p.pseudo.expr = v
return
}
// Word is a pseudo-instruction to add raw uint16 as little-endian to the assembled code.
func (self *Program) Word(v *expr.Expr) (p *Instruction) {
p = self.pseudo(_PseudoWord)
p.pseudo.expr = v
return
}
// Long is a pseudo-instruction to add raw uint32 as little-endian to the assembled code.
func (self *Program) Long(v *expr.Expr) (p *Instruction) {
p = self.pseudo(_PseudoLong)
p.pseudo.expr = v
return
}
// Quad is a pseudo-instruction to add raw uint64 as little-endian to the assembled code.
func (self *Program) Quad(v *expr.Expr) (p *Instruction) {
p = self.pseudo(_PseudoQuad)
p.pseudo.expr = v
return
}
// Data is a pseudo-instruction to add raw bytes to the assembled code.
func (self *Program) Data(v []byte) (p *Instruction) {
p = self.pseudo(_PseudoData)
p.pseudo.data = v
return
}
// Align is a pseudo-instruction to ensure the PC is aligned to a certain value.
func (self *Program) Align(align uint64, padding *expr.Expr) (p *Instruction) {
p = self.pseudo(_PseudoAlign)
p.pseudo.uint = align
p.pseudo.expr = padding
return
}
/** Program Assembler **/
// Free returns the Program object into pool.
// Any operation performed after Free is undefined behavior.
//
// NOTE: This also frees all the instructions, labels, memory
// operands and expressions associated with this program.
//
func (self *Program) Free() {
self.clear()
freeProgram(self)
}
// Link pins a label at the current position.
func (self *Program) Link(p *Label) {
if p.Dest != nil {
panic("lable was alreay linked")
} else {
p.Dest = self.pseudo(_PseudoNop)
}
}
// Assemble assembles and links the entire program into machine code.
func (self *Program) Assemble(pc uintptr) (ret []byte) {
orig := pc
next := true
offs := uintptr(0)
/* Pass 0: PC-precompute, assume all labeled branches are far-branches. */
for p := self.head; p != nil; p = p.next {
if p.pc = pc; !isLabel(p.argv[0]) || p.branch == _B_none {
pc += uintptr(p.encode(nil))
} else {
pc += uintptr(self.branchSize(p))
}
}
/* allocate space for the machine code */
nb := int(pc - orig)
ret = make([]byte, 0, nb)
/* Pass 1: adjust all the jumps */
for next {
next = false
offs = uintptr(0)
/* scan all the branches */
for p := self.head; p != nil; p = p.next {
var ok bool
var lb *Label
/* re-calculate the alignment here */
if nb = p.nb; p.pseudo.kind == _PseudoAlign {
p.pc -= offs
offs += uintptr(nb - p.encode(nil))
continue
}
/* adjust the program counter */
p.pc -= offs
lb, ok = p.argv[0].(*Label)
/* only care about labeled far-branches */
if !ok || p.nb == _N_near || p.branch == _B_none {
continue
}
/* calculate the jump offset */
size := self.branchSize(p)
diff := lb.offset(p.pc, size)
/* too far to be a near jump */
if diff > 127 || diff < -128 {
p.nb = size
continue
}
/* a far jump becomes a near jump, calculate
* the PC adjustment value and assemble again */
next = true
p.nb = _N_near
offs += uintptr(size - _N_near)
}
}
/* Pass 3: link all the cross-references */
for p := self.head; p != nil; p = p.next {
for i := 0; i < p.argc; i++ {
var ok bool
var lb *Label
var op *MemoryOperand
/* resolve labels */
if lb, ok = p.argv[i].(*Label); ok {
p.argv[i] = lb.offset(p.pc, p.nb)
continue
}
/* check for memory operands */
if op, ok = p.argv[i].(*MemoryOperand); !ok {
continue
}
/* check for label references */
if op.Addr.Type != Reference {
continue
}
/* replace the label with the real offset */
op.Addr.Type = Offset
op.Addr.Offset = op.Addr.Reference.offset(p.pc, p.nb)
}
}
/* Pass 4: actually encode all the instructions */
for p := self.head; p != nil; p = p.next {
p.encode(&ret)
}
/* all done */
return ret
}
// AssembleAndFree is like Assemble, but it frees the Program after assembling.
func (self *Program) AssembleAndFree(pc uintptr) (ret []byte) {
ret = self.Assemble(pc)
self.Free()
return
}

@ -0,0 +1,677 @@
package x86_64
import (
`fmt`
)
// Register represents a hardware register.
type Register interface {
fmt.Stringer
implRegister()
}
type (
Register8 byte
Register16 byte
Register32 byte
Register64 byte
)
type (
KRegister byte
MMRegister byte
XMMRegister byte
YMMRegister byte
ZMMRegister byte
)
// RegisterMask is a KRegister used to mask another register.
type RegisterMask struct {
Z bool
K KRegister
}
// String implements the fmt.Stringer interface.
func (self RegisterMask) String() string {
if !self.Z {
return fmt.Sprintf("{%%%s}", self.K)
} else {
return fmt.Sprintf("{%%%s}{z}", self.K)
}
}
// MaskedRegister is a Register masked by a RegisterMask.
type MaskedRegister struct {
Reg Register
Mask RegisterMask
}
// String implements the fmt.Stringer interface.
func (self MaskedRegister) String() string {
return self.Reg.String() + self.Mask.String()
}
const (
AL Register8 = iota
CL
DL
BL
SPL
BPL
SIL
DIL
R8b
R9b
R10b
R11b
R12b
R13b
R14b
R15b
)
const (
AH = SPL | 0x80
CH = BPL | 0x80
DH = SIL | 0x80
BH = DIL | 0x80
)
const (
AX Register16 = iota
CX
DX
BX
SP
BP
SI
DI
R8w
R9w
R10w
R11w
R12w
R13w
R14w
R15w
)
const (
EAX Register32 = iota
ECX
EDX
EBX
ESP
EBP
ESI
EDI
R8d
R9d
R10d
R11d
R12d
R13d
R14d
R15d
)
const (
RAX Register64 = iota
RCX
RDX
RBX
RSP
RBP
RSI
RDI
R8
R9
R10
R11
R12
R13
R14
R15
)
const (
K0 KRegister = iota
K1
K2
K3
K4
K5
K6
K7
)
const (
MM0 MMRegister = iota
MM1
MM2
MM3
MM4
MM5
MM6
MM7
)
const (
XMM0 XMMRegister = iota
XMM1
XMM2
XMM3
XMM4
XMM5
XMM6
XMM7
XMM8
XMM9
XMM10
XMM11
XMM12
XMM13
XMM14
XMM15
XMM16
XMM17
XMM18
XMM19
XMM20
XMM21
XMM22
XMM23
XMM24
XMM25
XMM26
XMM27
XMM28
XMM29
XMM30
XMM31
)
const (
YMM0 YMMRegister = iota
YMM1
YMM2
YMM3
YMM4
YMM5
YMM6
YMM7
YMM8
YMM9
YMM10
YMM11
YMM12
YMM13
YMM14
YMM15
YMM16
YMM17
YMM18
YMM19
YMM20
YMM21
YMM22
YMM23
YMM24
YMM25
YMM26
YMM27
YMM28
YMM29
YMM30
YMM31
)
const (
ZMM0 ZMMRegister = iota
ZMM1
ZMM2
ZMM3
ZMM4
ZMM5
ZMM6
ZMM7
ZMM8
ZMM9
ZMM10
ZMM11
ZMM12
ZMM13
ZMM14
ZMM15
ZMM16
ZMM17
ZMM18
ZMM19
ZMM20
ZMM21
ZMM22
ZMM23
ZMM24
ZMM25
ZMM26
ZMM27
ZMM28
ZMM29
ZMM30
ZMM31
)
func (self Register8) implRegister() {}
func (self Register16) implRegister() {}
func (self Register32) implRegister() {}
func (self Register64) implRegister() {}
func (self KRegister) implRegister() {}
func (self MMRegister) implRegister() {}
func (self XMMRegister) implRegister() {}
func (self YMMRegister) implRegister() {}
func (self ZMMRegister) implRegister() {}
func (self Register8) String() string { if int(self) >= len(r8names) { return "???" } else { return r8names[self] } }
func (self Register16) String() string { if int(self) >= len(r16names) { return "???" } else { return r16names[self] } }
func (self Register32) String() string { if int(self) >= len(r32names) { return "???" } else { return r32names[self] } }
func (self Register64) String() string { if int(self) >= len(r64names) { return "???" } else { return r64names[self] } }
func (self KRegister) String() string { if int(self) >= len(knames) { return "???" } else { return knames[self] } }
func (self MMRegister) String() string { if int(self) >= len(mmnames) { return "???" } else { return mmnames[self] } }
func (self XMMRegister) String() string { if int(self) >= len(xmmnames) { return "???" } else { return xmmnames[self] } }
func (self YMMRegister) String() string { if int(self) >= len(ymmnames) { return "???" } else { return ymmnames[self] } }
func (self ZMMRegister) String() string { if int(self) >= len(zmmnames) { return "???" } else { return zmmnames[self] } }
// Registers maps register name into Register instances.
var Registers = map[string]Register {
"al" : AL,
"cl" : CL,
"dl" : DL,
"bl" : BL,
"spl" : SPL,
"bpl" : BPL,
"sil" : SIL,
"dil" : DIL,
"r8b" : R8b,
"r9b" : R9b,
"r10b" : R10b,
"r11b" : R11b,
"r12b" : R12b,
"r13b" : R13b,
"r14b" : R14b,
"r15b" : R15b,
"ah" : AH,
"ch" : CH,
"dh" : DH,
"bh" : BH,
"ax" : AX,
"cx" : CX,
"dx" : DX,
"bx" : BX,
"sp" : SP,
"bp" : BP,
"si" : SI,
"di" : DI,
"r8w" : R8w,
"r9w" : R9w,
"r10w" : R10w,
"r11w" : R11w,
"r12w" : R12w,
"r13w" : R13w,
"r14w" : R14w,
"r15w" : R15w,
"eax" : EAX,
"ecx" : ECX,
"edx" : EDX,
"ebx" : EBX,
"esp" : ESP,
"ebp" : EBP,
"esi" : ESI,
"edi" : EDI,
"r8d" : R8d,
"r9d" : R9d,
"r10d" : R10d,
"r11d" : R11d,
"r12d" : R12d,
"r13d" : R13d,
"r14d" : R14d,
"r15d" : R15d,
"rax" : RAX,
"rcx" : RCX,
"rdx" : RDX,
"rbx" : RBX,
"rsp" : RSP,
"rbp" : RBP,
"rsi" : RSI,
"rdi" : RDI,
"r8" : R8,
"r9" : R9,
"r10" : R10,
"r11" : R11,
"r12" : R12,
"r13" : R13,
"r14" : R14,
"r15" : R15,
"k0" : K0,
"k1" : K1,
"k2" : K2,
"k3" : K3,
"k4" : K4,
"k5" : K5,
"k6" : K6,
"k7" : K7,
"mm0" : MM0,
"mm1" : MM1,
"mm2" : MM2,
"mm3" : MM3,
"mm4" : MM4,
"mm5" : MM5,
"mm6" : MM6,
"mm7" : MM7,
"xmm0" : XMM0,
"xmm1" : XMM1,
"xmm2" : XMM2,
"xmm3" : XMM3,
"xmm4" : XMM4,
"xmm5" : XMM5,
"xmm6" : XMM6,
"xmm7" : XMM7,
"xmm8" : XMM8,
"xmm9" : XMM9,
"xmm10" : XMM10,
"xmm11" : XMM11,
"xmm12" : XMM12,
"xmm13" : XMM13,
"xmm14" : XMM14,
"xmm15" : XMM15,
"xmm16" : XMM16,
"xmm17" : XMM17,
"xmm18" : XMM18,
"xmm19" : XMM19,
"xmm20" : XMM20,
"xmm21" : XMM21,
"xmm22" : XMM22,
"xmm23" : XMM23,
"xmm24" : XMM24,
"xmm25" : XMM25,
"xmm26" : XMM26,
"xmm27" : XMM27,
"xmm28" : XMM28,
"xmm29" : XMM29,
"xmm30" : XMM30,
"xmm31" : XMM31,
"ymm0" : YMM0,
"ymm1" : YMM1,
"ymm2" : YMM2,
"ymm3" : YMM3,
"ymm4" : YMM4,
"ymm5" : YMM5,
"ymm6" : YMM6,
"ymm7" : YMM7,
"ymm8" : YMM8,
"ymm9" : YMM9,
"ymm10" : YMM10,
"ymm11" : YMM11,
"ymm12" : YMM12,
"ymm13" : YMM13,
"ymm14" : YMM14,
"ymm15" : YMM15,
"ymm16" : YMM16,
"ymm17" : YMM17,
"ymm18" : YMM18,
"ymm19" : YMM19,
"ymm20" : YMM20,
"ymm21" : YMM21,
"ymm22" : YMM22,
"ymm23" : YMM23,
"ymm24" : YMM24,
"ymm25" : YMM25,
"ymm26" : YMM26,
"ymm27" : YMM27,
"ymm28" : YMM28,
"ymm29" : YMM29,
"ymm30" : YMM30,
"ymm31" : YMM31,
"zmm0" : ZMM0,
"zmm1" : ZMM1,
"zmm2" : ZMM2,
"zmm3" : ZMM3,
"zmm4" : ZMM4,
"zmm5" : ZMM5,
"zmm6" : ZMM6,
"zmm7" : ZMM7,
"zmm8" : ZMM8,
"zmm9" : ZMM9,
"zmm10" : ZMM10,
"zmm11" : ZMM11,
"zmm12" : ZMM12,
"zmm13" : ZMM13,
"zmm14" : ZMM14,
"zmm15" : ZMM15,
"zmm16" : ZMM16,
"zmm17" : ZMM17,
"zmm18" : ZMM18,
"zmm19" : ZMM19,
"zmm20" : ZMM20,
"zmm21" : ZMM21,
"zmm22" : ZMM22,
"zmm23" : ZMM23,
"zmm24" : ZMM24,
"zmm25" : ZMM25,
"zmm26" : ZMM26,
"zmm27" : ZMM27,
"zmm28" : ZMM28,
"zmm29" : ZMM29,
"zmm30" : ZMM30,
"zmm31" : ZMM31,
}
/** Register Name Tables **/
var r8names = [...]string {
AL : "al",
CL : "cl",
DL : "dl",
BL : "bl",
SPL : "spl",
BPL : "bpl",
SIL : "sil",
DIL : "dil",
R8b : "r8b",
R9b : "r9b",
R10b : "r10b",
R11b : "r11b",
R12b : "r12b",
R13b : "r13b",
R14b : "r14b",
R15b : "r15b",
AH : "ah",
CH : "ch",
DH : "dh",
BH : "bh",
}
var r16names = [...]string {
AX : "ax",
CX : "cx",
DX : "dx",
BX : "bx",
SP : "sp",
BP : "bp",
SI : "si",
DI : "di",
R8w : "r8w",
R9w : "r9w",
R10w : "r10w",
R11w : "r11w",
R12w : "r12w",
R13w : "r13w",
R14w : "r14w",
R15w : "r15w",
}
var r32names = [...]string {
EAX : "eax",
ECX : "ecx",
EDX : "edx",
EBX : "ebx",
ESP : "esp",
EBP : "ebp",
ESI : "esi",
EDI : "edi",
R8d : "r8d",
R9d : "r9d",
R10d : "r10d",
R11d : "r11d",
R12d : "r12d",
R13d : "r13d",
R14d : "r14d",
R15d : "r15d",
}
var r64names = [...]string {
RAX : "rax",
RCX : "rcx",
RDX : "rdx",
RBX : "rbx",
RSP : "rsp",
RBP : "rbp",
RSI : "rsi",
RDI : "rdi",
R8 : "r8",
R9 : "r9",
R10 : "r10",
R11 : "r11",
R12 : "r12",
R13 : "r13",
R14 : "r14",
R15 : "r15",
}
var knames = [...]string {
K0: "k0",
K1: "k1",
K2: "k2",
K3: "k3",
K4: "k4",
K5: "k5",
K6: "k6",
K7: "k7",
}
var mmnames = [...]string {
MM0: "mm0",
MM1: "mm1",
MM2: "mm2",
MM3: "mm3",
MM4: "mm4",
MM5: "mm5",
MM6: "mm6",
MM7: "mm7",
}
var xmmnames = [...]string {
XMM0 : "xmm0",
XMM1 : "xmm1",
XMM2 : "xmm2",
XMM3 : "xmm3",
XMM4 : "xmm4",
XMM5 : "xmm5",
XMM6 : "xmm6",
XMM7 : "xmm7",
XMM8 : "xmm8",
XMM9 : "xmm9",
XMM10 : "xmm10",
XMM11 : "xmm11",
XMM12 : "xmm12",
XMM13 : "xmm13",
XMM14 : "xmm14",
XMM15 : "xmm15",
XMM16 : "xmm16",
XMM17 : "xmm17",
XMM18 : "xmm18",
XMM19 : "xmm19",
XMM20 : "xmm20",
XMM21 : "xmm21",
XMM22 : "xmm22",
XMM23 : "xmm23",
XMM24 : "xmm24",
XMM25 : "xmm25",
XMM26 : "xmm26",
XMM27 : "xmm27",
XMM28 : "xmm28",
XMM29 : "xmm29",
XMM30 : "xmm30",
XMM31 : "xmm31",
}
var ymmnames = [...]string {
YMM0 : "ymm0",
YMM1 : "ymm1",
YMM2 : "ymm2",
YMM3 : "ymm3",
YMM4 : "ymm4",
YMM5 : "ymm5",
YMM6 : "ymm6",
YMM7 : "ymm7",
YMM8 : "ymm8",
YMM9 : "ymm9",
YMM10 : "ymm10",
YMM11 : "ymm11",
YMM12 : "ymm12",
YMM13 : "ymm13",
YMM14 : "ymm14",
YMM15 : "ymm15",
YMM16 : "ymm16",
YMM17 : "ymm17",
YMM18 : "ymm18",
YMM19 : "ymm19",
YMM20 : "ymm20",
YMM21 : "ymm21",
YMM22 : "ymm22",
YMM23 : "ymm23",
YMM24 : "ymm24",
YMM25 : "ymm25",
YMM26 : "ymm26",
YMM27 : "ymm27",
YMM28 : "ymm28",
YMM29 : "ymm29",
YMM30 : "ymm30",
YMM31 : "ymm31",
}
var zmmnames = [...]string {
ZMM0 : "zmm0",
ZMM1 : "zmm1",
ZMM2 : "zmm2",
ZMM3 : "zmm3",
ZMM4 : "zmm4",
ZMM5 : "zmm5",
ZMM6 : "zmm6",
ZMM7 : "zmm7",
ZMM8 : "zmm8",
ZMM9 : "zmm9",
ZMM10 : "zmm10",
ZMM11 : "zmm11",
ZMM12 : "zmm12",
ZMM13 : "zmm13",
ZMM14 : "zmm14",
ZMM15 : "zmm15",
ZMM16 : "zmm16",
ZMM17 : "zmm17",
ZMM18 : "zmm18",
ZMM19 : "zmm19",
ZMM20 : "zmm20",
ZMM21 : "zmm21",
ZMM22 : "zmm22",
ZMM23 : "zmm23",
ZMM24 : "zmm24",
ZMM25 : "zmm25",
ZMM26 : "zmm26",
ZMM27 : "zmm27",
ZMM28 : "zmm28",
ZMM29 : "zmm29",
ZMM30 : "zmm30",
ZMM31 : "zmm31",
}

@ -0,0 +1,131 @@
package x86_64
import (
`encoding/binary`
`errors`
`reflect`
`strconv`
`unicode/utf8`
`unsafe`
)
const (
_CC_digit = 1 << iota
_CC_ident
_CC_ident0
_CC_number
)
func ispow2(v uint64) bool {
return (v & (v - 1)) == 0
}
func isdigit(cc rune) bool {
return '0' <= cc && cc <= '9'
}
func isalpha(cc rune) bool {
return (cc >= 'a' && cc <= 'z') || (cc >= 'A' && cc <= 'Z')
}
func isident(cc rune) bool {
return cc == '_' || isalpha(cc) || isdigit(cc)
}
func isident0(cc rune) bool {
return cc == '_' || isalpha(cc)
}
func isnumber(cc rune) bool {
return (cc == 'b' || cc == 'B') ||
(cc == 'o' || cc == 'O') ||
(cc == 'x' || cc == 'X') ||
(cc >= '0' && cc <= '9') ||
(cc >= 'a' && cc <= 'f') ||
(cc >= 'A' && cc <= 'F')
}
func align(v int, n int) int {
return (((v - 1) >> n) + 1) << n
}
func append8(m *[]byte, v byte) {
*m = append(*m, v)
}
func append16(m *[]byte, v uint16) {
p := len(*m)
*m = append(*m, 0, 0)
binary.LittleEndian.PutUint16((*m)[p:], v)
}
func append32(m *[]byte, v uint32) {
p := len(*m)
*m = append(*m, 0, 0, 0, 0)
binary.LittleEndian.PutUint32((*m)[p:], v)
}
func append64(m *[]byte, v uint64) {
p := len(*m)
*m = append(*m, 0, 0, 0, 0, 0, 0, 0, 0)
binary.LittleEndian.PutUint64((*m)[p:], v)
}
func expandmm(m *[]byte, n int, v byte) {
sl := (*_GoSlice)(unsafe.Pointer(m))
nb := sl.len + n
/* grow as needed */
if nb > cap(*m) {
*m = growslice(byteType, *m, nb)
}
/* fill the new area */
memset(unsafe.Pointer(uintptr(sl.ptr) + uintptr(sl.len)), v, uintptr(n))
sl.len = nb
}
func memset(p unsafe.Pointer, c byte, n uintptr) {
if c != 0 {
memsetv(p, c, n)
} else {
memclrNoHeapPointers(p, n)
}
}
func memsetv(p unsafe.Pointer, c byte, n uintptr) {
for i := uintptr(0); i < n; i++ {
*(*byte)(unsafe.Pointer(uintptr(p) + i)) = c
}
}
func literal64(v string) (uint64, error) {
var nb int
var ch rune
var ex error
var mm [12]byte
/* unquote the runes */
for v != "" {
if ch, _, v, ex = strconv.UnquoteChar(v, '\''); ex != nil {
return 0, ex
} else if nb += utf8.EncodeRune(mm[nb:], ch); nb > 8 {
return 0, errors.New("multi-char constant too large")
}
}
/* convert to uint64 */
return *(*uint64)(unsafe.Pointer(&mm)), nil
}
var (
byteWrap = reflect.TypeOf(byte(0))
byteType = (*_GoType)(efaceOf(byteWrap).ptr)
)
//go:linkname growslice runtime.growslice
func growslice(_ *_GoType, _ []byte, _ int) []byte
//go:noescape
//go:linkname memclrNoHeapPointers runtime.memclrNoHeapPointers
func memclrNoHeapPointers(_ unsafe.Pointer, _ uintptr)

@ -23,6 +23,7 @@ type Config struct {
// Address It supports single and cluster redis server. Multiple addresses joined with char ','. Eg: 192.168.1.1:6379, 192.168.1.2:6379.
Address string `json:"address"`
Db int `json:"db"` // Redis db.
User string `json:"user"` // Username for AUTH.
Pass string `json:"pass"` // Password for AUTH.
MinIdle int `json:"minIdle"` // Minimum number of connections allowed to be idle (default is 0)
MaxIdle int `json:"maxIdle"` // Maximum number of connections allowed to be idle (default is 10)

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save