diff --git a/decoder/decoder_compat.go b/decoder/decoder_compat.go index a0e1de4da..408d59394 100644 --- a/decoder/decoder_compat.go +++ b/decoder/decoder_compat.go @@ -1,3 +1,4 @@ +//go:build (!amd64 && !arm64) || go1.24 || !go1.17 || (arm64 && !go1.20) // +build !amd64,!arm64 go1.24 !go1.17 arm64,!go1.20 /* @@ -19,14 +20,15 @@ package decoder import ( - `bytes` - `encoding/json` - `io` - `reflect` - `unsafe` - - `github.com/bytedance/sonic/internal/native/types` - `github.com/bytedance/sonic/option` + "bytes" + "encoding/json" + "io" + "reflect" + "unsafe" + + "github.com/bytedance/sonic/internal/decoder/consts" + "github.com/bytedance/sonic/internal/native/types" + "github.com/bytedance/sonic/option" ) func init() { @@ -34,15 +36,16 @@ func init() { } const ( - _F_use_int64 = 0 - _F_disable_urc = 2 - _F_disable_unknown = 3 - _F_copy_string = 4 + _F_use_int64 = consts.F_use_int64 + _F_disable_urc = consts.F_disable_unknown + _F_disable_unknown = consts.F_disable_unknown + _F_copy_string = consts.F_copy_string - _F_use_number = types.B_USE_NUMBER - _F_validate_string = types.B_VALIDATE_STRING - _F_allow_control = types.B_ALLOW_CONTROL - _F_no_validate_json = types.B_NO_VALIDATE_JSON + _F_use_number = consts.F_use_number + _F_validate_string = consts.F_validate_string + _F_allow_control = consts.F_allow_control + _F_no_validate_json = consts.F_no_validate_json + _F_case_sensitive = consts.F_case_sensitive ) type Options uint64 @@ -55,6 +58,7 @@ const ( OptionCopyString Options = 1 << _F_copy_string OptionValidateString Options = 1 << _F_validate_string OptionNoValidateJSON Options = 1 << _F_no_validate_json + OptionCaseSensitive Options = 1 << _F_case_sensitive ) func (self *Decoder) SetOptions(opts Options) { diff --git a/decoder/decoder_native.go b/decoder/decoder_native.go index 450dfb624..bf71e1bd4 100644 --- a/decoder/decoder_native.go +++ b/decoder/decoder_native.go @@ -44,6 +44,7 @@ const ( OptionCopyString Options = api.OptionCopyString OptionValidateString Options = api.OptionValidateString OptionNoValidateJSON Options = api.OptionNoValidateJSON + OptionCaseSensitive Options = api.OptionCaseSensitive ) // StreamDecoder is the decoder context object for streaming input. diff --git a/decoder/decoder_native_test.go b/decoder/decoder_native_test.go index 9b435ca92..62e85b52a 100644 --- a/decoder/decoder_native_test.go +++ b/decoder/decoder_native_test.go @@ -33,6 +33,67 @@ import ( "github.com/stretchr/testify/require" ) +func TestDecoder_OptionCaseSensitive(t *testing.T) { + var js = `{"a":1,"normallllll":1,"longllllllllllllllllllllllllllllllllll":1}` + type TS struct{ + A int + Normallllll int + Longllllllllllllllllllllllllllllllllll int + } + var obj = TS{} + d := NewDecoder(js) + d.SetOptions(OptionCaseSensitive) + err := d.Decode(&obj) + require.NoError(t, err) + require.Equal(t, TS{}, obj) +} + + +func TestDecoder_MapWithIndirectElement(t *testing.T) { + var v map[string]struct { A [129]byte } + _, err := decode(`{"":{"A":[1,2,3,4,5]}}`, &v, false) + require.NoError(t, err) + assert.Equal(t, [129]byte{1, 2, 3, 4, 5}, v[""].A) +} + +func TestDecoder_OptionCaseSensitiveForManyKeys(t *testing.T) { + var js = `{"a":1,"b":2,"C":3,"DD":4,"eE":5,"fF":6,"G":7,"H":8,"I":9,"J":10,"K":11,"L":12,"M":13}` + type TS struct{ + A int + B int + C int `json:"c"` + Dd int `json:"dd"` + Ee int `json:"ee"` + Ff int `json:"Ff"` + G int `json:"g"` + H int `json:"h"` + I int `json:"i"` + J int `json:"j"` + K int `json:"k"` + L int `json:"l"` + M int `json:"m"` + } + + { + var obj = TS{} + err := json.Unmarshal([]byte(js), &obj) + require.NoError(t, err) + + var obj2 = TS{} + d := NewDecoder(js) + err2 := d.Decode(&obj2) + require.NoError(t, err2) + require.Equal(t, obj, obj2) + } + + var obj = TS{} + d := NewDecoder(js) + d.SetOptions(OptionCaseSensitive) + err := d.Decode(&obj) + require.NoError(t, err) + require.Equal(t, TS{}, obj) +} + func BenchmarkSkipValidate(b *testing.B) { type skiptype struct { diff --git a/decoder/decoder_test.go b/decoder/decoder_test.go index c58ed97a5..6da755857 100644 --- a/decoder/decoder_test.go +++ b/decoder/decoder_test.go @@ -26,7 +26,6 @@ import ( "time" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestMain(m *testing.M) { @@ -287,14 +286,6 @@ func TestDecoder_Binding(t *testing.T) { assert.Equal(t, _BindingValue, v, 0) } - -func TestDecoder_MapWithIndirectElement(t *testing.T) { - var v map[string]struct { A [129]byte } - _, err := decode(`{"":{"A":[1,2,3,4,5]}}`, &v, false) - require.NoError(t, err) - assert.Equal(t, [129]byte{1, 2, 3, 4, 5}, v[""].A) -} - func BenchmarkDecoder_Generic_Sonic(b *testing.B) { var w interface{} _, _ = decode(TwitterJson, &w, true) diff --git a/internal/decoder/api/decoder.go b/internal/decoder/api/decoder.go index 0dc01998f..bae0584c2 100644 --- a/internal/decoder/api/decoder.go +++ b/internal/decoder/api/decoder.go @@ -35,6 +35,7 @@ const ( _F_use_int64 = consts.F_use_int64 _F_use_number = consts.F_use_number _F_validate_string = consts.F_validate_string + _F_case_sensitive = consts.F_case_sensitive _MaxStack = consts.MaxStack @@ -45,6 +46,7 @@ const ( OptionCopyString = consts.OptionCopyString OptionValidateString = consts.OptionValidateString OptionNoValidateJSON = consts.OptionNoValidateJSON + OptionCaseSensitive = consts.OptionCaseSensitive ) type ( diff --git a/internal/decoder/consts/option.go b/internal/decoder/consts/option.go index 4195ebda7..f8c49d500 100644 --- a/internal/decoder/consts/option.go +++ b/internal/decoder/consts/option.go @@ -12,11 +12,11 @@ const ( 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 F_no_validate_json = types.B_NO_VALIDATE_JSON + F_case_sensitive = 7 ) type Options uint64 @@ -29,6 +29,7 @@ const ( OptionCopyString Options = 1 << F_copy_string OptionValidateString Options = 1 << F_validate_string OptionNoValidateJSON Options = 1 << F_no_validate_json + OptionCaseSensitive Options = 1 << F_case_sensitive ) const ( diff --git a/internal/decoder/jitdec/assembler_regabi_amd64.go b/internal/decoder/jitdec/assembler_regabi_amd64.go index 42b8b502f..04e854df7 100644 --- a/internal/decoder/jitdec/assembler_regabi_amd64.go +++ b/internal/decoder/jitdec/assembler_regabi_amd64.go @@ -1794,6 +1794,8 @@ func (self *_Assembler) _asm_OP_struct_field(p *_Instr) { self.Emit("MOVQ" , _R8, _VAR_sr) // MOVQ R8, sr self.Sjmp("JMP" , "_end_{n}") // JMP _end_{n} self.Link("_try_lowercase_{n}") // _try_lowercase_{n}: + self.Emit("BTQ" , jit.Imm(_F_case_sensitive), _ARG_fv) // check if enable option CaseSensitive + self.Sjmp("JC" , "_unknown_{n}") self.Emit("MOVQ" , jit.Imm(referenceFields(p.vf())), _AX) // MOVQ ${p.vf()}, AX self.Emit("MOVQ", _ARG_sv_p, _BX) // MOVQ sv, BX self.Emit("MOVQ", _ARG_sv_n, _CX) // MOVQ sv, CX @@ -1801,6 +1803,10 @@ func (self *_Assembler) _asm_OP_struct_field(p *_Instr) { self.Emit("MOVQ" , _AX, _VAR_sr) // MOVQ AX, _VAR_sr self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX self.Sjmp("JNS" , "_end_{n}") // JNS _end_{n} + self.Link("_unknown_{n}") + // HACK: because `_VAR_sr` maybe used in `F_vstring`, so we should clear here again for `_OP_switch`. + self.Emit("MOVQ" , jit.Imm(-1), _AX) // MOVQ $-1, AX + self.Emit("MOVQ" , _AX, _VAR_sr) // MOVQ AX, sr self.Emit("BTQ" , jit.Imm(_F_disable_unknown), _ARG_fv) // BTQ ${_F_disable_unknown}, fv self.Sjmp("JC" , _LB_field_error) // JC _field_error self.Link("_end_{n}") // _end_{n}: diff --git a/internal/decoder/jitdec/decoder.go b/internal/decoder/jitdec/decoder.go index bbb4b4b61..de6325289 100644 --- a/internal/decoder/jitdec/decoder.go +++ b/internal/decoder/jitdec/decoder.go @@ -27,6 +27,7 @@ const ( _F_use_number = consts.F_use_number _F_no_validate_json = consts.F_no_validate_json _F_validate_string = consts.F_validate_string + _F_case_sensitive = consts.F_case_sensitive ) var ( diff --git a/internal/decoder/optdec/structs.go b/internal/decoder/optdec/structs.go index bce2758f1..8b148eadf 100644 --- a/internal/decoder/optdec/structs.go +++ b/internal/decoder/optdec/structs.go @@ -4,6 +4,7 @@ import ( "reflect" "unsafe" + "github.com/bytedance/sonic/internal/decoder/consts" caching "github.com/bytedance/sonic/internal/optcaching" "github.com/bytedance/sonic/internal/resolver" ) @@ -38,7 +39,7 @@ func (d *structDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) erro next = val.Next() // find field idx - idx := d.fieldMap.Get(key) + idx := d.fieldMap.Get(key, ctx.Options()&uint64(consts.OptionCaseSensitive) != 0) if idx == -1 { if Options(ctx.Options())&OptionDisableUnknown != 0 { return error_field(key) diff --git a/internal/native/neon/f32toa_arm64.s b/internal/native/neon/f32toa_arm64.s index a4f74da8a..64eed6d71 100644 --- a/internal/native/neon/f32toa_arm64.s +++ b/internal/native/neon/f32toa_arm64.s @@ -916,7 +916,7 @@ _Digits: WORD $0x37393639 // .ascii 4, '96979899' WORD $0x39393839 // .ascii 4, '9899' WORD $0x00000000 // .p2align 3, 0x00 -_LB_15828841: // _pow10_ceil_sig_f32.g +_LB_3c57fe76: // _pow10_ceil_sig_f32.g WORD $0x4b43fcf5; WORD $0x81ceb32c // .quad -9093133594791772939 WORD $0x5e14fc32; WORD $0xa2425ff7 // .quad -6754730975062328270 WORD $0x359a3b3f; WORD $0xcad2f7f5 // .quad -3831727700400522433 diff --git a/internal/native/neon/f64toa_arm64.s b/internal/native/neon/f64toa_arm64.s index d1e7f08b8..12bf45299 100644 --- a/internal/native/neon/f64toa_arm64.s +++ b/internal/native/neon/f64toa_arm64.s @@ -1232,7 +1232,7 @@ _Digits: WORD $0x37393639 // .ascii 4, '96979899' WORD $0x39393839 // .ascii 4, '9899' // .p2align 3, 0x00 -_LB_3b41de77: // _pow10_ceil_sig.g +_LB_f262bdcb: // _pow10_ceil_sig.g WORD $0xbebcdc4f; WORD $0xff77b1fc // .quad -38366372719436721 WORD $0x13bb0f7b; WORD $0x25e8e89c // .quad 2731688931043774331 WORD $0xf73609b1; WORD $0x9faacf3d // .quad -6941508010590729807 diff --git a/internal/native/neon/lookup_small_key_arm64.s b/internal/native/neon/lookup_small_key_arm64.s index fb856f144..004c09374 100644 --- a/internal/native/neon/lookup_small_key_arm64.s +++ b/internal/native/neon/lookup_small_key_arm64.s @@ -64,250 +64,232 @@ _lookup_small_key: WORD $0xf940002b // ldr x11, [x1] WORD $0x12001d49 // and w9, w10, #0xff WORD $0x8b294928 // add x8, x9, w9, uxtw #2 - WORD $0x8b08016c // add x12, x11, x8 - WORD $0x39400188 // ldrb w8, [x12] - WORD $0x34001be8 // cbz w8, LBB0_46 $892(%rip) - WORD $0xf940000f // ldr x15, [x0] - WORD $0xb840118c // ldur w12, [x12, #1] - WORD $0x1102958d // add w13, w12, #165 - WORD $0x8b0d016d // add x13, x11, x13 - WORD $0x92401d4e // and x14, x10, #0xff + WORD $0x8b08016d // add x13, x11, x8 + WORD $0x394001a8 // ldrb w8, [x13] + WORD $0x340019e8 // cbz w8, LBB0_46 $828(%rip) + WORD $0xf940000c // ldr x12, [x0] + WORD $0xb84011ad // ldur w13, [x13, #1] + WORD $0x110295ae // add w14, w13, #165 + WORD $0x8b0e016e // add x14, x11, x14 + WORD $0x92401d4f // and x15, x10, #0xff WORD $0x7100253f // cmp w9, #9 WORD $0x54000942 // b.hs LBB0_20 $296(%rip) WORD $0x11000530 // add w16, w9, #1 - WORD $0x394001f1 // ldrb w17, [x15] + WORD $0x39400191 // ldrb w17, [x12] WORD $0x528000e0 // mov w0, #7 WORD $0xaa0803e1 // mov x1, x8 WORD $0x14000007 // b LBB0_5 $28(%rip) LBB0_3: WORD $0x52800003 // mov w3, #0 - WORD $0x6b0e007f // cmp w3, w14 + WORD $0x6b0f007f // cmp w3, w15 WORD $0x540007a2 // b.hs LBB0_19 $244(%rip) LBB0_4: - WORD $0x8b1001ad // add x13, x13, x16 + WORD $0x8b1001ce // add x14, x14, x16 WORD $0x71000421 // subs w1, w1, #1 - WORD $0x54000b60 // b.eq LBB0_23 $364(%rip) + WORD $0x54000b40 // b.eq LBB0_23 $360(%rip) LBB0_5: - WORD $0x394001a3 // ldrb w3, [x13] + WORD $0x394001c3 // ldrb w3, [x14] WORD $0x6b11007f // cmp w3, w17 WORD $0x54ffff01 // b.ne LBB0_3 $-32(%rip) - WORD $0x394005a3 // ldrb w3, [x13, #1] - WORD $0x394005e4 // ldrb w4, [x15, #1] + WORD $0x394005c3 // ldrb w3, [x14, #1] + WORD $0x39400584 // ldrb w4, [x12, #1] WORD $0x6b04007f // cmp w3, w4 WORD $0x54000381 // b.ne LBB0_13 $112(%rip) - WORD $0x394009a3 // ldrb w3, [x13, #2] - WORD $0x394009e4 // ldrb w4, [x15, #2] + WORD $0x394009c3 // ldrb w3, [x14, #2] + WORD $0x39400984 // ldrb w4, [x12, #2] WORD $0x6b04007f // cmp w3, w4 WORD $0x54000381 // b.ne LBB0_14 $112(%rip) - WORD $0x39400da3 // ldrb w3, [x13, #3] - WORD $0x39400de4 // ldrb w4, [x15, #3] + WORD $0x39400dc3 // ldrb w3, [x14, #3] + WORD $0x39400d84 // ldrb w4, [x12, #3] WORD $0x6b04007f // cmp w3, w4 WORD $0x54000381 // b.ne LBB0_15 $112(%rip) - WORD $0x394011a3 // ldrb w3, [x13, #4] - WORD $0x394011e4 // ldrb w4, [x15, #4] + WORD $0x394011c3 // ldrb w3, [x14, #4] + WORD $0x39401184 // ldrb w4, [x12, #4] WORD $0x6b04007f // cmp w3, w4 WORD $0x54000381 // b.ne LBB0_16 $112(%rip) - WORD $0x394015a3 // ldrb w3, [x13, #5] - WORD $0x394015e4 // ldrb w4, [x15, #5] + WORD $0x394015c3 // ldrb w3, [x14, #5] + WORD $0x39401584 // ldrb w4, [x12, #5] WORD $0x6b04007f // cmp w3, w4 WORD $0x54000381 // b.ne LBB0_17 $112(%rip) - WORD $0x394019a3 // ldrb w3, [x13, #6] - WORD $0x394019e4 // ldrb w4, [x15, #6] + WORD $0x394019c3 // ldrb w3, [x14, #6] + WORD $0x39401984 // ldrb w4, [x12, #6] WORD $0x6b04007f // cmp w3, w4 WORD $0x54000381 // b.ne LBB0_18 $112(%rip) - WORD $0x39401da3 // ldrb w3, [x13, #7] - WORD $0x39401de4 // ldrb w4, [x15, #7] + WORD $0x39401dc3 // ldrb w3, [x14, #7] + WORD $0x39401d84 // ldrb w4, [x12, #7] WORD $0x6b04007f // cmp w3, w4 WORD $0x1a801403 // cinc w3, w0, eq - WORD $0x6b0e007f // cmp w3, w14 + WORD $0x6b0f007f // cmp w3, w15 WORD $0x54fffba3 // b.lo LBB0_4 $-140(%rip) WORD $0x14000018 // b LBB0_19 $96(%rip) LBB0_13: WORD $0x52800023 // mov w3, #1 - WORD $0x6b0e007f // cmp w3, w14 + WORD $0x6b0f007f // cmp w3, w15 WORD $0x54fffb23 // b.lo LBB0_4 $-156(%rip) WORD $0x14000014 // b LBB0_19 $80(%rip) LBB0_14: WORD $0x52800043 // mov w3, #2 - WORD $0x6b0e007f // cmp w3, w14 + WORD $0x6b0f007f // cmp w3, w15 WORD $0x54fffaa3 // b.lo LBB0_4 $-172(%rip) WORD $0x14000010 // b LBB0_19 $64(%rip) LBB0_15: WORD $0x52800063 // mov w3, #3 - WORD $0x6b0e007f // cmp w3, w14 + WORD $0x6b0f007f // cmp w3, w15 WORD $0x54fffa23 // b.lo LBB0_4 $-188(%rip) WORD $0x1400000c // b LBB0_19 $48(%rip) LBB0_16: WORD $0x52800083 // mov w3, #4 - WORD $0x6b0e007f // cmp w3, w14 + WORD $0x6b0f007f // cmp w3, w15 WORD $0x54fff9a3 // b.lo LBB0_4 $-204(%rip) WORD $0x14000008 // b LBB0_19 $32(%rip) LBB0_17: WORD $0x528000a3 // mov w3, #5 - WORD $0x6b0e007f // cmp w3, w14 + WORD $0x6b0f007f // cmp w3, w15 WORD $0x54fff923 // b.lo LBB0_4 $-220(%rip) WORD $0x14000004 // b LBB0_19 $16(%rip) LBB0_18: WORD $0x528000c3 // mov w3, #6 - WORD $0x6b0e007f // cmp w3, w14 + WORD $0x6b0f007f // cmp w3, w15 WORD $0x54fff8a3 // b.lo LBB0_4 $-236(%rip) LBB0_19: - WORD $0x8b0e01a8 // add x8, x13, x14 + WORD $0x8b0f01c8 // add x8, x14, x15 WORD $0x39400100 // ldrb w0, [x8] WORD $0xa940fbfd // ldp fp, lr, [sp, #8] WORD $0x910083ff // add sp, sp, #32 WORD $0xd65f03c0 // ret LBB0_20: - WORD $0xad4001e1 // ldp q1, q0, [x15] - WORD $0x9280000f // mov x15, #-1 - WORD $0x9ace21ef // lsl x15, x15, x14 - WORD $0x11000530 // add w16, w9, #1 + WORD $0xad400580 // ldp q0, q1, [x12] + WORD $0x92800010 // mov x16, #-1 + WORD $0x9acf2210 // lsl x16, x16, x15 + WORD $0x11000531 // add w17, w9, #1 Lloh0: - WORD $0x10fff331 // adr x17, lCPI0_0 $-412(%rip) + WORD $0x10fff320 // adr x0, lCPI0_0 $-412(%rip) Lloh1: - WORD $0x3dc00222 // ldr q2, [x17, lCPI0_0@PAGEOFF] $0(%rip) + WORD $0x3dc00002 // ldr q2, [x0, lCPI0_0@PAGEOFF] $0(%rip) Lloh2: - WORD $0x10fff371 // adr x17, lCPI0_1 $-404(%rip) + WORD $0x10fff360 // adr x0, lCPI0_1 $-404(%rip) Lloh3: - WORD $0x3dc00223 // ldr q3, [x17, lCPI0_1@PAGEOFF] $0(%rip) - WORD $0xaa0803f1 // mov x17, x8 + WORD $0x3dc00003 // ldr q3, [x0, lCPI0_1@PAGEOFF] $0(%rip) + WORD $0xaa0803e0 // mov x0, x8 LBB0_21: - WORD $0xad4015a4 // ldp q4, q5, [x13] - WORD $0x6e248c24 // cmeq.16b v4, v1, v4 - WORD $0x6e258c05 // cmeq.16b v5, v0, v5 + WORD $0xad4015c4 // ldp q4, q5, [x14] + WORD $0x6e248c04 // cmeq.16b v4, v0, v4 + WORD $0x6e258c25 // cmeq.16b v5, v1, v5 WORD $0x4e221c84 // and.16b v4, v4, v2 WORD $0x4e030084 // tbl.16b v4, { v4 }, v3 WORD $0x4e71b884 // addv.8h h4, v4 - WORD $0x1e260080 // fmov w0, s4 + WORD $0x1e260081 // fmov w1, s4 WORD $0x4e221ca4 // and.16b v4, v5, v2 WORD $0x4e030084 // tbl.16b v4, { v4 }, v3 WORD $0x4e71b884 // addv.8h h4, v4 - WORD $0x1e260081 // fmov w1, s4 - WORD $0x33103c20 // bfi w0, w1, #16, #16 - WORD $0x2a0f0000 // orr w0, w0, w15 - WORD $0x3100041f // cmn w0, #1 + WORD $0x1e260083 // fmov w3, s4 + WORD $0x33103c61 // bfi w1, w3, #16, #16 + WORD $0x2a100021 // orr w1, w1, w16 + WORD $0x3100043f // cmn w1, #1 WORD $0x54fffc80 // b.eq LBB0_19 $-112(%rip) - WORD $0x8b1001ad // add x13, x13, x16 - WORD $0x71000631 // subs w17, w17, #1 + WORD $0x8b1101ce // add x14, x14, x17 + WORD $0x71000400 // subs w0, w0, #1 WORD $0x54fffde1 // b.ne LBB0_21 $-68(%rip) - WORD $0x14000002 // b LBB0_24 $8(%rip) LBB0_23: - WORD $0xad4001e1 // ldp q1, q0, [x15] -LBB0_24: - WORD $0x4f05e7e2 // movi.16b v2, #191 - WORD $0x4e228424 // add.16b v4, v1, v2 - WORD $0x4f00e743 // movi.16b v3, #26 - WORD $0x6e243465 // cmhi.16b v5, v3, v4 - WORD $0x4f01e404 // movi.16b v4, #32 - WORD $0x4e241ca5 // and.16b v5, v5, v4 - WORD $0x4e2184a1 // add.16b v1, v5, v1 - WORD $0x8b0c016b // add x11, x11, x12 + WORD $0xb100045f // cmn x2, #1 + WORD $0x54000c40 // b.eq LBB0_46 $392(%rip) + WORD $0x3dc00180 // ldr q0, [x12] + WORD $0x4f05e7e1 // movi.16b v1, #191 + WORD $0x4e218403 // add.16b v3, v0, v1 + WORD $0x4f00e742 // movi.16b v2, #26 + WORD $0x6e233444 // cmhi.16b v4, v2, v3 + WORD $0x4f01e403 // movi.16b v3, #32 + WORD $0x4e231c84 // and.16b v4, v4, v3 + WORD $0x4e208480 // add.16b v0, v4, v0 + WORD $0x8b0d016b // add x11, x11, x13 WORD $0x8b02016b // add x11, x11, x2 WORD $0x92401d4a // and x10, x10, #0xff WORD $0x7100253f // cmp w9, #9 - WORD $0x54000922 // b.hs LBB0_43 $292(%rip) - WORD $0x0e013c2c // umov.b w12, v1[0] - WORD $0x0e033c2d // umov.b w13, v1[1] - WORD $0x0e053c2e // umov.b w14, v1[2] - WORD $0x0e073c2f // umov.b w15, v1[3] - WORD $0x0e093c30 // umov.b w16, v1[4] - WORD $0x0e0b3c31 // umov.b w17, v1[5] + WORD $0x540006e2 // b.hs LBB0_43 $220(%rip) + WORD $0x0e013c0c // umov.b w12, v0[0] + WORD $0x0e033c0d // umov.b w13, v0[1] + WORD $0x0e053c0e // umov.b w14, v0[2] + WORD $0x0e073c0f // umov.b w15, v0[3] + WORD $0x0e093c10 // umov.b w16, v0[4] + WORD $0x0e0b3c11 // umov.b w17, v0[5] WORD $0x11000529 // add w9, w9, #1 - WORD $0x0e0d3c20 // umov.b w0, v1[6] + WORD $0x0e0d3c00 // umov.b w0, v0[6] WORD $0x528000e1 // mov w1, #7 - WORD $0x0e0f3c22 // umov.b w2, v1[7] - WORD $0x14000007 // b LBB0_28 $28(%rip) + WORD $0x0e0f3c02 // umov.b w2, v0[7] LBB0_26: - WORD $0x52800003 // mov w3, #0 - WORD $0x6b0a007f // cmp w3, w10 - WORD $0x540006c2 // b.hs LBB0_42 $216(%rip) -LBB0_27: - WORD $0x8b09016b // add x11, x11, x9 - WORD $0x71000508 // subs w8, w8, #1 - WORD $0x54000aa0 // b.eq LBB0_46 $340(%rip) -LBB0_28: WORD $0x39400163 // ldrb w3, [x11] WORD $0x6b2c007f // cmp w3, w12, uxtb - WORD $0x54ffff01 // b.ne LBB0_26 $-32(%rip) + WORD $0x540002e1 // b.ne LBB0_34 $92(%rip) WORD $0x39400563 // ldrb w3, [x11, #1] WORD $0x6b2d007f // cmp w3, w13, uxtb - WORD $0x540002c1 // b.ne LBB0_36 $88(%rip) + WORD $0x540002c1 // b.ne LBB0_35 $88(%rip) WORD $0x39400963 // ldrb w3, [x11, #2] WORD $0x6b2e007f // cmp w3, w14, uxtb - WORD $0x540002e1 // b.ne LBB0_37 $92(%rip) + WORD $0x540002a1 // b.ne LBB0_36 $84(%rip) WORD $0x39400d63 // ldrb w3, [x11, #3] WORD $0x6b2f007f // cmp w3, w15, uxtb - WORD $0x54000301 // b.ne LBB0_38 $96(%rip) + WORD $0x54000281 // b.ne LBB0_37 $80(%rip) WORD $0x39401163 // ldrb w3, [x11, #4] WORD $0x6b30007f // cmp w3, w16, uxtb - WORD $0x54000321 // b.ne LBB0_39 $100(%rip) + WORD $0x54000261 // b.ne LBB0_38 $76(%rip) WORD $0x39401563 // ldrb w3, [x11, #5] WORD $0x6b31007f // cmp w3, w17, uxtb - WORD $0x54000341 // b.ne LBB0_40 $104(%rip) + WORD $0x54000241 // b.ne LBB0_39 $72(%rip) WORD $0x39401963 // ldrb w3, [x11, #6] WORD $0x6b20007f // cmp w3, w0, uxtb - WORD $0x54000361 // b.ne LBB0_41 $108(%rip) + WORD $0x54000221 // b.ne LBB0_40 $68(%rip) WORD $0x39401d63 // ldrb w3, [x11, #7] WORD $0x6b22007f // cmp w3, w2, uxtb WORD $0x1a811423 // cinc w3, w1, eq - WORD $0x6b0a007f // cmp w3, w10 - WORD $0x54fffc83 // b.lo LBB0_27 $-112(%rip) - WORD $0x14000018 // b LBB0_42 $96(%rip) -LBB0_36: + WORD $0x1400000e // b LBB0_41 $56(%rip) +LBB0_34: + WORD $0x52800003 // mov w3, #0 + WORD $0x1400000c // b LBB0_41 $48(%rip) +LBB0_35: WORD $0x52800023 // mov w3, #1 - WORD $0x6b0a007f // cmp w3, w10 - WORD $0x54fffc03 // b.lo LBB0_27 $-128(%rip) - WORD $0x14000014 // b LBB0_42 $80(%rip) -LBB0_37: + WORD $0x1400000a // b LBB0_41 $40(%rip) +LBB0_36: WORD $0x52800043 // mov w3, #2 - WORD $0x6b0a007f // cmp w3, w10 - WORD $0x54fffb83 // b.lo LBB0_27 $-144(%rip) - WORD $0x14000010 // b LBB0_42 $64(%rip) -LBB0_38: + WORD $0x14000008 // b LBB0_41 $32(%rip) +LBB0_37: WORD $0x52800063 // mov w3, #3 - WORD $0x6b0a007f // cmp w3, w10 - WORD $0x54fffb03 // b.lo LBB0_27 $-160(%rip) - WORD $0x1400000c // b LBB0_42 $48(%rip) -LBB0_39: + WORD $0x14000006 // b LBB0_41 $24(%rip) +LBB0_38: WORD $0x52800083 // mov w3, #4 - WORD $0x6b0a007f // cmp w3, w10 - WORD $0x54fffa83 // b.lo LBB0_27 $-176(%rip) - WORD $0x14000008 // b LBB0_42 $32(%rip) -LBB0_40: + WORD $0x14000004 // b LBB0_41 $16(%rip) +LBB0_39: WORD $0x528000a3 // mov w3, #5 - WORD $0x6b0a007f // cmp w3, w10 - WORD $0x54fffa03 // b.lo LBB0_27 $-192(%rip) - WORD $0x14000004 // b LBB0_42 $16(%rip) -LBB0_41: + WORD $0x14000002 // b LBB0_41 $8(%rip) +LBB0_40: WORD $0x528000c3 // mov w3, #6 +LBB0_41: WORD $0x6b0a007f // cmp w3, w10 - WORD $0x54fff983 // b.lo LBB0_27 $-208(%rip) -LBB0_42: - WORD $0x8b0a0168 // add x8, x11, x10 - WORD $0x39400100 // ldrb w0, [x8] - WORD $0xa940fbfd // ldp fp, lr, [sp, #8] - WORD $0x910083ff // add sp, sp, #32 - WORD $0xd65f03c0 // ret + WORD $0x540004e2 // b.hs LBB0_47 $156(%rip) + WORD $0x8b09016b // add x11, x11, x9 + WORD $0x71000508 // subs w8, w8, #1 + WORD $0x54fffac1 // b.ne LBB0_26 $-168(%rip) + WORD $0x1400001f // b LBB0_46 $124(%rip) LBB0_43: - WORD $0x4e228402 // add.16b v2, v0, v2 - WORD $0x6e223462 // cmhi.16b v2, v3, v2 - WORD $0x4e241c42 // and.16b v2, v2, v4 - WORD $0x4e208440 // add.16b v0, v2, v0 + WORD $0x3dc00584 // ldr q4, [x12, #16] + WORD $0x4e218481 // add.16b v1, v4, v1 + WORD $0x6e213441 // cmhi.16b v1, v2, v1 + WORD $0x4e231c21 // and.16b v1, v1, v3 + WORD $0x4e248421 // add.16b v1, v1, v4 WORD $0x9280000c // mov x12, #-1 WORD $0x9aca218c // lsl x12, x12, x10 WORD $0x11000529 // add w9, w9, #1 Lloh4: - WORD $0x10ffe4ad // adr x13, lCPI0_0 $-876(%rip) + WORD $0x10ffe6ad // adr x13, lCPI0_0 $-812(%rip) Lloh5: WORD $0x3dc001a2 // ldr q2, [x13, lCPI0_0@PAGEOFF] $0(%rip) Lloh6: - WORD $0x10ffe4ed // adr x13, lCPI0_1 $-868(%rip) + WORD $0x10ffe6ed // adr x13, lCPI0_1 $-804(%rip) Lloh7: WORD $0x3dc001a3 // ldr q3, [x13, lCPI0_1@PAGEOFF] $0(%rip) LBB0_44: WORD $0xad401564 // ldp q4, q5, [x11] - WORD $0x6e248c24 // cmeq.16b v4, v1, v4 - WORD $0x6e258c05 // cmeq.16b v5, v0, v5 + WORD $0x6e248c04 // cmeq.16b v4, v0, v4 + WORD $0x6e258c25 // cmeq.16b v5, v1, v5 WORD $0x4e221c84 // and.16b v4, v4, v2 WORD $0x4e030084 // tbl.16b v4, { v4 }, v3 WORD $0x4e71b884 // addv.8h h4, v4 @@ -319,7 +301,7 @@ LBB0_44: WORD $0x33103dcd // bfi w13, w14, #16, #16 WORD $0x2a0c01ad // orr w13, w13, w12 WORD $0x310005bf // cmn w13, #1 - WORD $0x54fffc40 // b.eq LBB0_42 $-120(%rip) + WORD $0x54000100 // b.eq LBB0_47 $32(%rip) WORD $0x8b09016b // add x11, x11, x9 WORD $0x71000508 // subs w8, w8, #1 WORD $0x54fffde1 // b.ne LBB0_44 $-68(%rip) @@ -328,6 +310,12 @@ LBB0_46: WORD $0xa940fbfd // ldp fp, lr, [sp, #8] WORD $0x910083ff // add sp, sp, #32 WORD $0xd65f03c0 // ret +LBB0_47: + WORD $0x8b0a0168 // add x8, x11, x10 + WORD $0x39400100 // ldrb w0, [x8] + WORD $0xa940fbfd // ldp fp, lr, [sp, #8] + WORD $0x910083ff // add sp, sp, #32 + WORD $0xd65f03c0 // ret TEXT ยท__lookup_small_key(SB), NOSPLIT, $0-32 NO_LOCAL_POINTERS diff --git a/internal/optcaching/fcache.go b/internal/optcaching/fcache.go index 40b3e081f..010028203 100644 --- a/internal/optcaching/fcache.go +++ b/internal/optcaching/fcache.go @@ -32,7 +32,7 @@ const _PaddingSize = 32 type FieldLookup interface { Set(fields []resolver.FieldMeta) - Get(name string) int + Get(name string, caseSensitive bool) int } func isAscii(s string) bool { @@ -93,13 +93,15 @@ func (self *SmallFieldMap) Set(fields []resolver.FieldMeta) { } } -func (self *SmallFieldMap) Get(name string) int { +func (self *SmallFieldMap) Get(name string, caseSensitive bool) int { for i, k := range self.keys { if len(k) == len(name) && k == name { return i } } - + if caseSensitive { + return -1 + } name = strings.ToLower(name) for i, k := range self.lowerKeys { if len(k) == len(name) && k == name { @@ -153,16 +155,20 @@ const _HdrSlot = 33 const _HdrSize = _HdrSlot * 5 // use native SIMD to accelerate it -func (self *NormalFieldMap) Get(name string) int { +func (self *NormalFieldMap) Get(name string, caseSensitive bool) int { // small keys use native C if len(name) <= 32 { - _ = native.LookupSmallKey - return native.LookupSmallKey(&name, &self.keys, self.lowOffset); + _ = native.LookupSmallKey + lowOffset := self.lowOffset + if caseSensitive { + lowOffset = -1 + } + return native.LookupSmallKey(&name, &self.keys, lowOffset); } - return self.getLongKey(name) + return self.getLongKey(name, caseSensitive) } -func (self *NormalFieldMap) getLongKey(name string) int { +func (self *NormalFieldMap) getLongKey(name string, caseSensitive bool) int { for _, k := range self.longKeys { if len(k.key) != len(name) { continue; @@ -172,6 +178,10 @@ func (self *NormalFieldMap) getLongKey(name string) int { } } + if caseSensitive { + return -1 + } + lower := strings.ToLower(name) for _, k := range self.longKeys { if len(k.key) != len(name) { @@ -329,11 +339,13 @@ type FallbackFieldMap struct { } } - func (self *FallbackFieldMap) Get(name string) int { + func (self *FallbackFieldMap) Get(name string, caseSensitive bool) int { if i, ok := self.inner[name]; ok { return i - } else { + } else if !caseSensitive { return self.getCaseInsensitive(name) + } else { + return -1 } } diff --git a/native/lookup_small_key.c b/native/lookup_small_key.c index fcf41b455..07eff791a 100644 --- a/native/lookup_small_key.c +++ b/native/lookup_small_key.c @@ -130,6 +130,10 @@ long lookup_small_key(GoString* key, GoSlice* table, long lower_off) { } case_sensitve: + if (lower_off == -1) { + return -_NOT_FOUND; + } + offset = lower_off + *(uint32_t*)(meta + 1); p = table->buf + offset; to_lower(lower, (uint8_t*)(key->buf), 32);