]> Cypherpunks repositories - gostls13.git/commitdiff
Revert "encoding/json: reduce unmarshal mallocs for unmapped fields"
authorBrad Fitzpatrick <bradfitz@golang.org>
Thu, 29 Jun 2017 17:06:54 +0000 (17:06 +0000)
committerBrad Fitzpatrick <bradfitz@golang.org>
Thu, 29 Jun 2017 17:21:51 +0000 (17:21 +0000)
This reverts commit df68afd07ce67727 (https://golang.org/cl/33276)

Reason for revert: made other benchmarks worse

Fixes #20693 (details)
Updates #17914
Updates #10335

Change-Id: If451b620803ccb0536b89c76c4353d2185d57d7e
Reviewed-on: https://go-review.googlesource.com/47211
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
src/encoding/json/decode.go

index 710c835547e7a2f6388c88a4489f0288db2c46af..420a07e1549c451bb2173cd3f00c3048ae6e9b26 100644 (file)
@@ -361,40 +361,47 @@ func (d *decodeState) scanWhile(op int) int {
        return newOp
 }
 
-// discardObject and discardArray are dummy data targets
-// used by the (*decodeState).value method, which
-// accepts a zero reflect.Value to discard a value.
-// The (*decodeState).object and (*decodeState).array methods,
-// however, require a valid reflect.Value destination.
-// These are the target values used when the caller of value
-// wants to skip a field.
-//
-// Because these values refer to zero-sized objects
-// and thus can't be mutated, they're safe for concurrent use
-// by different goroutines unmarshalling skipped fields.
-var (
-       discardObject = reflect.ValueOf(struct{}{})
-       discardArray  = reflect.ValueOf([0]interface{}{})
-)
-
 // value decodes a JSON value from d.data[d.off:] into the value.
-// It updates d.off to point past the decoded value. If v is
-// invalid, the JSON value is discarded.
+// it updates d.off to point past the decoded value.
 func (d *decodeState) value(v reflect.Value) {
+       if !v.IsValid() {
+               _, rest, err := nextValue(d.data[d.off:], &d.nextscan)
+               if err != nil {
+                       d.error(err)
+               }
+               d.off = len(d.data) - len(rest)
+
+               // d.scan thinks we're still at the beginning of the item.
+               // Feed in an empty string - the shortest, simplest value -
+               // so that it knows we got to the end of the value.
+               if d.scan.redo {
+                       // rewind.
+                       d.scan.redo = false
+                       d.scan.step = stateBeginValue
+               }
+               d.scan.step(&d.scan, '"')
+               d.scan.step(&d.scan, '"')
+
+               n := len(d.scan.parseState)
+               if n > 0 && d.scan.parseState[n-1] == parseObjectKey {
+                       // d.scan thinks we just read an object key; finish the object
+                       d.scan.step(&d.scan, ':')
+                       d.scan.step(&d.scan, '"')
+                       d.scan.step(&d.scan, '"')
+                       d.scan.step(&d.scan, '}')
+               }
+
+               return
+       }
+
        switch op := d.scanWhile(scanSkipSpace); op {
        default:
                d.error(errPhase)
 
        case scanBeginArray:
-               if !v.IsValid() {
-                       v = discardArray
-               }
                d.array(v)
 
        case scanBeginObject:
-               if !v.IsValid() {
-                       v = discardObject
-               }
                d.object(v)
 
        case scanBeginLiteral:
@@ -512,7 +519,8 @@ func (d *decodeState) array(v reflect.Value) {
                d.off--
                d.next()
                return
-       case reflect.Array, reflect.Slice:
+       case reflect.Array:
+       case reflect.Slice:
                break
        }
 
@@ -791,9 +799,7 @@ func (d *decodeState) literal(v reflect.Value) {
        d.off--
        d.scan.undo(op)
 
-       if v.IsValid() {
-               d.literalStore(d.data[start:d.off], v, false)
-       }
+       d.literalStore(d.data[start:d.off], v, false)
 }
 
 // convertNumber converts the number literal s to a float64 or a Number