Ver Fonte

use hash for field dispatching

Tao Wen há 8 anos atrás
pai
commit
da7ed7809b
4 ficheiros alterados com 853 adições e 115 exclusões
  1. 53 0
      feature_iter_int.go
  2. 38 0
      feature_iter_object.go
  3. 737 115
      feature_reflect_object.go
  4. 25 0
      jsoniter_reflect_struct_test.go

+ 53 - 0
feature_iter_int.go

@@ -122,6 +122,59 @@ func (iter *Iterator) readUint32(c byte) (ret uint32) {
 		return
 	}
 	value := uint32(ind)
+	if iter.tail - iter.head > 10 {
+		i := iter.head
+		ind2 := intDigits[iter.buf[i]]
+		if ind2 == invalidCharForNumber {
+			iter.head = i
+			return value
+		}
+		i++
+		ind3 := intDigits[iter.buf[i]]
+		if ind3 == invalidCharForNumber {
+			iter.head = i
+			return value * 10 + uint32(ind2)
+		}
+		//iter.head = i + 1
+		//value = value * 100 + uint32(ind2) * 10 + uint32(ind3)
+		i++
+		ind4 := intDigits[iter.buf[i]]
+		if ind4 == invalidCharForNumber {
+			iter.head = i
+			return value * 100 + uint32(ind2) * 10 + uint32(ind3)
+		}
+		i++
+		ind5 := intDigits[iter.buf[i]]
+		if ind5 == invalidCharForNumber {
+			iter.head = i
+			return value * 1000 + uint32(ind2) * 100 + uint32(ind3) * 10 + uint32(ind4)
+		}
+		i++
+		ind6 := intDigits[iter.buf[i]]
+		if ind6 == invalidCharForNumber {
+			iter.head = i
+			return value * 10000 + uint32(ind2) * 1000 + uint32(ind3) * 100 + uint32(ind4) * 10 + uint32(ind5)
+		}
+		i++
+		ind7 := intDigits[iter.buf[i]]
+		if ind7 == invalidCharForNumber {
+			iter.head = i
+			return value * 100000 + uint32(ind2) * 10000 + uint32(ind3) * 1000 + uint32(ind4) * 100 + uint32(ind5) * 10 + uint32(ind6)
+		}
+		i++
+		ind8 := intDigits[iter.buf[i]]
+		if ind8 == invalidCharForNumber {
+			iter.head = i
+			return value * 1000000 + uint32(ind2) * 100000 + uint32(ind3) * 10000 + uint32(ind4) * 1000 + uint32(ind5) * 100 + uint32(ind6) * 10 + uint32(ind7)
+		}
+		i++
+		ind9 := intDigits[iter.buf[i]]
+		value = value * 10000000 + uint32(ind2) * 1000000 + uint32(ind3) * 100000 + uint32(ind4) * 10000 + uint32(ind5) * 1000 + uint32(ind6) * 100 + uint32(ind7) * 10 + uint32(ind8)
+		iter.head = i
+		if ind9 == invalidCharForNumber {
+			return value
+		}
+	}
 	for {
 		for i := iter.head; i < iter.tail; i++ {
 			ind = intDigits[iter.buf[i]]

+ 38 - 0
feature_iter_object.go

@@ -27,6 +27,44 @@ func (iter *Iterator) ReadObject() (ret string) {
 	}
 }
 
+func (iter *Iterator) readFieldHash() int32 {
+	hash := 0x811c9dc5
+	c := iter.nextToken()
+	if c == '"' {
+		for {
+			for i := iter.head; i < iter.tail; i++ {
+				// require ascii string and no escape
+				b := iter.buf[i]
+				if b == '"' {
+					iter.head = i+1
+					c = iter.nextToken()
+					if c != ':' {
+						iter.reportError("readFieldHash", `expect :, but found ` + string([]byte{c}))
+					}
+					return int32(hash)
+				}
+				hash ^= int(b)
+				hash *= 0x1000193
+			}
+			if !iter.loadMore() {
+				iter.reportError("readFieldHash", `incomplete field name`)
+				return 0
+			}
+		}
+	}
+	iter.reportError("readFieldHash", `expect ", but found ` + string([]byte{c}))
+	return 0
+}
+
+func calcHash(str string) int32 {
+	hash := 0x811c9dc5
+	for _, b := range str {
+		hash ^= int(b)
+		hash *= 0x1000193
+	}
+	return int32(hash)
+}
+
 func (iter *Iterator) ReadObjectCB(callback func(*Iterator, string) bool) bool {
 	c := iter.nextToken()
 	if c == '{' {

+ 737 - 115
feature_reflect_object.go

@@ -99,76 +99,425 @@ func decoderOfStruct(typ reflect.Type) (Decoder, error) {
 			fields[fieldName] = &structFieldDecoder{&field, decoder}
 		}
 	}
+	return createStructDecoder(typ, fields)
+}
+
+func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder) (Decoder, error) {
+	knownHash := map[int32]struct{}{
+		0: struct{}{},
+	}
 	switch len(fields) {
 	case 0:
 		return &skipDecoder{typ}, nil
 	case 1:
 		for fieldName, fieldDecoder := range fields {
-			return &oneFieldStructDecoder{typ, fieldName, fieldDecoder}, nil
+			fieldHash := calcHash(fieldName)
+			_, known := knownHash[fieldHash]
+			if known {
+				return &generalStructDecoder{typ, fields}, nil
+			} else {
+				knownHash[fieldHash] = struct{}{}
+			}
+			return &oneFieldStructDecoder{typ, fieldHash, fieldDecoder}, nil
 		}
 	case 2:
-		var fieldName1 string
-		var fieldName2 string
+		var fieldHash1 int32
+		var fieldHash2 int32
 		var fieldDecoder1 *structFieldDecoder
 		var fieldDecoder2 *structFieldDecoder
 		for fieldName, fieldDecoder := range fields {
-			if fieldName1 == "" {
-				fieldName1 = fieldName
+			fieldHash := calcHash(fieldName)
+			_, known := knownHash[fieldHash]
+			if known {
+				return &generalStructDecoder{typ, fields}, nil
+			} else {
+				knownHash[fieldHash] = struct{}{}
+			}
+			if fieldHash1 == 0 {
+				fieldHash1 = fieldHash
 				fieldDecoder1 = fieldDecoder
 			} else {
-				fieldName2 = fieldName
+				fieldHash2 = fieldHash
 				fieldDecoder2 = fieldDecoder
 			}
 		}
-		return &twoFieldsStructDecoder{typ, fieldName1, fieldDecoder1, fieldName2, fieldDecoder2}, nil
+		return &twoFieldsStructDecoder{typ, fieldHash1, fieldDecoder1, fieldHash2, fieldDecoder2}, nil
 	case 3:
-		var fieldName1 string
-		var fieldName2 string
-		var fieldName3 string
+		var fieldName1 int32
+		var fieldName2 int32
+		var fieldName3 int32
 		var fieldDecoder1 *structFieldDecoder
 		var fieldDecoder2 *structFieldDecoder
 		var fieldDecoder3 *structFieldDecoder
 		for fieldName, fieldDecoder := range fields {
-			if fieldName1 == "" {
-				fieldName1 = fieldName
+			fieldHash := calcHash(fieldName)
+			_, known := knownHash[fieldHash]
+			if known {
+				return &generalStructDecoder{typ, fields}, nil
+			} else {
+				knownHash[fieldHash] = struct{}{}
+			}
+			if fieldName1 == 0 {
+				fieldName1 = fieldHash
 				fieldDecoder1 = fieldDecoder
-			} else if fieldName2 == "" {
-				fieldName2 = fieldName
+			} else if fieldName2 == 0 {
+				fieldName2 = fieldHash
 				fieldDecoder2 = fieldDecoder
 			} else {
-				fieldName3 = fieldName
+				fieldName3 = fieldHash
 				fieldDecoder3 = fieldDecoder
 			}
 		}
 		return &threeFieldsStructDecoder{typ,
 			fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3}, nil
 	case 4:
-		var fieldName1 string
-		var fieldName2 string
-		var fieldName3 string
-		var fieldName4 string
+		var fieldName1 int32
+		var fieldName2 int32
+		var fieldName3 int32
+		var fieldName4 int32
 		var fieldDecoder1 *structFieldDecoder
 		var fieldDecoder2 *structFieldDecoder
 		var fieldDecoder3 *structFieldDecoder
 		var fieldDecoder4 *structFieldDecoder
 		for fieldName, fieldDecoder := range fields {
-			if fieldName1 == "" {
-				fieldName1 = fieldName
+			fieldHash := calcHash(fieldName)
+			_, known := knownHash[fieldHash]
+			if known {
+				return &generalStructDecoder{typ, fields}, nil
+			} else {
+				knownHash[fieldHash] = struct{}{}
+			}
+			if fieldName1 == 0 {
+				fieldName1 = fieldHash
 				fieldDecoder1 = fieldDecoder
-			} else if fieldName2 == "" {
-				fieldName2 = fieldName
+			} else if fieldName2 == 0 {
+				fieldName2 = fieldHash
 				fieldDecoder2 = fieldDecoder
-			} else if fieldName3 == "" {
-				fieldName3 = fieldName
+			} else if fieldName3 == 0 {
+				fieldName3 = fieldHash
 				fieldDecoder3 = fieldDecoder
 			} else {
-				fieldName4 = fieldName
+				fieldName4 = fieldHash
 				fieldDecoder4 = fieldDecoder
 			}
 		}
 		return &fourFieldsStructDecoder{typ,
 			fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
 			fieldName4, fieldDecoder4}, nil
+	case 5:
+		var fieldName1 int32
+		var fieldName2 int32
+		var fieldName3 int32
+		var fieldName4 int32
+		var fieldName5 int32
+		var fieldDecoder1 *structFieldDecoder
+		var fieldDecoder2 *structFieldDecoder
+		var fieldDecoder3 *structFieldDecoder
+		var fieldDecoder4 *structFieldDecoder
+		var fieldDecoder5 *structFieldDecoder
+		for fieldName, fieldDecoder := range fields {
+			fieldHash := calcHash(fieldName)
+			_, known := knownHash[fieldHash]
+			if known {
+				return &generalStructDecoder{typ, fields}, nil
+			} else {
+				knownHash[fieldHash] = struct{}{}
+			}
+			if fieldName1 == 0 {
+				fieldName1 = fieldHash
+				fieldDecoder1 = fieldDecoder
+			} else if fieldName2 == 0 {
+				fieldName2 = fieldHash
+				fieldDecoder2 = fieldDecoder
+			} else if fieldName3 == 0 {
+				fieldName3 = fieldHash
+				fieldDecoder3 = fieldDecoder
+			} else if fieldName4 == 0 {
+				fieldName4 = fieldHash
+				fieldDecoder4 = fieldDecoder
+			} else {
+				fieldName5 = fieldHash
+				fieldDecoder5 = fieldDecoder
+			}
+		}
+		return &fiveFieldsStructDecoder{typ,
+			fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
+			fieldName4, fieldDecoder4, fieldName5, fieldDecoder5}, nil
+	case 6:
+		var fieldName1 int32
+		var fieldName2 int32
+		var fieldName3 int32
+		var fieldName4 int32
+		var fieldName5 int32
+		var fieldName6 int32
+		var fieldDecoder1 *structFieldDecoder
+		var fieldDecoder2 *structFieldDecoder
+		var fieldDecoder3 *structFieldDecoder
+		var fieldDecoder4 *structFieldDecoder
+		var fieldDecoder5 *structFieldDecoder
+		var fieldDecoder6 *structFieldDecoder
+		for fieldName, fieldDecoder := range fields {
+			fieldHash := calcHash(fieldName)
+			_, known := knownHash[fieldHash]
+			if known {
+				return &generalStructDecoder{typ, fields}, nil
+			} else {
+				knownHash[fieldHash] = struct{}{}
+			}
+			if fieldName1 == 0 {
+				fieldName1 = fieldHash
+				fieldDecoder1 = fieldDecoder
+			} else if fieldName2 == 0 {
+				fieldName2 = fieldHash
+				fieldDecoder2 = fieldDecoder
+			} else if fieldName3 == 0 {
+				fieldName3 = fieldHash
+				fieldDecoder3 = fieldDecoder
+			} else if fieldName4 == 0 {
+				fieldName4 = fieldHash
+				fieldDecoder4 = fieldDecoder
+			} else if fieldName5 == 0 {
+				fieldName5 = fieldHash
+				fieldDecoder5 = fieldDecoder
+			} else {
+				fieldName6 = fieldHash
+				fieldDecoder6 = fieldDecoder
+			}
+		}
+		return &sixFieldsStructDecoder{typ,
+			fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
+			fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6}, nil
+	case 7:
+		var fieldName1 int32
+		var fieldName2 int32
+		var fieldName3 int32
+		var fieldName4 int32
+		var fieldName5 int32
+		var fieldName6 int32
+		var fieldName7 int32
+		var fieldDecoder1 *structFieldDecoder
+		var fieldDecoder2 *structFieldDecoder
+		var fieldDecoder3 *structFieldDecoder
+		var fieldDecoder4 *structFieldDecoder
+		var fieldDecoder5 *structFieldDecoder
+		var fieldDecoder6 *structFieldDecoder
+		var fieldDecoder7 *structFieldDecoder
+		for fieldName, fieldDecoder := range fields {
+			fieldHash := calcHash(fieldName)
+			_, known := knownHash[fieldHash]
+			if known {
+				return &generalStructDecoder{typ, fields}, nil
+			} else {
+				knownHash[fieldHash] = struct{}{}
+			}
+			if fieldName1 == 0 {
+				fieldName1 = fieldHash
+				fieldDecoder1 = fieldDecoder
+			} else if fieldName2 == 0 {
+				fieldName2 = fieldHash
+				fieldDecoder2 = fieldDecoder
+			} else if fieldName3 == 0 {
+				fieldName3 = fieldHash
+				fieldDecoder3 = fieldDecoder
+			} else if fieldName4 == 0 {
+				fieldName4 = fieldHash
+				fieldDecoder4 = fieldDecoder
+			} else if fieldName5 == 0 {
+				fieldName5 = fieldHash
+				fieldDecoder5 = fieldDecoder
+			} else if fieldName6 == 0 {
+				fieldName6 = fieldHash
+				fieldDecoder6 = fieldDecoder
+			} else {
+				fieldName7 = fieldHash
+				fieldDecoder7 = fieldDecoder
+			}
+		}
+		return &sevenFieldsStructDecoder{typ,
+			fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
+			fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
+			fieldName7, fieldDecoder7}, nil
+	case 8:
+		var fieldName1 int32
+		var fieldName2 int32
+		var fieldName3 int32
+		var fieldName4 int32
+		var fieldName5 int32
+		var fieldName6 int32
+		var fieldName7 int32
+		var fieldName8 int32
+		var fieldDecoder1 *structFieldDecoder
+		var fieldDecoder2 *structFieldDecoder
+		var fieldDecoder3 *structFieldDecoder
+		var fieldDecoder4 *structFieldDecoder
+		var fieldDecoder5 *structFieldDecoder
+		var fieldDecoder6 *structFieldDecoder
+		var fieldDecoder7 *structFieldDecoder
+		var fieldDecoder8 *structFieldDecoder
+		for fieldName, fieldDecoder := range fields {
+			fieldHash := calcHash(fieldName)
+			_, known := knownHash[fieldHash]
+			if known {
+				return &generalStructDecoder{typ, fields}, nil
+			} else {
+				knownHash[fieldHash] = struct{}{}
+			}
+			if fieldName1 == 0 {
+				fieldName1 = fieldHash
+				fieldDecoder1 = fieldDecoder
+			} else if fieldName2 == 0 {
+				fieldName2 = fieldHash
+				fieldDecoder2 = fieldDecoder
+			} else if fieldName3 == 0 {
+				fieldName3 = fieldHash
+				fieldDecoder3 = fieldDecoder
+			} else if fieldName4 == 0 {
+				fieldName4 = fieldHash
+				fieldDecoder4 = fieldDecoder
+			} else if fieldName5 == 0 {
+				fieldName5 = fieldHash
+				fieldDecoder5 = fieldDecoder
+			} else if fieldName6 == 0 {
+				fieldName6 = fieldHash
+				fieldDecoder6 = fieldDecoder
+			} else if fieldName7 == 0 {
+				fieldName7 = fieldHash
+				fieldDecoder7 = fieldDecoder
+			} else {
+				fieldName8 = fieldHash
+				fieldDecoder8 = fieldDecoder
+			}
+		}
+		return &eightFieldsStructDecoder{typ,
+			fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
+			fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
+			fieldName7, fieldDecoder7, fieldName8, fieldDecoder8}, nil
+	case 9:
+		var fieldName1 int32
+		var fieldName2 int32
+		var fieldName3 int32
+		var fieldName4 int32
+		var fieldName5 int32
+		var fieldName6 int32
+		var fieldName7 int32
+		var fieldName8 int32
+		var fieldName9 int32
+		var fieldDecoder1 *structFieldDecoder
+		var fieldDecoder2 *structFieldDecoder
+		var fieldDecoder3 *structFieldDecoder
+		var fieldDecoder4 *structFieldDecoder
+		var fieldDecoder5 *structFieldDecoder
+		var fieldDecoder6 *structFieldDecoder
+		var fieldDecoder7 *structFieldDecoder
+		var fieldDecoder8 *structFieldDecoder
+		var fieldDecoder9 *structFieldDecoder
+		for fieldName, fieldDecoder := range fields {
+			fieldHash := calcHash(fieldName)
+			_, known := knownHash[fieldHash]
+			if known {
+				return &generalStructDecoder{typ, fields}, nil
+			} else {
+				knownHash[fieldHash] = struct{}{}
+			}
+			if fieldName1 == 0 {
+				fieldName1 = fieldHash
+				fieldDecoder1 = fieldDecoder
+			} else if fieldName2 == 0 {
+				fieldName2 = fieldHash
+				fieldDecoder2 = fieldDecoder
+			} else if fieldName3 == 0 {
+				fieldName3 = fieldHash
+				fieldDecoder3 = fieldDecoder
+			} else if fieldName4 == 0 {
+				fieldName4 = fieldHash
+				fieldDecoder4 = fieldDecoder
+			} else if fieldName5 == 0 {
+				fieldName5 = fieldHash
+				fieldDecoder5 = fieldDecoder
+			} else if fieldName6 == 0 {
+				fieldName6 = fieldHash
+				fieldDecoder6 = fieldDecoder
+			} else if fieldName7 == 0 {
+				fieldName7 = fieldHash
+				fieldDecoder7 = fieldDecoder
+			} else if fieldName8 == 0 {
+				fieldName8 = fieldHash
+				fieldDecoder8 = fieldDecoder
+			} else {
+				fieldName9 = fieldHash
+				fieldDecoder9 = fieldDecoder
+			}
+		}
+		return &nineFieldsStructDecoder{typ,
+			fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
+			fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
+			fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9}, nil
+	case 10:
+		var fieldName1 int32
+		var fieldName2 int32
+		var fieldName3 int32
+		var fieldName4 int32
+		var fieldName5 int32
+		var fieldName6 int32
+		var fieldName7 int32
+		var fieldName8 int32
+		var fieldName9 int32
+		var fieldName10 int32
+		var fieldDecoder1 *structFieldDecoder
+		var fieldDecoder2 *structFieldDecoder
+		var fieldDecoder3 *structFieldDecoder
+		var fieldDecoder4 *structFieldDecoder
+		var fieldDecoder5 *structFieldDecoder
+		var fieldDecoder6 *structFieldDecoder
+		var fieldDecoder7 *structFieldDecoder
+		var fieldDecoder8 *structFieldDecoder
+		var fieldDecoder9 *structFieldDecoder
+		var fieldDecoder10 *structFieldDecoder
+		for fieldName, fieldDecoder := range fields {
+			fieldHash := calcHash(fieldName)
+			_, known := knownHash[fieldHash]
+			if known {
+				return &generalStructDecoder{typ, fields}, nil
+			} else {
+				knownHash[fieldHash] = struct{}{}
+			}
+			if fieldName1 == 0 {
+				fieldName1 = fieldHash
+				fieldDecoder1 = fieldDecoder
+			} else if fieldName2 == 0 {
+				fieldName2 = fieldHash
+				fieldDecoder2 = fieldDecoder
+			} else if fieldName3 == 0 {
+				fieldName3 = fieldHash
+				fieldDecoder3 = fieldDecoder
+			} else if fieldName4 == 0 {
+				fieldName4 = fieldHash
+				fieldDecoder4 = fieldDecoder
+			} else if fieldName5 == 0 {
+				fieldName5 = fieldHash
+				fieldDecoder5 = fieldDecoder
+			} else if fieldName6 == 0 {
+				fieldName6 = fieldHash
+				fieldDecoder6 = fieldDecoder
+			} else if fieldName7 == 0 {
+				fieldName7 = fieldHash
+				fieldDecoder7 = fieldDecoder
+			} else if fieldName8 == 0 {
+				fieldName8 = fieldHash
+				fieldDecoder8 = fieldDecoder
+			} else if fieldName9 == 0 {
+				fieldName9 = fieldHash
+				fieldDecoder9 = fieldDecoder
+			} else {
+				fieldName10 = fieldHash
+				fieldDecoder10 = fieldDecoder
+			}
+		}
+		return &tenFieldsStructDecoder{typ,
+			fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
+			fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
+			fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9,
+			fieldName10, fieldDecoder10}, nil
 	}
 	return &generalStructDecoder{typ, fields}, nil
 }
@@ -218,7 +567,7 @@ func (decoder *skipDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
 
 type oneFieldStructDecoder struct {
 	typ          reflect.Type
-	fieldName    string
+	fieldHash    int32
 	fieldDecoder *structFieldDecoder
 }
 
@@ -226,21 +575,15 @@ func (decoder *oneFieldStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator)
 	if !iter.readObjectStart() {
 		return
 	}
-	fieldBytes := iter.readObjectFieldAsBytes()
-	field := *(*string)(unsafe.Pointer(&fieldBytes))
-	if field == decoder.fieldName {
-		decoder.fieldDecoder.decode(ptr, iter)
-	} else {
-		iter.Skip()
-	}
-	for iter.nextToken() == ',' {
-		fieldBytes = iter.readObjectFieldAsBytes()
-		field = *(*string)(unsafe.Pointer(&fieldBytes))
-		if field == decoder.fieldName {
+	for {
+		if iter.readFieldHash() == decoder.fieldHash {
 			decoder.fieldDecoder.decode(ptr, iter)
 		} else {
 			iter.Skip()
 		}
+		if iter.nextToken() != ',' {
+			break
+		}
 	}
 	if iter.Error != nil && iter.Error != io.EOF {
 		iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
@@ -248,38 +591,29 @@ func (decoder *oneFieldStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator)
 }
 
 type twoFieldsStructDecoder struct {
-	typ           reflect.Type
-	fieldName1    string
-	fieldDecoder1 *structFieldDecoder
-	fieldName2    string
-	fieldDecoder2 *structFieldDecoder
+	typ            reflect.Type
+	fieldHash1     int32
+	fieldDecoder1  *structFieldDecoder
+	fieldHash2     int32
+	fieldDecoder2  *structFieldDecoder
 }
 
 func (decoder *twoFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
 	if !iter.readObjectStart() {
 		return
 	}
-	fieldBytes := iter.readObjectFieldAsBytes()
-	field := *(*string)(unsafe.Pointer(&fieldBytes))
-	switch field {
-	case decoder.fieldName1:
-		decoder.fieldDecoder1.decode(ptr, iter)
-	case decoder.fieldName2:
-		decoder.fieldDecoder2.decode(ptr, iter)
-	default:
-		iter.Skip()
-	}
-	for iter.nextToken() == ',' {
-		fieldBytes = iter.readObjectFieldAsBytes()
-		field = *(*string)(unsafe.Pointer(&fieldBytes))
-		switch field {
-		case decoder.fieldName1:
+	for {
+		switch iter.readFieldHash() {
+		case decoder.fieldHash1:
 			decoder.fieldDecoder1.decode(ptr, iter)
-		case decoder.fieldName2:
+		case decoder.fieldHash2:
 			decoder.fieldDecoder2.decode(ptr, iter)
 		default:
 			iter.Skip()
 		}
+		if iter.nextToken() != ',' {
+			break
+		}
 	}
 	if iter.Error != nil && iter.Error != io.EOF {
 		iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
@@ -287,44 +621,33 @@ func (decoder *twoFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator
 }
 
 type threeFieldsStructDecoder struct {
-	typ           reflect.Type
-	fieldName1    string
-	fieldDecoder1 *structFieldDecoder
-	fieldName2    string
-	fieldDecoder2 *structFieldDecoder
-	fieldName3    string
-	fieldDecoder3 *structFieldDecoder
+	typ            reflect.Type
+	fieldHash1     int32
+	fieldDecoder1  *structFieldDecoder
+	fieldHash2     int32
+	fieldDecoder2  *structFieldDecoder
+	fieldHash3     int32
+	fieldDecoder3  *structFieldDecoder
 }
 
 func (decoder *threeFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
 	if !iter.readObjectStart() {
 		return
 	}
-	fieldBytes := iter.readObjectFieldAsBytes()
-	field := *(*string)(unsafe.Pointer(&fieldBytes))
-	switch field {
-	case decoder.fieldName1:
-		decoder.fieldDecoder1.decode(ptr, iter)
-	case decoder.fieldName2:
-		decoder.fieldDecoder2.decode(ptr, iter)
-	case decoder.fieldName3:
-		decoder.fieldDecoder3.decode(ptr, iter)
-	default:
-		iter.Skip()
-	}
-	for iter.nextToken() == ',' {
-		fieldBytes = iter.readObjectFieldAsBytes()
-		field = *(*string)(unsafe.Pointer(&fieldBytes))
-		switch field {
-		case decoder.fieldName1:
+	for {
+		switch iter.readFieldHash() {
+		case decoder.fieldHash1:
 			decoder.fieldDecoder1.decode(ptr, iter)
-		case decoder.fieldName2:
+		case decoder.fieldHash2:
 			decoder.fieldDecoder2.decode(ptr, iter)
-		case decoder.fieldName3:
+		case decoder.fieldHash3:
 			decoder.fieldDecoder3.decode(ptr, iter)
 		default:
 			iter.Skip()
 		}
+		if iter.nextToken() != ',' {
+			break
+		}
 	}
 	if iter.Error != nil && iter.Error != io.EOF {
 		iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
@@ -332,50 +655,349 @@ func (decoder *threeFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterat
 }
 
 type fourFieldsStructDecoder struct {
-	typ           reflect.Type
-	fieldName1    string
-	fieldDecoder1 *structFieldDecoder
-	fieldName2    string
-	fieldDecoder2 *structFieldDecoder
-	fieldName3    string
-	fieldDecoder3 *structFieldDecoder
-	fieldName4    string
-	fieldDecoder4 *structFieldDecoder
+	typ            reflect.Type
+	fieldHash1     int32
+	fieldDecoder1  *structFieldDecoder
+	fieldHash2     int32
+	fieldDecoder2  *structFieldDecoder
+	fieldHash3     int32
+	fieldDecoder3  *structFieldDecoder
+	fieldHash4     int32
+	fieldDecoder4  *structFieldDecoder
 }
 
 func (decoder *fourFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
 	if !iter.readObjectStart() {
 		return
 	}
-	fieldBytes := iter.readObjectFieldAsBytes()
-	field := *(*string)(unsafe.Pointer(&fieldBytes))
-	switch field {
-	case decoder.fieldName1:
-		decoder.fieldDecoder1.decode(ptr, iter)
-	case decoder.fieldName2:
-		decoder.fieldDecoder2.decode(ptr, iter)
-	case decoder.fieldName3:
-		decoder.fieldDecoder3.decode(ptr, iter)
-	case decoder.fieldName4:
-		decoder.fieldDecoder4.decode(ptr, iter)
-	default:
-		iter.Skip()
+	for {
+		switch iter.readFieldHash() {
+		case decoder.fieldHash1:
+			decoder.fieldDecoder1.decode(ptr, iter)
+		case decoder.fieldHash2:
+			decoder.fieldDecoder2.decode(ptr, iter)
+		case decoder.fieldHash3:
+			decoder.fieldDecoder3.decode(ptr, iter)
+		case decoder.fieldHash4:
+			decoder.fieldDecoder4.decode(ptr, iter)
+		default:
+			iter.Skip()
+		}
+		if iter.nextToken() != ',' {
+			break
+		}
 	}
-	for iter.nextToken() == ',' {
-		fieldBytes = iter.readObjectFieldAsBytes()
-		field = *(*string)(unsafe.Pointer(&fieldBytes))
-		switch field {
-		case decoder.fieldName1:
+	if iter.Error != nil && iter.Error != io.EOF {
+		iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
+	}
+}
+
+type fiveFieldsStructDecoder struct {
+	typ            reflect.Type
+	fieldHash1     int32
+	fieldDecoder1  *structFieldDecoder
+	fieldHash2     int32
+	fieldDecoder2  *structFieldDecoder
+	fieldHash3     int32
+	fieldDecoder3  *structFieldDecoder
+	fieldHash4     int32
+	fieldDecoder4  *structFieldDecoder
+	fieldHash5     int32
+	fieldDecoder5  *structFieldDecoder
+}
+
+func (decoder *fiveFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
+	if !iter.readObjectStart() {
+		return
+	}
+	for {
+		switch iter.readFieldHash() {
+		case decoder.fieldHash1:
+			decoder.fieldDecoder1.decode(ptr, iter)
+		case decoder.fieldHash2:
+			decoder.fieldDecoder2.decode(ptr, iter)
+		case decoder.fieldHash3:
+			decoder.fieldDecoder3.decode(ptr, iter)
+		case decoder.fieldHash4:
+			decoder.fieldDecoder4.decode(ptr, iter)
+		case decoder.fieldHash5:
+			decoder.fieldDecoder5.decode(ptr, iter)
+		default:
+			iter.Skip()
+		}
+		if iter.nextToken() != ',' {
+			break
+		}
+	}
+	if iter.Error != nil && iter.Error != io.EOF {
+		iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
+	}
+}
+
+type sixFieldsStructDecoder struct {
+	typ            reflect.Type
+	fieldHash1     int32
+	fieldDecoder1  *structFieldDecoder
+	fieldHash2     int32
+	fieldDecoder2  *structFieldDecoder
+	fieldHash3     int32
+	fieldDecoder3  *structFieldDecoder
+	fieldHash4     int32
+	fieldDecoder4  *structFieldDecoder
+	fieldHash5     int32
+	fieldDecoder5  *structFieldDecoder
+	fieldHash6     int32
+	fieldDecoder6  *structFieldDecoder
+}
+
+func (decoder *sixFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
+	if !iter.readObjectStart() {
+		return
+	}
+	for {
+		switch iter.readFieldHash() {
+		case decoder.fieldHash1:
 			decoder.fieldDecoder1.decode(ptr, iter)
-		case decoder.fieldName2:
+		case decoder.fieldHash2:
 			decoder.fieldDecoder2.decode(ptr, iter)
-		case decoder.fieldName3:
+		case decoder.fieldHash3:
 			decoder.fieldDecoder3.decode(ptr, iter)
-		case decoder.fieldName4:
+		case decoder.fieldHash4:
 			decoder.fieldDecoder4.decode(ptr, iter)
+		case decoder.fieldHash5:
+			decoder.fieldDecoder5.decode(ptr, iter)
+		case decoder.fieldHash6:
+			decoder.fieldDecoder6.decode(ptr, iter)
 		default:
 			iter.Skip()
 		}
+		if iter.nextToken() != ',' {
+			break
+		}
+	}
+	if iter.Error != nil && iter.Error != io.EOF {
+		iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
+	}
+}
+
+type sevenFieldsStructDecoder struct {
+	typ            reflect.Type
+	fieldHash1     int32
+	fieldDecoder1  *structFieldDecoder
+	fieldHash2     int32
+	fieldDecoder2  *structFieldDecoder
+	fieldHash3     int32
+	fieldDecoder3  *structFieldDecoder
+	fieldHash4     int32
+	fieldDecoder4  *structFieldDecoder
+	fieldHash5     int32
+	fieldDecoder5  *structFieldDecoder
+	fieldHash6     int32
+	fieldDecoder6  *structFieldDecoder
+	fieldHash7     int32
+	fieldDecoder7  *structFieldDecoder
+}
+
+func (decoder *sevenFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
+	if !iter.readObjectStart() {
+		return
+	}
+	for {
+		switch iter.readFieldHash() {
+		case decoder.fieldHash1:
+			decoder.fieldDecoder1.decode(ptr, iter)
+		case decoder.fieldHash2:
+			decoder.fieldDecoder2.decode(ptr, iter)
+		case decoder.fieldHash3:
+			decoder.fieldDecoder3.decode(ptr, iter)
+		case decoder.fieldHash4:
+			decoder.fieldDecoder4.decode(ptr, iter)
+		case decoder.fieldHash5:
+			decoder.fieldDecoder5.decode(ptr, iter)
+		case decoder.fieldHash6:
+			decoder.fieldDecoder6.decode(ptr, iter)
+		case decoder.fieldHash7:
+			decoder.fieldDecoder7.decode(ptr, iter)
+		default:
+			iter.Skip()
+		}
+		if iter.nextToken() != ',' {
+			break
+		}
+	}
+	if iter.Error != nil && iter.Error != io.EOF {
+		iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
+	}
+}
+
+type eightFieldsStructDecoder struct {
+	typ            reflect.Type
+	fieldHash1     int32
+	fieldDecoder1  *structFieldDecoder
+	fieldHash2     int32
+	fieldDecoder2  *structFieldDecoder
+	fieldHash3     int32
+	fieldDecoder3  *structFieldDecoder
+	fieldHash4     int32
+	fieldDecoder4  *structFieldDecoder
+	fieldHash5     int32
+	fieldDecoder5  *structFieldDecoder
+	fieldHash6     int32
+	fieldDecoder6  *structFieldDecoder
+	fieldHash7     int32
+	fieldDecoder7  *structFieldDecoder
+	fieldHash8     int32
+	fieldDecoder8  *structFieldDecoder
+}
+
+func (decoder *eightFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
+	if !iter.readObjectStart() {
+		return
+	}
+	for {
+		switch iter.readFieldHash() {
+		case decoder.fieldHash1:
+			decoder.fieldDecoder1.decode(ptr, iter)
+		case decoder.fieldHash2:
+			decoder.fieldDecoder2.decode(ptr, iter)
+		case decoder.fieldHash3:
+			decoder.fieldDecoder3.decode(ptr, iter)
+		case decoder.fieldHash4:
+			decoder.fieldDecoder4.decode(ptr, iter)
+		case decoder.fieldHash5:
+			decoder.fieldDecoder5.decode(ptr, iter)
+		case decoder.fieldHash6:
+			decoder.fieldDecoder6.decode(ptr, iter)
+		case decoder.fieldHash7:
+			decoder.fieldDecoder7.decode(ptr, iter)
+		case decoder.fieldHash8:
+			decoder.fieldDecoder8.decode(ptr, iter)
+		default:
+			iter.Skip()
+		}
+		if iter.nextToken() != ',' {
+			break
+		}
+	}
+	if iter.Error != nil && iter.Error != io.EOF {
+		iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
+	}
+}
+
+type nineFieldsStructDecoder struct {
+	typ            reflect.Type
+	fieldHash1     int32
+	fieldDecoder1  *structFieldDecoder
+	fieldHash2     int32
+	fieldDecoder2  *structFieldDecoder
+	fieldHash3     int32
+	fieldDecoder3  *structFieldDecoder
+	fieldHash4     int32
+	fieldDecoder4  *structFieldDecoder
+	fieldHash5     int32
+	fieldDecoder5  *structFieldDecoder
+	fieldHash6     int32
+	fieldDecoder6  *structFieldDecoder
+	fieldHash7     int32
+	fieldDecoder7  *structFieldDecoder
+	fieldHash8     int32
+	fieldDecoder8  *structFieldDecoder
+	fieldHash9     int32
+	fieldDecoder9  *structFieldDecoder
+}
+
+func (decoder *nineFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
+	if !iter.readObjectStart() {
+		return
+	}
+	for {
+		switch iter.readFieldHash() {
+		case decoder.fieldHash1:
+			decoder.fieldDecoder1.decode(ptr, iter)
+		case decoder.fieldHash2:
+			decoder.fieldDecoder2.decode(ptr, iter)
+		case decoder.fieldHash3:
+			decoder.fieldDecoder3.decode(ptr, iter)
+		case decoder.fieldHash4:
+			decoder.fieldDecoder4.decode(ptr, iter)
+		case decoder.fieldHash5:
+			decoder.fieldDecoder5.decode(ptr, iter)
+		case decoder.fieldHash6:
+			decoder.fieldDecoder6.decode(ptr, iter)
+		case decoder.fieldHash7:
+			decoder.fieldDecoder7.decode(ptr, iter)
+		case decoder.fieldHash8:
+			decoder.fieldDecoder8.decode(ptr, iter)
+		case decoder.fieldHash9:
+			decoder.fieldDecoder9.decode(ptr, iter)
+		default:
+			iter.Skip()
+		}
+		if iter.nextToken() != ',' {
+			break
+		}
+	}
+	if iter.Error != nil && iter.Error != io.EOF {
+		iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
+	}
+}
+
+type tenFieldsStructDecoder struct {
+	typ            reflect.Type
+	fieldHash1     int32
+	fieldDecoder1  *structFieldDecoder
+	fieldHash2     int32
+	fieldDecoder2  *structFieldDecoder
+	fieldHash3     int32
+	fieldDecoder3  *structFieldDecoder
+	fieldHash4     int32
+	fieldDecoder4  *structFieldDecoder
+	fieldHash5     int32
+	fieldDecoder5  *structFieldDecoder
+	fieldHash6     int32
+	fieldDecoder6  *structFieldDecoder
+	fieldHash7     int32
+	fieldDecoder7  *structFieldDecoder
+	fieldHash8     int32
+	fieldDecoder8  *structFieldDecoder
+	fieldHash9     int32
+	fieldDecoder9  *structFieldDecoder
+	fieldHash10    int32
+	fieldDecoder10 *structFieldDecoder
+}
+
+func (decoder *tenFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
+	if !iter.readObjectStart() {
+		return
+	}
+	for {
+		switch iter.readFieldHash() {
+		case decoder.fieldHash1:
+			decoder.fieldDecoder1.decode(ptr, iter)
+		case decoder.fieldHash2:
+			decoder.fieldDecoder2.decode(ptr, iter)
+		case decoder.fieldHash3:
+			decoder.fieldDecoder3.decode(ptr, iter)
+		case decoder.fieldHash4:
+			decoder.fieldDecoder4.decode(ptr, iter)
+		case decoder.fieldHash5:
+			decoder.fieldDecoder5.decode(ptr, iter)
+		case decoder.fieldHash6:
+			decoder.fieldDecoder6.decode(ptr, iter)
+		case decoder.fieldHash7:
+			decoder.fieldDecoder7.decode(ptr, iter)
+		case decoder.fieldHash8:
+			decoder.fieldDecoder8.decode(ptr, iter)
+		case decoder.fieldHash9:
+			decoder.fieldDecoder9.decode(ptr, iter)
+		case decoder.fieldHash10:
+			decoder.fieldDecoder10.decode(ptr, iter)
+		default:
+			iter.Skip()
+		}
+		if iter.nextToken() != ',' {
+			break
+		}
 	}
 	if iter.Error != nil && iter.Error != io.EOF {
 		iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())

+ 25 - 0
jsoniter_reflect_struct_test.go

@@ -85,6 +85,31 @@ func Test_decode_five_fields_struct(t *testing.T) {
 	should.Equal("e", obj.field5)
 }
 
+func Test_decode_ten_fields_struct(t *testing.T) {
+	should := require.New(t)
+	type TestObject struct {
+		field1 string
+		field2 string
+		field3 string
+		field4 string
+		field5 string
+		field6 string
+		field7 string
+		field8 string
+		field9 string
+		field10 string
+	}
+	obj := TestObject{}
+	should.Nil(UnmarshalFromString(`{}`, &obj))
+	should.Equal("", obj.field1)
+	should.Nil(UnmarshalFromString(`{"field1": "a", "field2": "b", "field3": "c", "field4": "d", "field5": "e"}`, &obj))
+	should.Equal("a", obj.field1)
+	should.Equal("b", obj.field2)
+	should.Equal("c", obj.field3)
+	should.Equal("d", obj.field4)
+	should.Equal("e", obj.field5)
+}
+
 func Test_decode_struct_field_with_tag(t *testing.T) {
 	should := require.New(t)
 	type TestObject struct {