AST Tweaks (#551)
* Use pointers instead of copying around ast.Node Node is a 56B struct that is constantly in the hot path. Passing nodes around by copy had a cost that started to add up. This change replaces them by pointers. Using unsafe pointer arithmetic and converting sibling/child indexes to relative offsets, it removes the need to carry around a pointer to the root of the tree. This saves 8B per Node. This space will be used to store an extra []byte slice to provide contextual error handling on all nodes, including the ones whose data is different than the raw input (for example: strings with escaped characters), while staying under the size of a cache line. * Remove conditional * Add Raw to track range in data for parsed values * Simplify reference tracking
This commit is contained in:
+19
-22
@@ -106,7 +106,6 @@ func (d *Decoder) Decode(v interface{}) error {
|
||||
|
||||
type decoder struct {
|
||||
// Which parser instance in use for this decoding session.
|
||||
// TODO: Think about removing later.
|
||||
p *parser
|
||||
|
||||
// Flag indicating that the current expression is stashed.
|
||||
@@ -132,7 +131,7 @@ type decoder struct {
|
||||
strict strict
|
||||
}
|
||||
|
||||
func (d *decoder) expr() ast.Node {
|
||||
func (d *decoder) expr() *ast.Node {
|
||||
return d.p.Expression()
|
||||
}
|
||||
|
||||
@@ -208,7 +207,7 @@ Rules for the unmarshal code:
|
||||
- An "object" is either a struct or a map.
|
||||
*/
|
||||
|
||||
func (d *decoder) handleRootExpression(expr ast.Node, v reflect.Value) error {
|
||||
func (d *decoder) handleRootExpression(expr *ast.Node, v reflect.Value) error {
|
||||
var x reflect.Value
|
||||
var err error
|
||||
|
||||
@@ -533,7 +532,7 @@ func (d *decoder) handleTablePart(key ast.Iterator, v reflect.Value) (reflect.Va
|
||||
return d.handleKeyPart(key, v, d.handleTable, makeMapStringInterface)
|
||||
}
|
||||
|
||||
func tryTextUnmarshaler(node ast.Node, v reflect.Value) (bool, error) {
|
||||
func (d *decoder) tryTextUnmarshaler(node *ast.Node, v reflect.Value) (bool, error) {
|
||||
if v.Kind() != reflect.Struct {
|
||||
return false, nil
|
||||
}
|
||||
@@ -547,9 +546,7 @@ func tryTextUnmarshaler(node ast.Node, v reflect.Value) (bool, error) {
|
||||
if v.CanAddr() && v.Addr().Type().Implements(textUnmarshalerType) {
|
||||
err := v.Addr().Interface().(encoding.TextUnmarshaler).UnmarshalText(node.Data)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("toml: error calling UnmarshalText: %w", err)
|
||||
// TODO: same as above
|
||||
// return false, newDecodeError(node.Data, "error calling UnmarshalText: %w", err)
|
||||
return false, newDecodeError(d.p.Raw(node.Raw), "error calling UnmarshalText: %w", err)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
@@ -558,12 +555,12 @@ func tryTextUnmarshaler(node ast.Node, v reflect.Value) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (d *decoder) handleValue(value ast.Node, v reflect.Value) error {
|
||||
func (d *decoder) handleValue(value *ast.Node, v reflect.Value) error {
|
||||
for v.Kind() == reflect.Ptr {
|
||||
v = initAndDereferencePointer(v)
|
||||
}
|
||||
|
||||
ok, err := tryTextUnmarshaler(value, v)
|
||||
ok, err := d.tryTextUnmarshaler(value, v)
|
||||
if ok || err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -592,7 +589,7 @@ func (d *decoder) handleValue(value ast.Node, v reflect.Value) error {
|
||||
}
|
||||
}
|
||||
|
||||
func (d *decoder) unmarshalArray(array ast.Node, v reflect.Value) error {
|
||||
func (d *decoder) unmarshalArray(array *ast.Node, v reflect.Value) error {
|
||||
switch v.Kind() {
|
||||
case reflect.Slice:
|
||||
if v.IsNil() {
|
||||
@@ -663,7 +660,7 @@ func (d *decoder) unmarshalArray(array ast.Node, v reflect.Value) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *decoder) unmarshalInlineTable(itable ast.Node, v reflect.Value) error {
|
||||
func (d *decoder) unmarshalInlineTable(itable *ast.Node, v reflect.Value) error {
|
||||
// Make sure v is an initialized object.
|
||||
switch v.Kind() {
|
||||
case reflect.Map:
|
||||
@@ -699,7 +696,7 @@ func (d *decoder) unmarshalInlineTable(itable ast.Node, v reflect.Value) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *decoder) unmarshalDateTime(value ast.Node, v reflect.Value) error {
|
||||
func (d *decoder) unmarshalDateTime(value *ast.Node, v reflect.Value) error {
|
||||
dt, err := parseDateTime(value.Data)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -709,7 +706,7 @@ func (d *decoder) unmarshalDateTime(value ast.Node, v reflect.Value) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *decoder) unmarshalLocalDate(value ast.Node, v reflect.Value) error {
|
||||
func (d *decoder) unmarshalLocalDate(value *ast.Node, v reflect.Value) error {
|
||||
ld, err := parseLocalDate(value.Data)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -727,7 +724,7 @@ func (d *decoder) unmarshalLocalDate(value ast.Node, v reflect.Value) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *decoder) unmarshalLocalDateTime(value ast.Node, v reflect.Value) error {
|
||||
func (d *decoder) unmarshalLocalDateTime(value *ast.Node, v reflect.Value) error {
|
||||
ldt, rest, err := parseLocalDateTime(value.Data)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -749,7 +746,7 @@ func (d *decoder) unmarshalLocalDateTime(value ast.Node, v reflect.Value) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *decoder) unmarshalBool(value ast.Node, v reflect.Value) error {
|
||||
func (d *decoder) unmarshalBool(value *ast.Node, v reflect.Value) error {
|
||||
b := value.Data[0] == 't'
|
||||
|
||||
switch v.Kind() {
|
||||
@@ -764,7 +761,7 @@ func (d *decoder) unmarshalBool(value ast.Node, v reflect.Value) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *decoder) unmarshalFloat(value ast.Node, v reflect.Value) error {
|
||||
func (d *decoder) unmarshalFloat(value *ast.Node, v reflect.Value) error {
|
||||
f, err := parseFloat(value.Data)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -787,7 +784,7 @@ func (d *decoder) unmarshalFloat(value ast.Node, v reflect.Value) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *decoder) unmarshalInteger(value ast.Node, v reflect.Value) error {
|
||||
func (d *decoder) unmarshalInteger(value *ast.Node, v reflect.Value) error {
|
||||
const (
|
||||
maxInt = int64(^uint(0) >> 1)
|
||||
minInt = -maxInt - 1
|
||||
@@ -865,7 +862,7 @@ func (d *decoder) unmarshalInteger(value ast.Node, v reflect.Value) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *decoder) unmarshalString(value ast.Node, v reflect.Value) error {
|
||||
func (d *decoder) unmarshalString(value *ast.Node, v reflect.Value) error {
|
||||
var err error
|
||||
|
||||
switch v.Kind() {
|
||||
@@ -874,13 +871,13 @@ func (d *decoder) unmarshalString(value ast.Node, v reflect.Value) error {
|
||||
case reflect.Interface:
|
||||
v.Set(reflect.ValueOf(string(value.Data)))
|
||||
default:
|
||||
err = fmt.Errorf("toml: cannot store TOML string into a Go %s", v.Kind())
|
||||
err = newDecodeError(d.p.Raw(value.Raw), "cannot store TOML string into a Go %s", v.Kind())
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *decoder) handleKeyValue(expr ast.Node, v reflect.Value) (reflect.Value, error) {
|
||||
func (d *decoder) handleKeyValue(expr *ast.Node, v reflect.Value) (reflect.Value, error) {
|
||||
d.strict.EnterKeyValue(expr)
|
||||
|
||||
v, err := d.handleKeyValueInner(expr.Key(), expr.Value(), v)
|
||||
@@ -894,7 +891,7 @@ func (d *decoder) handleKeyValue(expr ast.Node, v reflect.Value) (reflect.Value,
|
||||
return v, err
|
||||
}
|
||||
|
||||
func (d *decoder) handleKeyValueInner(key ast.Iterator, value ast.Node, v reflect.Value) (reflect.Value, error) {
|
||||
func (d *decoder) handleKeyValueInner(key ast.Iterator, value *ast.Node, v reflect.Value) (reflect.Value, error) {
|
||||
if key.Next() {
|
||||
// Still scoping the key
|
||||
return d.handleKeyValuePart(key, value, v)
|
||||
@@ -904,7 +901,7 @@ func (d *decoder) handleKeyValueInner(key ast.Iterator, value ast.Node, v reflec
|
||||
return reflect.Value{}, d.handleValue(value, v)
|
||||
}
|
||||
|
||||
func (d *decoder) handleKeyValuePart(key ast.Iterator, value ast.Node, v reflect.Value) (reflect.Value, error) {
|
||||
func (d *decoder) handleKeyValuePart(key ast.Iterator, value *ast.Node, v reflect.Value) (reflect.Value, error) {
|
||||
// contains the replacement for v
|
||||
var rv reflect.Value
|
||||
|
||||
|
||||
Reference in New Issue
Block a user