diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2013-01-30 01:37:13 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2013-01-30 01:37:13 +0000 |
commit | 777133fefb9704c957884216e44bf7ba25ca2fae (patch) | |
tree | ac10866a1e77c784cb9d48b872fd8013ba124fd0 | |
parent | 900f0840363c7a110723b18024b361f22b8892b9 (diff) | |
download | gcc-777133fefb9704c957884216e44bf7ba25ca2fae.tar.gz |
libgo: Update Go library to master revision 15502/229081515358.
From-SVN: r195569
-rw-r--r-- | libgo/MERGE | 2 | ||||
-rw-r--r-- | libgo/go/encoding/json/bench_test.go | 34 | ||||
-rw-r--r-- | libgo/go/encoding/json/decode.go | 19 | ||||
-rw-r--r-- | libgo/go/encoding/json/decode_test.go | 23 | ||||
-rw-r--r-- | libgo/go/encoding/json/stream.go | 7 | ||||
-rw-r--r-- | libgo/go/encoding/json/stream_test.go | 24 | ||||
-rw-r--r-- | libgo/go/exp/ssa/blockopt.go | 6 | ||||
-rw-r--r-- | libgo/go/exp/ssa/func.go | 50 | ||||
-rw-r--r-- | libgo/go/exp/ssa/ssa.go | 30 | ||||
-rw-r--r-- | libgo/go/go/build/build.go | 8 | ||||
-rw-r--r-- | libgo/go/go/build/build_test.go | 12 | ||||
-rw-r--r-- | libgo/runtime/go-traceback.c | 6 | ||||
-rw-r--r-- | libgo/runtime/panic.c | 5 | ||||
-rw-r--r-- | libgo/runtime/proc.c | 14 | ||||
-rw-r--r-- | libgo/runtime/runtime.c | 6 | ||||
-rw-r--r-- | libgo/runtime/runtime.h | 6 | ||||
-rw-r--r-- | libgo/runtime/time.goc | 4 |
17 files changed, 158 insertions, 98 deletions
diff --git a/libgo/MERGE b/libgo/MERGE index b69bf8437f9..5cf1a26a66f 100644 --- a/libgo/MERGE +++ b/libgo/MERGE @@ -1,4 +1,4 @@ -921e53d4863c +229081515358 The first line of this file holds the Mercurial revision number of the last merge done from the master library sources. 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" diff --git a/libgo/runtime/go-traceback.c b/libgo/runtime/go-traceback.c index 11cc052829f..30a5ed91c44 100644 --- a/libgo/runtime/go-traceback.c +++ b/libgo/runtime/go-traceback.c @@ -17,11 +17,11 @@ runtime_traceback () int32 c; c = runtime_callers (1, pcbuf, sizeof pcbuf / sizeof pcbuf[0]); - runtime_printtrace (pcbuf, c); + runtime_printtrace (pcbuf, c, true); } void -runtime_printtrace (uintptr *pcbuf, int32 c) +runtime_printtrace (uintptr *pcbuf, int32 c, bool current) { int32 i; @@ -32,7 +32,7 @@ runtime_printtrace (uintptr *pcbuf, int32 c) intgo line; if (__go_file_line (pcbuf[i], &fn, &file, &line) - && runtime_showframe (fn)) + && runtime_showframe (fn, current)) { runtime_printf ("%S\n", fn); runtime_printf ("\t%S:%D\n", file, (int64) line); diff --git a/libgo/runtime/panic.c b/libgo/runtime/panic.c index 23a56f3dc64..7b9b578e46c 100644 --- a/libgo/runtime/panic.c +++ b/libgo/runtime/panic.c @@ -86,6 +86,11 @@ runtime_dopanic(int32 unused __attribute__ ((unused))) void runtime_throw(const char *s) { + M *mp; + + mp = runtime_m(); + if(mp->throwing == 0) + mp->throwing = 1; runtime_startpanic(); runtime_printf("fatal error: %s\n", s); runtime_dopanic(0); diff --git a/libgo/runtime/proc.c b/libgo/runtime/proc.c index e805c908000..b2e37f39150 100644 --- a/libgo/runtime/proc.c +++ b/libgo/runtime/proc.c @@ -528,6 +528,7 @@ runtime_main(void) setmcpumax(runtime_gomaxprocs); runtime_sched.init = true; scvg = __go_go(runtime_MHeap_Scavenger, nil); + scvg->issystem = true; main_init(); runtime_sched.init = false; if(!runtime_sched.lockmain) @@ -638,12 +639,16 @@ void runtime_tracebackothers(G * volatile me) { G * volatile gp; - Traceback traceback; + Traceback tb; + int32 traceback; - traceback.gp = me; + tb.gp = me; + traceback = runtime_gotraceback(); for(gp = runtime_allg; gp != nil; gp = gp->alllink) { if(gp == me || gp->status == Gdead) continue; + if(gp->issystem && traceback < 2) + continue; runtime_printf("\n"); runtime_goroutineheader(gp); @@ -661,7 +666,7 @@ runtime_tracebackothers(G * volatile me) continue; } - gp->traceback = &traceback; + gp->traceback = &tb; #ifdef USING_SPLIT_STACK __splitstack_getcontext(&me->stack_context[0]); @@ -672,7 +677,7 @@ runtime_tracebackothers(G * volatile me) runtime_gogo(gp); } - runtime_printtrace(traceback.pcbuf, traceback.c); + runtime_printtrace(tb.pcbuf, tb.c, false); runtime_goroutinetrailer(gp); } } @@ -975,6 +980,7 @@ top: if((scvg == nil && runtime_sched.grunning == 0) || (scvg != nil && runtime_sched.grunning == 1 && runtime_sched.gwait == 0 && (scvg->status == Grunning || scvg->status == Gsyscall))) { + m->throwing = -1; // do not dump full stacks runtime_throw("all goroutines are asleep - deadlock!"); } diff --git a/libgo/runtime/runtime.c b/libgo/runtime/runtime.c index b090169bbb7..48ece55d18e 100644 --- a/libgo/runtime/runtime.c +++ b/libgo/runtime/runtime.c @@ -132,10 +132,12 @@ runtime_cputicks(void) } bool -runtime_showframe(String s) +runtime_showframe(String s, bool current) { static int32 traceback = -1; - + + if(current && runtime_m()->throwing > 0) + return 1; if(traceback < 0) traceback = runtime_gotraceback(); return traceback > 1 || (__builtin_memchr(s.str, '.', s.len) != nil && __builtin_memcmp(s.str, "runtime.", 7) != 0); diff --git a/libgo/runtime/runtime.h b/libgo/runtime/runtime.h index a937503a09a..de72f42bc55 100644 --- a/libgo/runtime/runtime.h +++ b/libgo/runtime/runtime.h @@ -178,6 +178,7 @@ struct G G* schedlink; bool readyonstop; bool ispanic; + bool issystem; int8 raceignore; // ignore race detection events M* m; // for debuggers, but offset not hard-coded M* lockedm; @@ -208,6 +209,7 @@ struct M G* curg; // current running goroutine int32 id; int32 mallocing; + int32 throwing; int32 gcing; int32 locks; int32 nomemprof; @@ -389,7 +391,7 @@ void runtime_goroutineheader(G*); void runtime_goroutinetrailer(G*); void runtime_traceback(); void runtime_tracebackothers(G*); -void runtime_printtrace(uintptr*, int32); +void runtime_printtrace(uintptr*, int32, bool); String runtime_gostringnocopy(const byte*); void* runtime_mstart(void*); G* runtime_malg(int32, byte**, size_t*); @@ -593,7 +595,7 @@ void runtime_osyield(void); void runtime_LockOSThread(void) __asm__ (GOSYM_PREFIX "runtime.LockOSThread"); void runtime_UnlockOSThread(void) __asm__ (GOSYM_PREFIX "runtime.UnlockOSThread"); -bool runtime_showframe(String); +bool runtime_showframe(String, bool); uintptr runtime_memlimit(void); diff --git a/libgo/runtime/time.goc b/libgo/runtime/time.goc index d4973611d4e..9a5cbdfed3b 100644 --- a/libgo/runtime/time.goc +++ b/libgo/runtime/time.goc @@ -110,8 +110,10 @@ addtimer(Timer *t) runtime_ready(timers.timerproc); } } - if(timers.timerproc == nil) + if(timers.timerproc == nil) { timers.timerproc = __go_go(timerproc, nil); + timers.timerproc->issystem = true; + } } // Delete timer t from the heap. |