diff --git a/decoder/assembler_amd64_go116.go b/decoder/assembler_amd64_go116.go index f889d861e..86d5a3d3f 100644 --- a/decoder/assembler_amd64_go116.go +++ b/decoder/assembler_amd64_go116.go @@ -319,6 +319,7 @@ var _OpFuncTab = [256]func(*_Assembler, *_Instr) { _OP_dismatch_err : (*_Assembler)._asm_OP_dismatch_err, _OP_go_skip : (*_Assembler)._asm_OP_go_skip, _OP_add : (*_Assembler)._asm_OP_add, + _OP_check_empty : (*_Assembler)._asm_OP_check_empty, } func (self *_Assembler) instr(v *_Instr) { @@ -1172,6 +1173,8 @@ var ( var ( _F_FieldMap_GetCaseInsensitive obj.Addr + _Empty_Slice = make([]byte, 0) + _Zero_Base = int64(uintptr(((*rt.GoSlice)(unsafe.Pointer(&_Empty_Slice))).Ptr)) ) const ( @@ -1642,6 +1645,22 @@ func (self *_Assembler) _asm_OP_slice_init(p *_Instr) { self.Emit("MOVQ" , _AX, jit.Ptr(_VP, 8)) // MOVQ AX, 8(VP) } +func (self *_Assembler) _asm_OP_check_empty(p *_Instr) { + rbracket := p.vb() + if rbracket == ']' { + self.check_eof(1) + self.Emit("LEAQ", jit.Ptr(_IC, 1), _AX) // LEAQ 1(IC), AX + self.Emit("CMPB", jit.Sib(_IP, _IC, 1, 0), jit.Imm(int64(rbracket))) // CMPB (IP)(IC), ']' + self.Sjmp("JNE" , "_not_empty_array_{n}") // JNE _not_empty_array_{n} + self.Emit("MOVQ", _AX, _IC) // MOVQ AX, IC + self.Emit("MOVQ", jit.Imm(_Zero_Base), jit.Ptr(_VP, 0)) // MOVQ $zerobase, (VP) + self.Xjmp("JMP" , p.vi()) // JMP {p.vi()} + self.Link("_not_empty_array_{n}") + } else { + panic("only implement check empty array here!") + } +} + func (self *_Assembler) _asm_OP_slice_append(p *_Instr) { self.Emit("MOVQ" , jit.Ptr(_VP, 8), _AX) // MOVQ 8(VP), AX self.Emit("CMPQ" , _AX, jit.Ptr(_VP, 16)) // CMPQ AX, 16(VP) diff --git a/decoder/assembler_amd64_go117.go b/decoder/assembler_amd64_go117.go index a952ad2bf..e25d6efc3 100644 --- a/decoder/assembler_amd64_go117.go +++ b/decoder/assembler_amd64_go117.go @@ -315,6 +315,7 @@ var _OpFuncTab = [256]func(*_Assembler, *_Instr) { _OP_dismatch_err : (*_Assembler)._asm_OP_dismatch_err, _OP_go_skip : (*_Assembler)._asm_OP_go_skip, _OP_add : (*_Assembler)._asm_OP_add, + _OP_check_empty : (*_Assembler)._asm_OP_check_empty, _OP_debug : (*_Assembler)._asm_OP_debug, } @@ -1165,6 +1166,8 @@ var ( var ( _F_FieldMap_GetCaseInsensitive obj.Addr + _Empty_Slice = make([]byte, 0) + _Zero_Base = int64(uintptr(((*rt.GoSlice)(unsafe.Pointer(&_Empty_Slice))).Ptr)) ) const ( @@ -1632,6 +1635,22 @@ func (self *_Assembler) _asm_OP_slice_init(p *_Instr) { self.Link("_done_{n}") // _done_{n} } +func (self *_Assembler) _asm_OP_check_empty(p *_Instr) { + rbracket := p.vb() + if rbracket == ']' { + self.check_eof(1) + self.Emit("LEAQ", jit.Ptr(_IC, 1), _AX) // LEAQ 1(IC), AX + self.Emit("CMPB", jit.Sib(_IP, _IC, 1, 0), jit.Imm(int64(rbracket))) // CMPB (IP)(IC), ']' + self.Sjmp("JNE" , "_not_empty_array_{n}") // JNE _not_empty_array_{n} + self.Emit("MOVQ", _AX, _IC) // MOVQ AX, IC + self.Emit("MOVQ", jit.Imm(_Zero_Base), jit.Ptr(_VP, 0)) // MOVQ $zerobase, (VP) + self.Xjmp("JMP" , p.vi()) // JMP {p.vi()} + self.Link("_not_empty_array_{n}") + } else { + panic("only implement check empty array here!") + } +} + func (self *_Assembler) _asm_OP_slice_append(p *_Instr) { self.Emit("MOVQ" , jit.Ptr(_VP, 8), _AX) // MOVQ 8(VP), AX self.Emit("CMPQ" , _AX, jit.Ptr(_VP, 16)) // CMPQ AX, 16(VP) diff --git a/decoder/compiler.go b/decoder/compiler.go index b6164338f..8f3905fca 100644 --- a/decoder/compiler.go +++ b/decoder/compiler.go @@ -98,6 +98,7 @@ const ( _OP_dismatch_err _OP_go_skip _OP_add + _OP_check_empty _OP_debug ) @@ -174,6 +175,9 @@ var _OpNames = [256]string { _OP_check_char_0 : "check_char_0", _OP_dismatch_err : "dismatch_err", _OP_add : "add", + _OP_go_skip : "go_skip", + _OP_check_empty : "check_empty", + _OP_debug : "debug", } func (self _Op) String() string { @@ -806,11 +810,11 @@ func (self *_Compiler) compileSliceList(p *_Program, sp int, vt reflect.Type) { } func (self *_Compiler) compileSliceBody(p *_Program, sp int, et reflect.Type) { - p.rtt(_OP_slice_init, et) - p.add(_OP_save) p.add(_OP_lspace) j := p.pc() - p.chr(_OP_check_char, ']') + p.chr(_OP_check_empty, ']') + p.rtt(_OP_slice_init, et) + p.add(_OP_save) p.rtt(_OP_slice_append, et) self.compileOne(p, sp + 1, et) p.add(_OP_load) @@ -823,9 +827,9 @@ func (self *_Compiler) compileSliceBody(p *_Program, sp int, et reflect.Type) { self.compileOne(p, sp + 1, et) p.add(_OP_load) p.int(_OP_goto, k0) - p.pin(j) p.pin(k1) p.add(_OP_drop) + p.pin(j) } func (self *_Compiler) compileString(p *_Program, vt reflect.Type) { diff --git a/decoder/pools.go b/decoder/pools.go index ab1e5f23c..06adc7fa1 100644 --- a/decoder/pools.go +++ b/decoder/pools.go @@ -26,7 +26,7 @@ import ( ) const ( - _MinSlice = 16 + _MinSlice = 2 _MaxStack = 4096 // 4k slots _MaxStackBytes = _MaxStack * _PtrBytes _MaxDigitNums = 800 // used in atof fallback algorithm