Patchwork libgo patch committed: Update libgo again

login
register
mail settings
Submitter Ian Taylor
Date Jan. 30, 2013, 1:37 a.m.
Message ID <mcrvcafv4bc.fsf@google.com>
Download mbox | patch
Permalink /patch/216744/
State New
Headers show

Comments

Ian Taylor - Jan. 30, 2013, 1:37 a.m.
Unfortunately I updated the last libgo version from sources that a bug
in the JSON package.  This patch updates libgo again to the new current
sources, fixing the bug.  Bootstrapped and ran Go testsuite on
x86_64-unknown-linux-gnu.  Committed to mainline.

Ian

Patch

diff -r 6141bbace093 libgo/MERGE
--- a/libgo/MERGE	Tue Jan 29 10:59:14 2013 -0800
+++ b/libgo/MERGE	Tue Jan 29 17:29:12 2013 -0800
@@ -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 -r 6141bbace093 libgo/go/encoding/json/bench_test.go
--- a/libgo/go/encoding/json/bench_test.go	Tue Jan 29 10:59:14 2013 -0800
+++ b/libgo/go/encoding/json/bench_test.go	Tue Jan 29 17:29:12 2013 -0800
@@ -153,5 +153,37 @@ 
 			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 -r 6141bbace093 libgo/go/encoding/json/decode.go
--- a/libgo/go/encoding/json/decode.go	Tue Jan 29 10:59:14 2013 -0800
+++ b/libgo/go/encoding/json/decode.go	Tue Jan 29 17:29:12 2013 -0800
@@ -52,25 +52,6 @@ 
 // 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 -r 6141bbace093 libgo/go/encoding/json/decode_test.go
--- a/libgo/go/encoding/json/decode_test.go	Tue Jan 29 10:59:14 2013 -0800
+++ b/libgo/go/encoding/json/decode_test.go	Tue Jan 29 17:29:12 2013 -0800
@@ -1059,12 +1059,33 @@ 
 	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 -r 6141bbace093 libgo/go/encoding/json/stream.go
--- a/libgo/go/encoding/json/stream.go	Tue Jan 29 10:59:14 2013 -0800
+++ b/libgo/go/encoding/json/stream.go	Tue Jan 29 17:29:12 2013 -0800
@@ -5,6 +5,7 @@ 
 package json
 
 import (
+	"bytes"
 	"errors"
 	"io"
 )
@@ -58,6 +59,12 @@ 
 	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 -r 6141bbace093 libgo/go/encoding/json/stream_test.go
--- a/libgo/go/encoding/json/stream_test.go	Tue Jan 29 10:59:14 2013 -0800
+++ b/libgo/go/encoding/json/stream_test.go	Tue Jan 29 17:29:12 2013 -0800
@@ -6,8 +6,10 @@ 
 
 import (
 	"bytes"
+	"io/ioutil"
 	"net"
 	"reflect"
+	"strings"
 	"testing"
 )
 
@@ -83,6 +85,28 @@ 
 	}
 }
 
+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 -r 6141bbace093 libgo/go/exp/ssa/blockopt.go
--- a/libgo/go/exp/ssa/blockopt.go	Tue Jan 29 10:59:14 2013 -0800
+++ b/libgo/go/exp/ssa/blockopt.go	Tue Jan 29 17:29:12 2013 -0800
@@ -5,10 +5,6 @@ 
 // 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 @@ 
 	}
 
 	// 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 -r 6141bbace093 libgo/go/exp/ssa/func.go
--- a/libgo/go/exp/ssa/func.go	Tue Jan 29 10:59:14 2013 -0800
+++ b/libgo/go/exp/ssa/func.go	Tue Jan 29 17:29:12 2013 -0800
@@ -151,16 +151,27 @@ 
 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 @@ 
 	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 @@ 
 	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) 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) 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 @@ 
 		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 -r 6141bbace093 libgo/go/exp/ssa/ssa.go
--- a/libgo/go/exp/ssa/ssa.go	Tue Jan 29 10:59:14 2013 -0800
+++ b/libgo/go/exp/ssa/ssa.go	Tue Jan 29 17:29:12 2013 -0800
@@ -246,19 +246,20 @@ 
 // 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 @@ 
 
 // 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 -r 6141bbace093 libgo/go/go/build/build.go
--- a/libgo/go/go/build/build.go	Tue Jan 29 10:59:14 2013 -0800
+++ b/libgo/go/go/build/build.go	Tue Jan 29 17:29:12 2013 -0800
@@ -321,13 +321,7 @@ 
 // 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 -r 6141bbace093 libgo/go/go/build/build_test.go
--- a/libgo/go/go/build/build_test.go	Tue Jan 29 10:59:14 2013 -0800
+++ b/libgo/go/go/build/build_test.go	Tue Jan 29 17:29:12 2013 -0800
@@ -5,7 +5,6 @@ 
 package build
 
 import (
-	"fmt"
 	"os"
 	"path/filepath"
 	"runtime"
@@ -90,17 +89,6 @@ 
 	}
 }
 
-// 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 -r 6141bbace093 libgo/runtime/go-traceback.c
--- a/libgo/runtime/go-traceback.c	Tue Jan 29 10:59:14 2013 -0800
+++ b/libgo/runtime/go-traceback.c	Tue Jan 29 17:29:12 2013 -0800
@@ -17,11 +17,11 @@ 
   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 @@ 
       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 -r 6141bbace093 libgo/runtime/panic.c
--- a/libgo/runtime/panic.c	Tue Jan 29 10:59:14 2013 -0800
+++ b/libgo/runtime/panic.c	Tue Jan 29 17:29:12 2013 -0800
@@ -86,6 +86,11 @@ 
 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 -r 6141bbace093 libgo/runtime/proc.c
--- a/libgo/runtime/proc.c	Tue Jan 29 10:59:14 2013 -0800
+++ b/libgo/runtime/proc.c	Tue Jan 29 17:29:12 2013 -0800
@@ -528,6 +528,7 @@ 
 	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 @@ 
 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 @@ 
 			continue;
 		}
 
-		gp->traceback = &traceback;
+		gp->traceback = &tb;
 
 #ifdef USING_SPLIT_STACK
 		__splitstack_getcontext(&me->stack_context[0]);
@@ -672,7 +677,7 @@ 
 			runtime_gogo(gp);
 		}
 
-		runtime_printtrace(traceback.pcbuf, traceback.c);
+		runtime_printtrace(tb.pcbuf, tb.c, false);
 		runtime_goroutinetrailer(gp);
 	}
 }
@@ -975,6 +980,7 @@ 
 	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 -r 6141bbace093 libgo/runtime/runtime.c
--- a/libgo/runtime/runtime.c	Tue Jan 29 10:59:14 2013 -0800
+++ b/libgo/runtime/runtime.c	Tue Jan 29 17:29:12 2013 -0800
@@ -132,10 +132,12 @@ 
 }
 
 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 -r 6141bbace093 libgo/runtime/runtime.h
--- a/libgo/runtime/runtime.h	Tue Jan 29 10:59:14 2013 -0800
+++ b/libgo/runtime/runtime.h	Tue Jan 29 17:29:12 2013 -0800
@@ -178,6 +178,7 @@ 
 	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 @@ 
 	G*	curg;		// current running goroutine
 	int32	id;
 	int32	mallocing;
+	int32	throwing;
 	int32	gcing;
 	int32	locks;
 	int32	nomemprof;
@@ -389,7 +391,7 @@ 
 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_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 -r 6141bbace093 libgo/runtime/time.goc
--- a/libgo/runtime/time.goc	Tue Jan 29 10:59:14 2013 -0800
+++ b/libgo/runtime/time.goc	Tue Jan 29 17:29:12 2013 -0800
@@ -110,8 +110,10 @@ 
 			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.