summaryrefslogtreecommitdiff
path: root/libgo/go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go')
-rw-r--r--libgo/go/encoding/json/bench_test.go34
-rw-r--r--libgo/go/encoding/json/decode.go19
-rw-r--r--libgo/go/encoding/json/decode_test.go23
-rw-r--r--libgo/go/encoding/json/stream.go7
-rw-r--r--libgo/go/encoding/json/stream_test.go24
-rw-r--r--libgo/go/exp/ssa/blockopt.go6
-rw-r--r--libgo/go/exp/ssa/func.go50
-rw-r--r--libgo/go/exp/ssa/ssa.go30
-rw-r--r--libgo/go/go/build/build.go8
-rw-r--r--libgo/go/go/build/build_test.go12
10 files changed, 128 insertions, 85 deletions
diff --git a/libgo/go/encoding/json/bench_test.go b/libgo/go/encoding/json/bench_test.go
index 333c1c0ce9e..29dbc26d417 100644
--- a/libgo/go/encoding/json/bench_test.go
+++ b/libgo/go/encoding/json/bench_test.go
@@ -153,5 +153,37 @@ func BenchmarkCodeUnmarshalReuse(b *testing.B) {
b.Fatal("Unmmarshal:", err)
}
}
- b.SetBytes(int64(len(codeJSON)))
+}
+
+func BenchmarkUnmarshalString(b *testing.B) {
+ data := []byte(`"hello, world"`)
+ var s string
+
+ for i := 0; i < b.N; i++ {
+ if err := Unmarshal(data, &s); err != nil {
+ b.Fatal("Unmarshal:", err)
+ }
+ }
+}
+
+func BenchmarkUnmarshalFloat64(b *testing.B) {
+ var f float64
+ data := []byte(`3.14`)
+
+ for i := 0; i < b.N; i++ {
+ if err := Unmarshal(data, &f); err != nil {
+ b.Fatal("Unmarshal:", err)
+ }
+ }
+}
+
+func BenchmarkUnmarshalInt64(b *testing.B) {
+ var x int64
+ data := []byte(`3`)
+
+ for i := 0; i < b.N; i++ {
+ if err := Unmarshal(data, &x); err != nil {
+ b.Fatal("Unmarshal:", err)
+ }
+ }
}
diff --git a/libgo/go/encoding/json/decode.go b/libgo/go/encoding/json/decode.go
index 6e6815ff131..95e91209184 100644
--- a/libgo/go/encoding/json/decode.go
+++ b/libgo/go/encoding/json/decode.go
@@ -52,25 +52,6 @@ import (
// an UnmarshalTypeError describing the earliest such error.
//
func Unmarshal(data []byte, v interface{}) error {
-
- // skip heavy processing for primitive values
- var first byte
- var i int
- for i, first = range data {
- if !isSpace(rune(first)) {
- break
- }
- }
- if first != '{' && first != '[' {
- rv := reflect.ValueOf(v)
- if rv.Kind() != reflect.Ptr || rv.IsNil() {
- return &InvalidUnmarshalError{reflect.TypeOf(v)}
- }
- var d decodeState
- d.literalStore(data[i:], rv.Elem(), false)
- return d.savedError
- }
-
d := new(decodeState).init(data)
// Quick check for well-formedness.
diff --git a/libgo/go/encoding/json/decode_test.go b/libgo/go/encoding/json/decode_test.go
index 97f2a41eb76..a91c6da01d3 100644
--- a/libgo/go/encoding/json/decode_test.go
+++ b/libgo/go/encoding/json/decode_test.go
@@ -1059,12 +1059,33 @@ func TestUnmarshalTypeError(t *testing.T) {
for _, item := range decodeTypeErrorTests {
err := Unmarshal([]byte(item.src), item.dest)
if _, ok := err.(*UnmarshalTypeError); !ok {
- t.Errorf("expected type error for Unmarshal(%q, type %T): got %v instead",
+ t.Errorf("expected type error for Unmarshal(%q, type %T): got %T",
item.src, item.dest, err)
}
}
}
+var unmarshalSyntaxTests = []string{
+ "tru",
+ "fals",
+ "nul",
+ "123e",
+ `"hello`,
+ `[1,2,3`,
+ `{"key":1`,
+ `{"key":1,`,
+}
+
+func TestUnmarshalSyntax(t *testing.T) {
+ var x interface{}
+ for _, src := range unmarshalSyntaxTests {
+ err := Unmarshal([]byte(src), &x)
+ if _, ok := err.(*SyntaxError); !ok {
+ t.Errorf("expected syntax error for Unmarshal(%q): got %T", src, err)
+ }
+ }
+}
+
// Test handling of unexported fields that should be ignored.
// Issue 4660
type unexportedFields struct {
diff --git a/libgo/go/encoding/json/stream.go b/libgo/go/encoding/json/stream.go
index 9592467d25b..00f4726cf7f 100644
--- a/libgo/go/encoding/json/stream.go
+++ b/libgo/go/encoding/json/stream.go
@@ -5,6 +5,7 @@
package json
import (
+ "bytes"
"errors"
"io"
)
@@ -58,6 +59,12 @@ func (dec *Decoder) Decode(v interface{}) error {
return err
}
+// Buffered returns a reader of the data remaining in the Decoder's
+// buffer. The reader is valid until the next call to Decode.
+func (dec *Decoder) Buffered() io.Reader {
+ return bytes.NewReader(dec.buf)
+}
+
// readValue reads a JSON value into dec.buf.
// It returns the length of the encoding.
func (dec *Decoder) readValue() (int, error) {
diff --git a/libgo/go/encoding/json/stream_test.go b/libgo/go/encoding/json/stream_test.go
index 4d66f556767..07c9e1d390c 100644
--- a/libgo/go/encoding/json/stream_test.go
+++ b/libgo/go/encoding/json/stream_test.go
@@ -6,8 +6,10 @@ package json
import (
"bytes"
+ "io/ioutil"
"net"
"reflect"
+ "strings"
"testing"
)
@@ -83,6 +85,28 @@ func TestDecoder(t *testing.T) {
}
}
+func TestDecoderBuffered(t *testing.T) {
+ r := strings.NewReader(`{"Name": "Gopher"} extra `)
+ var m struct {
+ Name string
+ }
+ d := NewDecoder(r)
+ err := d.Decode(&m)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if m.Name != "Gopher" {
+ t.Errorf("Name = %q; want Gopher", m.Name)
+ }
+ rest, err := ioutil.ReadAll(d.Buffered())
+ if err != nil {
+ t.Fatal(err)
+ }
+ if g, w := string(rest), " extra "; g != w {
+ t.Errorf("Remaining = %q; want %q", g, w)
+ }
+}
+
func nlines(s string, n int) string {
if n <= 0 {
return ""
diff --git a/libgo/go/exp/ssa/blockopt.go b/libgo/go/exp/ssa/blockopt.go
index 77a98b3e011..a81be6aefe8 100644
--- a/libgo/go/exp/ssa/blockopt.go
+++ b/libgo/go/exp/ssa/blockopt.go
@@ -5,10 +5,6 @@ package ssa
// TODO(adonovan): instead of creating several "unreachable" blocks
// per function in the Builder, reuse a single one (e.g. at Blocks[1])
// to reduce garbage.
-//
-// TODO(adonovan): in the absence of multiway branch instructions,
-// each BasicBlock has 0, 1, or 2 successors. We should preallocate
-// the backing array for the Succs slice inline in BasicBlock.
import (
"fmt"
@@ -117,7 +113,7 @@ func fuseBlocks(f *Function, a *BasicBlock) bool {
}
// A inherits B's successors
- a.Succs = b.Succs
+ a.Succs = append(a.succs2[:0], b.Succs...)
// Fix up Preds links of all successors of B.
for _, c := range b.Succs {
diff --git a/libgo/go/exp/ssa/func.go b/libgo/go/exp/ssa/func.go
index 3751839b287..6af5e1efcd5 100644
--- a/libgo/go/exp/ssa/func.go
+++ b/libgo/go/exp/ssa/func.go
@@ -151,16 +151,27 @@ func (f *Function) labelledBlock(label *ast.Ident) *lblock {
func (f *Function) addParam(name string, typ types.Type) *Parameter {
v := &Parameter{
Name_: name,
- Type_: pointer(typ), // address of param
+ Type_: typ,
}
f.Params = append(f.Params, v)
return v
}
-func (f *Function) addObjParam(obj types.Object) *Parameter {
- p := f.addParam(obj.GetName(), obj.GetType())
- f.objects[obj] = p
- return p
+// addSpilledParam declares a parameter that is pre-spilled to the
+// stack; the function body will load/store the spilled location.
+// Subsequent registerization will eliminate spills where possible.
+//
+func (f *Function) addSpilledParam(obj types.Object) {
+ name := obj.GetName()
+ param := f.addParam(name, obj.GetType())
+ spill := &Alloc{
+ Name_: name + "~", // "~" means "spilled"
+ Type_: pointer(obj.GetType()),
+ }
+ f.objects[obj] = spill
+ f.Locals = append(f.Locals, spill)
+ f.emit(spill)
+ f.emit(&Store{Addr: spill, Val: param})
}
// start initializes the function prior to generating SSA code for its body.
@@ -186,7 +197,7 @@ func (f *Function) start(mode BuilderMode, idents map[*ast.Ident]types.Object) {
if f.syntax.recvField != nil {
for _, field := range f.syntax.recvField.List {
for _, n := range field.Names {
- f.addObjParam(idents[n])
+ f.addSpilledParam(idents[n])
}
if field.Names == nil {
f.addParam(f.Signature.Recv.Name, f.Signature.Recv.Type)
@@ -198,7 +209,7 @@ func (f *Function) start(mode BuilderMode, idents map[*ast.Ident]types.Object) {
if f.syntax.paramFields != nil {
for _, field := range f.syntax.paramFields.List {
for _, n := range field.Names {
- f.addObjParam(idents[n])
+ f.addSpilledParam(idents[n])
}
}
}
@@ -300,18 +311,18 @@ func (f *Function) addLocal(typ types.Type) *Alloc {
func (f *Function) lookup(obj types.Object, escaping bool) Value {
if v, ok := f.objects[obj]; ok {
if escaping {
- switch v := v.(type) {
- case *Capture:
- // TODO(adonovan): fix: we must support this case.
- // Requires copying to a 'new' Alloc.
- fmt.Fprintln(os.Stderr, "Error: escaping reference to Capture")
- case *Parameter:
- v.Heap = true
- case *Alloc:
- v.Heap = true
- default:
- panic(fmt.Sprintf("Unexpected Function.objects kind: %T", v))
+ // Walk up the chain of Captures.
+ x := v
+ for {
+ if c, ok := x.(*Capture); ok {
+ x = c.Outer
+ } else {
+ break
+ }
}
+ // By construction, all captures are ultimately Allocs in the
+ // naive SSA form. Parameters are pre-spilled to the stack.
+ x.(*Alloc).Heap = true
}
return v // function-local var (address)
}
@@ -340,7 +351,7 @@ func (f *Function) emit(instr Instruction) Value {
func (f *Function) DumpTo(w io.Writer) {
fmt.Fprintf(w, "# Name: %s\n", f.FullName())
fmt.Fprintf(w, "# Declared at %s\n", f.Prog.Files.Position(f.Pos))
- fmt.Fprintf(w, "# Type: %s\n", f.Type())
+ fmt.Fprintf(w, "# Type: %s\n", f.Signature)
if f.Enclosing != nil {
fmt.Fprintf(w, "# Parent: %s\n", f.Enclosing.Name())
@@ -411,6 +422,7 @@ func (f *Function) newBasicBlock(name string) *BasicBlock {
Name: fmt.Sprintf("%d.%s", len(f.Blocks), name),
Func: f,
}
+ b.Succs = b.succs2[:0]
f.Blocks = append(f.Blocks, b)
return b
}
diff --git a/libgo/go/exp/ssa/ssa.go b/libgo/go/exp/ssa/ssa.go
index 8e503dc35b8..eb0f7fc0b07 100644
--- a/libgo/go/exp/ssa/ssa.go
+++ b/libgo/go/exp/ssa/ssa.go
@@ -246,19 +246,20 @@ type Function struct {
// instructions, respectively).
//
type BasicBlock struct {
- Name string // label; no semantic significance
- Func *Function // containing function
- Instrs []Instruction // instructions in order
- Preds, Succs []*BasicBlock // predecessors and successors
+ Name string // label; no semantic significance
+ Func *Function // containing function
+ Instrs []Instruction // instructions in order
+ Preds, Succs []*BasicBlock // predecessors and successors
+ succs2 [2]*BasicBlock // initial space for Succs.
}
// Pure values ----------------------------------------
// A Capture is a pointer to a lexically enclosing local variable.
//
-// The referent of a capture is a Parameter, Alloc or another Capture
-// and is always considered potentially escaping, so Captures are
-// always addresses in the heap, and have pointer types.
+// The referent of a capture is an Alloc or another Capture and is
+// always considered potentially escaping, so Captures are always
+// addresses in the heap, and have pointer types.
//
type Capture struct {
Outer Value // the Value captured from the enclosing context.
@@ -266,22 +267,9 @@ type Capture struct {
// A Parameter represents an input parameter of a function.
//
-// Parameters are addresses and thus have pointer types.
-// TODO(adonovan): this will change. We should just spill parameters
-// to ordinary Alloc-style locals if they are ever used in an
-// addressable context. Then we can lose the Heap flag.
-//
-// In the common case where Heap=false, Parameters are pointers into
-// the function's stack frame. If the case where Heap=true because a
-// parameter's address may escape from its function, Parameters are
-// pointers into a space in the heap implicitly allocated during the
-// function call. (See also Alloc, which uses the Heap flag in a
-// similar manner.)
-//
type Parameter struct {
Name_ string
- Type_ *types.Pointer
- Heap bool
+ Type_ types.Type
}
// A Literal represents a literal nil, boolean, string or numeric
diff --git a/libgo/go/go/build/build.go b/libgo/go/go/build/build.go
index f11582ac685..e2a47a556a7 100644
--- a/libgo/go/go/build/build.go
+++ b/libgo/go/go/build/build.go
@@ -321,13 +321,7 @@ func (p *Package) IsCommand() bool {
// ImportDir is like Import but processes the Go package found in
// the named directory.
func (ctxt *Context) ImportDir(dir string, mode ImportMode) (*Package, error) {
- p, err := ctxt.Import(".", dir, mode)
- // TODO(rsc,adg): breaks godoc net/http. Not sure why.
- // See CL 7232047 and issue 4696.
- if false && err == nil && !ctxt.isDir(p.Dir) {
- err = fmt.Errorf("%q is not a directory", p.Dir)
- }
- return p, err
+ return ctxt.Import(".", dir, mode)
}
// NoGoError is the error used by Import to describe a directory
diff --git a/libgo/go/go/build/build_test.go b/libgo/go/go/build/build_test.go
index 4684d9baf80..d8cf98840d7 100644
--- a/libgo/go/go/build/build_test.go
+++ b/libgo/go/go/build/build_test.go
@@ -5,7 +5,6 @@
package build
import (
- "fmt"
"os"
"path/filepath"
"runtime"
@@ -90,17 +89,6 @@ func TestLocalDirectory(t *testing.T) {
}
}
-// golang.org/issue/3248
-func TestBogusDirectory(t *testing.T) {
- return // See issue 4696.
- const dir = "/foo/bar/baz/gopher"
- _, err := ImportDir(dir, FindOnly)
- want := fmt.Sprintf("%q is not a directory", filepath.FromSlash(dir))
- if err == nil || err.Error() != want {
- t.Errorf("got error %q, want %q", err, want)
- }
-}
-
func TestShouldBuild(t *testing.T) {
const file1 = "// +build tag1\n\n" +
"package main\n"