mirror of https://github.com/goccy/go-json.git
Optimize opcode
This commit is contained in:
parent
4f3b1262b2
commit
40544f1ea2
|
@ -54,18 +54,21 @@ func (e *Encoder) compileOp(typ *rtype) (*opcode, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) compilePtrOp(typ *rtype) (*opcode, error) {
|
func (e *Encoder) compilePtrOp(typ *rtype) (*opcode, error) {
|
||||||
elem := typ.Elem()
|
code, err := e.compileOp(typ.Elem())
|
||||||
code, err := e.compileOp(elem)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &opcode{
|
switch code.op {
|
||||||
opcodeHeader: &opcodeHeader{
|
case opStructFieldHead:
|
||||||
op: opPtr,
|
code.op = opStructFieldPtrHead
|
||||||
typ: typ,
|
case opStructFieldHeadInt:
|
||||||
next: code,
|
code.op = opStructFieldPtrHeadInt
|
||||||
},
|
case opStructFieldHeadString:
|
||||||
}, nil
|
code.op = opStructFieldPtrHeadString
|
||||||
|
default:
|
||||||
|
return newOpCode(opPtr, typ, code), nil
|
||||||
|
}
|
||||||
|
return code, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) compileIntOp(typ *rtype) (*opcode, error) {
|
func (e *Encoder) compileIntOp(typ *rtype) (*opcode, error) {
|
||||||
|
@ -132,22 +135,21 @@ func (e *Encoder) compileSliceOp(typ *rtype) (*opcode, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// header => firstElem => opcode => elem => end
|
// header => opcode => elem => end
|
||||||
// ^ |
|
// ^ |
|
||||||
// |________|
|
// |________|
|
||||||
|
|
||||||
header := &opcode{opcodeHeader: &opcodeHeader{op: opSliceHead}}
|
header := newSliceHeaderCode()
|
||||||
firstElem := &sliceElemCode{opcodeHeader: &opcodeHeader{op: opSliceElemFirst}}
|
|
||||||
elemCode := &sliceElemCode{opcodeHeader: &opcodeHeader{op: opSliceElem}, size: size}
|
elemCode := &sliceElemCode{opcodeHeader: &opcodeHeader{op: opSliceElem}, size: size}
|
||||||
end := &opcode{opcodeHeader: &opcodeHeader{op: opSliceEnd}}
|
end := newOpCode(opSliceEnd, nil, nil)
|
||||||
|
|
||||||
header.next = (*opcode)(unsafe.Pointer(firstElem))
|
header.elem = elemCode
|
||||||
firstElem.next = code
|
header.end = end
|
||||||
firstElem.elem = elemCode
|
header.next = code
|
||||||
code.beforeLastCode().next = (*opcode)(unsafe.Pointer(elemCode))
|
code.beforeLastCode().next = (*opcode)(unsafe.Pointer(elemCode))
|
||||||
elemCode.next = code
|
elemCode.next = code
|
||||||
elemCode.end = end
|
elemCode.end = end
|
||||||
end.next = &opcode{opcodeHeader: &opcodeHeader{op: opEnd}}
|
end.next = newEndOp()
|
||||||
return (*opcode)(unsafe.Pointer(header)), nil
|
return (*opcode)(unsafe.Pointer(header)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,9 +159,11 @@ func (e *Encoder) compileStructOp(typ *rtype) (*opcode, error) {
|
||||||
// |________|
|
// |________|
|
||||||
fieldNum := typ.NumField()
|
fieldNum := typ.NumField()
|
||||||
fieldIdx := 0
|
fieldIdx := 0
|
||||||
header := &opcode{opcodeHeader: &opcodeHeader{op: opStructHead}}
|
var (
|
||||||
code := header
|
head *structFieldCode
|
||||||
var prevField *structFieldCode
|
code *opcode
|
||||||
|
prevField *structFieldCode
|
||||||
|
)
|
||||||
for i := 0; i < fieldNum; i++ {
|
for i := 0; i < fieldNum; i++ {
|
||||||
field := typ.Field(i)
|
field := typ.Field(i)
|
||||||
if e.isIgnoredStructField(field) {
|
if e.isIgnoredStructField(field) {
|
||||||
|
@ -182,22 +186,22 @@ func (e *Encoder) compileStructOp(typ *rtype) (*opcode, error) {
|
||||||
if fieldIdx == 0 {
|
if fieldIdx == 0 {
|
||||||
fieldCode := &structFieldCode{
|
fieldCode := &structFieldCode{
|
||||||
opcodeHeader: &opcodeHeader{
|
opcodeHeader: &opcodeHeader{
|
||||||
op: opStructFieldFirst,
|
op: opStructFieldHead,
|
||||||
typ: fieldType,
|
typ: fieldType,
|
||||||
next: valueCode,
|
next: valueCode,
|
||||||
},
|
},
|
||||||
key: key,
|
key: key,
|
||||||
offset: field.Offset,
|
offset: field.Offset,
|
||||||
}
|
}
|
||||||
code.next = (*opcode)(unsafe.Pointer(fieldCode))
|
head = fieldCode
|
||||||
|
code = (*opcode)(unsafe.Pointer(fieldCode))
|
||||||
prevField = fieldCode
|
prevField = fieldCode
|
||||||
if valueCode.op == opInt {
|
switch valueCode.op {
|
||||||
fieldCode.op = opStructFieldFirstInt
|
case opInt:
|
||||||
code = (*opcode)(unsafe.Pointer(fieldCode))
|
fieldCode.op = opStructFieldHeadInt
|
||||||
} else if valueCode.op == opString {
|
case opString:
|
||||||
fieldCode.op = opStructFieldFirstString
|
fieldCode.op = opStructFieldHeadString
|
||||||
code = (*opcode)(unsafe.Pointer(fieldCode))
|
default:
|
||||||
} else {
|
|
||||||
code = valueCode.beforeLastCode()
|
code = valueCode.beforeLastCode()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -213,21 +217,23 @@ func (e *Encoder) compileStructOp(typ *rtype) (*opcode, error) {
|
||||||
code.next = (*opcode)(unsafe.Pointer(fieldCode))
|
code.next = (*opcode)(unsafe.Pointer(fieldCode))
|
||||||
prevField.nextField = (*opcode)(unsafe.Pointer(fieldCode))
|
prevField.nextField = (*opcode)(unsafe.Pointer(fieldCode))
|
||||||
prevField = fieldCode
|
prevField = fieldCode
|
||||||
if valueCode.op == opInt {
|
switch valueCode.op {
|
||||||
|
case opInt:
|
||||||
fieldCode.op = opStructFieldInt
|
fieldCode.op = opStructFieldInt
|
||||||
code = (*opcode)(unsafe.Pointer(fieldCode))
|
code = (*opcode)(unsafe.Pointer(fieldCode))
|
||||||
} else if valueCode.op == opString {
|
case opString:
|
||||||
fieldCode.op = opStructFieldString
|
fieldCode.op = opStructFieldString
|
||||||
code = (*opcode)(unsafe.Pointer(fieldCode))
|
code = (*opcode)(unsafe.Pointer(fieldCode))
|
||||||
} else {
|
default:
|
||||||
code = valueCode.beforeLastCode()
|
code = valueCode.beforeLastCode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
prevField.nextField = &opcode{opcodeHeader: &opcodeHeader{op: opEnd}}
|
prevField.nextField = newEndOp()
|
||||||
fieldIdx++
|
fieldIdx++
|
||||||
}
|
}
|
||||||
structEndCode := &opcode{opcodeHeader: &opcodeHeader{op: opStructEnd}}
|
structEndCode := newOpCode(opStructEnd, nil, nil)
|
||||||
|
head.end = structEndCode
|
||||||
code.next = structEndCode
|
code.next = structEndCode
|
||||||
structEndCode.next = &opcode{opcodeHeader: &opcodeHeader{op: opEnd}}
|
structEndCode.next = newEndOp()
|
||||||
return header, nil
|
return (*opcode)(unsafe.Pointer(head)), nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,15 +27,16 @@ const (
|
||||||
opBool
|
opBool
|
||||||
opPtr
|
opPtr
|
||||||
opSliceHead
|
opSliceHead
|
||||||
opSliceElemFirst
|
|
||||||
opSliceElem
|
opSliceElem
|
||||||
opSliceEnd
|
opSliceEnd
|
||||||
opStructHead
|
opStructFieldHead
|
||||||
opStructFieldFirst
|
opStructFieldHeadInt
|
||||||
|
opStructFieldHeadString
|
||||||
|
opStructFieldPtrHead
|
||||||
|
opStructFieldPtrHeadInt
|
||||||
|
opStructFieldPtrHeadString
|
||||||
opStructField
|
opStructField
|
||||||
opStructFieldFirstInt
|
|
||||||
opStructFieldInt
|
opStructFieldInt
|
||||||
opStructFieldFirstString
|
|
||||||
opStructFieldString
|
opStructFieldString
|
||||||
opStructEnd
|
opStructEnd
|
||||||
)
|
)
|
||||||
|
@ -76,24 +77,26 @@ func (t opType) String() string {
|
||||||
return "PTR"
|
return "PTR"
|
||||||
case opSliceHead:
|
case opSliceHead:
|
||||||
return "SLICE_HEAD"
|
return "SLICE_HEAD"
|
||||||
case opSliceElemFirst:
|
|
||||||
return "SLICE_ELEM_FIRST"
|
|
||||||
case opSliceElem:
|
case opSliceElem:
|
||||||
return "SLICE_ELEM"
|
return "SLICE_ELEM"
|
||||||
case opSliceEnd:
|
case opSliceEnd:
|
||||||
return "SLICE_END"
|
return "SLICE_END"
|
||||||
case opStructHead:
|
case opStructFieldHead:
|
||||||
return "STRUCT_HEAD"
|
return "STRUCT_FIELD_HEAD"
|
||||||
case opStructFieldFirst:
|
case opStructFieldHeadInt:
|
||||||
return "STRUCT_FIELD_FIRST"
|
return "STRUCT_FIELD_HEAD_INT"
|
||||||
|
case opStructFieldHeadString:
|
||||||
|
return "STRUCT_FIELD_HEAD_STRING"
|
||||||
|
case opStructFieldPtrHead:
|
||||||
|
return "STRUCT_FIELD_PTR_HEAD"
|
||||||
|
case opStructFieldPtrHeadInt:
|
||||||
|
return "STRUCT_FIELD_PTR_HEAD_INT"
|
||||||
|
case opStructFieldPtrHeadString:
|
||||||
|
return "STRUCT_FIELD_PTR_HEAD_STRING"
|
||||||
case opStructField:
|
case opStructField:
|
||||||
return "STRUCT_FIELD"
|
return "STRUCT_FIELD"
|
||||||
case opStructFieldFirstInt:
|
|
||||||
return "STRUCT_FIELD_FIRST_INT"
|
|
||||||
case opStructFieldInt:
|
case opStructFieldInt:
|
||||||
return "STRUCT_FIELD_INT"
|
return "STRUCT_FIELD_INT"
|
||||||
case opStructFieldFirstString:
|
|
||||||
return "STRUCT_FIELD_FIRST_STRING"
|
|
||||||
case opStructFieldString:
|
case opStructFieldString:
|
||||||
return "STRUCT_FIELD_STRING"
|
return "STRUCT_FIELD_STRING"
|
||||||
case opStructEnd:
|
case opStructEnd:
|
||||||
|
@ -157,18 +160,32 @@ func (c *opcode) dump() string {
|
||||||
return strings.Join(codes, "\n")
|
return strings.Join(codes, "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *opcode) toSliceHeaderCode() *sliceHeaderCode {
|
||||||
|
return (*sliceHeaderCode)(unsafe.Pointer(c))
|
||||||
|
}
|
||||||
|
|
||||||
func (c *opcode) toSliceElemCode() *sliceElemCode {
|
func (c *opcode) toSliceElemCode() *sliceElemCode {
|
||||||
return (*sliceElemCode)(unsafe.Pointer(c))
|
return (*sliceElemCode)(unsafe.Pointer(c))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *opcode) toStructHeaderCode() *structHeaderCode {
|
|
||||||
return (*structHeaderCode)(unsafe.Pointer(c))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *opcode) toStructFieldCode() *structFieldCode {
|
func (c *opcode) toStructFieldCode() *structFieldCode {
|
||||||
return (*structFieldCode)(unsafe.Pointer(c))
|
return (*structFieldCode)(unsafe.Pointer(c))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type sliceHeaderCode struct {
|
||||||
|
*opcodeHeader
|
||||||
|
elem *sliceElemCode
|
||||||
|
end *opcode
|
||||||
|
}
|
||||||
|
|
||||||
|
func newSliceHeaderCode() *sliceHeaderCode {
|
||||||
|
return &sliceHeaderCode{
|
||||||
|
opcodeHeader: &opcodeHeader{
|
||||||
|
op: opSliceHead,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type sliceElemCode struct {
|
type sliceElemCode struct {
|
||||||
*opcodeHeader
|
*opcodeHeader
|
||||||
idx uintptr
|
idx uintptr
|
||||||
|
@ -185,14 +202,10 @@ func (c *sliceElemCode) set(header *reflect.SliceHeader) {
|
||||||
c.data = header.Data
|
c.data = header.Data
|
||||||
}
|
}
|
||||||
|
|
||||||
type structHeaderCode struct {
|
|
||||||
*opcodeHeader
|
|
||||||
end *opcode
|
|
||||||
}
|
|
||||||
|
|
||||||
type structFieldCode struct {
|
type structFieldCode struct {
|
||||||
*opcodeHeader
|
*opcodeHeader
|
||||||
key string
|
key string
|
||||||
offset uintptr
|
offset uintptr
|
||||||
nextField *opcode
|
nextField *opcode
|
||||||
|
end *opcode
|
||||||
}
|
}
|
||||||
|
|
92
encode_vm.go
92
encode_vm.go
|
@ -59,24 +59,22 @@ func (e *Encoder) run(code *opcode) error {
|
||||||
code = code.next
|
code = code.next
|
||||||
case opSliceHead:
|
case opSliceHead:
|
||||||
p := code.ptr
|
p := code.ptr
|
||||||
|
headerCode := code.toSliceHeaderCode()
|
||||||
if p == 0 {
|
if p == 0 {
|
||||||
e.encodeString("null")
|
e.encodeString("null")
|
||||||
code = code.next.toSliceElemCode().end
|
code = headerCode.end.next
|
||||||
} else {
|
} else {
|
||||||
e.encodeByte('[')
|
e.encodeByte('[')
|
||||||
header := (*reflect.SliceHeader)(unsafe.Pointer(p))
|
header := (*reflect.SliceHeader)(unsafe.Pointer(p))
|
||||||
firstElem := code.next.toSliceElemCode()
|
headerCode := code.toSliceHeaderCode()
|
||||||
firstElem.set(header)
|
headerCode.elem.set(header)
|
||||||
firstElem.elem.set(header)
|
if header.Len > 0 {
|
||||||
code = code.next
|
code = code.next
|
||||||
}
|
code.ptr = header.Data
|
||||||
case opSliceElemFirst:
|
|
||||||
c := code.toSliceElemCode()
|
|
||||||
if c.len > 0 {
|
|
||||||
code = code.next
|
|
||||||
code.ptr = c.data
|
|
||||||
} else {
|
} else {
|
||||||
code = c.end
|
e.encodeByte(']')
|
||||||
|
code = headerCode.end.next
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case opSliceElem:
|
case opSliceElem:
|
||||||
c := code.toSliceElemCode()
|
c := code.toSliceElemCode()
|
||||||
|
@ -86,39 +84,57 @@ func (e *Encoder) run(code *opcode) error {
|
||||||
code = code.next
|
code = code.next
|
||||||
code.ptr = c.data + c.idx*c.size
|
code.ptr = c.data + c.idx*c.size
|
||||||
} else {
|
} else {
|
||||||
code = c.end
|
|
||||||
}
|
|
||||||
case opSliceEnd:
|
|
||||||
e.encodeByte(']')
|
e.encodeByte(']')
|
||||||
code = code.next
|
code = c.end.next
|
||||||
case opStructHead:
|
}
|
||||||
ptr := code.ptr
|
case opStructFieldPtrHead:
|
||||||
|
code.ptr = e.ptrToPtr(code.ptr)
|
||||||
|
fallthrough
|
||||||
|
case opStructFieldHead:
|
||||||
|
field := code.toStructFieldCode()
|
||||||
|
ptr := field.ptr
|
||||||
if ptr == 0 {
|
if ptr == 0 {
|
||||||
e.encodeString("null")
|
e.encodeString("null")
|
||||||
code = code.toStructHeaderCode().end
|
code = field.end
|
||||||
} else {
|
} else {
|
||||||
e.encodeByte('{')
|
e.encodeByte('{')
|
||||||
code = code.next
|
e.encodeString(field.key)
|
||||||
code.ptr = ptr
|
code = field.next
|
||||||
|
code.ptr = field.ptr + field.offset
|
||||||
|
field.nextField.ptr = field.ptr
|
||||||
|
}
|
||||||
|
case opStructFieldPtrHeadInt:
|
||||||
|
code.ptr = e.ptrToPtr(code.ptr)
|
||||||
|
fallthrough
|
||||||
|
case opStructFieldHeadInt:
|
||||||
|
field := code.toStructFieldCode()
|
||||||
|
ptr := field.ptr
|
||||||
|
if ptr == 0 {
|
||||||
|
e.encodeString("null")
|
||||||
|
code = field.end
|
||||||
|
} else {
|
||||||
|
e.encodeByte('{')
|
||||||
|
e.encodeString(field.key)
|
||||||
|
e.encodeInt(e.ptrToInt(field.ptr + field.offset))
|
||||||
|
field.nextField.ptr = field.ptr
|
||||||
|
code = field.next
|
||||||
|
}
|
||||||
|
case opStructFieldPtrHeadString:
|
||||||
|
code.ptr = e.ptrToPtr(code.ptr)
|
||||||
|
fallthrough
|
||||||
|
case opStructFieldHeadString:
|
||||||
|
field := code.toStructFieldCode()
|
||||||
|
ptr := field.ptr
|
||||||
|
if ptr == 0 {
|
||||||
|
e.encodeString("null")
|
||||||
|
code = field.end
|
||||||
|
} else {
|
||||||
|
e.encodeByte('{')
|
||||||
|
e.encodeString(field.key)
|
||||||
|
e.encodeEscapedString(e.ptrToString(field.ptr + field.offset))
|
||||||
|
field.nextField.ptr = field.ptr
|
||||||
|
code = field.next
|
||||||
}
|
}
|
||||||
case opStructFieldFirst:
|
|
||||||
c := code.toStructFieldCode()
|
|
||||||
e.encodeString(c.key)
|
|
||||||
code = code.next
|
|
||||||
code.ptr = c.ptr + c.offset
|
|
||||||
c.nextField.ptr = c.ptr
|
|
||||||
case opStructFieldFirstInt:
|
|
||||||
c := code.toStructFieldCode()
|
|
||||||
e.encodeString(c.key)
|
|
||||||
c.nextField.ptr = c.ptr
|
|
||||||
e.encodeInt(e.ptrToInt(c.ptr + c.offset))
|
|
||||||
code = code.next
|
|
||||||
case opStructFieldFirstString:
|
|
||||||
c := code.toStructFieldCode()
|
|
||||||
e.encodeString(c.key)
|
|
||||||
c.nextField.ptr = c.ptr
|
|
||||||
e.encodeEscapedString(e.ptrToString(c.ptr + c.offset))
|
|
||||||
code = code.next
|
|
||||||
case opStructField:
|
case opStructField:
|
||||||
e.encodeByte(',')
|
e.encodeByte(',')
|
||||||
c := code.toStructFieldCode()
|
c := code.toStructFieldCode()
|
||||||
|
|
Loading…
Reference in New Issue