libgo: Update Go library to master revision 15502/229081515358.
authorIan Lance Taylor <ian@gcc.gnu.org>
Wed, 30 Jan 2013 01:37:13 +0000 (01:37 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Wed, 30 Jan 2013 01:37:13 +0000 (01:37 +0000)
From-SVN: r195569

17 files changed:
libgo/MERGE
libgo/go/encoding/json/bench_test.go
libgo/go/encoding/json/decode.go
libgo/go/encoding/json/decode_test.go
libgo/go/encoding/json/stream.go
libgo/go/encoding/json/stream_test.go
libgo/go/exp/ssa/blockopt.go
libgo/go/exp/ssa/func.go
libgo/go/exp/ssa/ssa.go
libgo/go/go/build/build.go
libgo/go/go/build/build_test.go
libgo/runtime/go-traceback.c
libgo/runtime/panic.c
libgo/runtime/proc.c
libgo/runtime/runtime.c
libgo/runtime/runtime.h
libgo/runtime/time.goc

index b69bf8437f9ae6078cb58109cff099079d54754b..5cf1a26a66fa7d431800ae3f1f991b318b8d4364 100644 (file)
@@ -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.
index 333c1c0ce9e3d13b63bfa9bd58543a6d5cd6bcad..29dbc26d4173d889d0fb55a8854abd514708be08 100644 (file)
@@ -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)
+               }
+       }
 }
index 6e6815ff13185c7ea1f40ba4173be32d56e2c4ee..95e91209184aa8afd2eccb34115c7a64f3c0e4c9 100644 (file)
@@ -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.
index 97f2a41eb767db439705134f0ad5fa53c1086c3f..a91c6da01d3c1b3b90fb20f8b85b182158c2c01c 100644 (file)
@@ -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 {
index 9592467d25baaefa853bdc2f1c87751b8fe4564f..00f4726cf7f6dce09cbda73c271eeea1babad756 100644 (file)
@@ -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) {
index 4d66f556767215d8abd4e88d6b161d8caf85efac..07c9e1d390c68db75a19a88a120d60e981594387 100644 (file)
@@ -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 ""
index 77a98b3e011f50cd77a593a581f24950b6b469e2..a81be6aefe8476714bf88f83bdcbb756e6f26f62 100644 (file)
@@ -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 {
index 3751839b287a9cfaeecb56601f5249e1b7f8e1db..6af5e1efcd5495dc4e3640cd38664d1cdcfadf6f 100644 (file)
@@ -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
 }
index 8e503dc35b8ea7782f1018e7e2fa8dea5b9aca4c..eb0f7fc0b07904dee3fa9a801cd8116f8f2291bd 100644 (file)
@@ -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
index f11582ac685584b4bdeccaaf047670b98b3737c8..e2a47a556a70bc14cec8c93f2334a449a78a91f5 100644 (file)
@@ -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
index 4684d9baf804eb0d45312389f01aee218e48d588..d8cf98840d71f33ec435ce2f3cf2d13699661294 100644 (file)
@@ -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"
index 11cc052829f1203ab7422a28be1bcfa50da7455e..30a5ed91c447fa86887257daf01d8ba38c836c55 100644 (file)
@@ -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);
index 23a56f3dc64f5ee932f93336b2f6a6483b7fb4a4..7b9b578e46c1ebce1b1f7ed45d2e0f1b9436f45f 100644 (file)
@@ -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);
index e805c90800038771e13ee725d925229b63732c54..b2e37f3915025ae57b873a1a9fafec50369e1b56 100644 (file)
@@ -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!");
        }
 
index b090169bbb7805c27cb99a0d7c3c49752df5a1a1..48ece55d18e1e778109416bd0e6950dfeec4b93a 100644 (file)
@@ -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);
index a937503a09a700eafe14e8b016bf5f7e92fe04d8..de72f42bc55f58fdb7d57a025aa4efcbf83fa91d 100644 (file)
@@ -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);
 
index d4973611d4eb7167f987ad6e4c7677aef82b7454..9a5cbdfed3b8a3b4db7128ce6249f6bc74e52978 100644 (file)
@@ -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.