mirror of git://gcc.gnu.org/git/gcc.git
libgo: Update Go library to master revision 15502/229081515358.
From-SVN: r195569
This commit is contained in:
parent
900f084036
commit
777133fefb
|
|
@ -1,4 +1,4 @@
|
||||||
921e53d4863c
|
229081515358
|
||||||
|
|
||||||
The first line of this file holds the Mercurial revision number of the
|
The first line of this file holds the Mercurial revision number of the
|
||||||
last merge done from the master library sources.
|
last merge done from the master library sources.
|
||||||
|
|
|
||||||
|
|
@ -153,5 +153,37 @@ func BenchmarkCodeUnmarshalReuse(b *testing.B) {
|
||||||
b.Fatal("Unmmarshal:", err)
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,25 +52,6 @@ import (
|
||||||
// an UnmarshalTypeError describing the earliest such error.
|
// an UnmarshalTypeError describing the earliest such error.
|
||||||
//
|
//
|
||||||
func Unmarshal(data []byte, v interface{}) 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)
|
d := new(decodeState).init(data)
|
||||||
|
|
||||||
// Quick check for well-formedness.
|
// Quick check for well-formedness.
|
||||||
|
|
|
||||||
|
|
@ -1059,12 +1059,33 @@ func TestUnmarshalTypeError(t *testing.T) {
|
||||||
for _, item := range decodeTypeErrorTests {
|
for _, item := range decodeTypeErrorTests {
|
||||||
err := Unmarshal([]byte(item.src), item.dest)
|
err := Unmarshal([]byte(item.src), item.dest)
|
||||||
if _, ok := err.(*UnmarshalTypeError); !ok {
|
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)
|
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.
|
// Test handling of unexported fields that should be ignored.
|
||||||
// Issue 4660
|
// Issue 4660
|
||||||
type unexportedFields struct {
|
type unexportedFields struct {
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
package json
|
package json
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
)
|
)
|
||||||
|
|
@ -58,6 +59,12 @@ func (dec *Decoder) Decode(v interface{}) error {
|
||||||
return err
|
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.
|
// readValue reads a JSON value into dec.buf.
|
||||||
// It returns the length of the encoding.
|
// It returns the length of the encoding.
|
||||||
func (dec *Decoder) readValue() (int, error) {
|
func (dec *Decoder) readValue() (int, error) {
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,10 @@ package json
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strings"
|
||||||
"testing"
|
"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 {
|
func nlines(s string, n int) string {
|
||||||
if n <= 0 {
|
if n <= 0 {
|
||||||
return ""
|
return ""
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,6 @@ package ssa
|
||||||
// TODO(adonovan): instead of creating several "unreachable" blocks
|
// TODO(adonovan): instead of creating several "unreachable" blocks
|
||||||
// per function in the Builder, reuse a single one (e.g. at Blocks[1])
|
// per function in the Builder, reuse a single one (e.g. at Blocks[1])
|
||||||
// to reduce garbage.
|
// 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 (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
@ -117,7 +113,7 @@ func fuseBlocks(f *Function, a *BasicBlock) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// A inherits B's successors
|
// 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.
|
// Fix up Preds links of all successors of B.
|
||||||
for _, c := range b.Succs {
|
for _, c := range b.Succs {
|
||||||
|
|
|
||||||
|
|
@ -151,16 +151,27 @@ func (f *Function) labelledBlock(label *ast.Ident) *lblock {
|
||||||
func (f *Function) addParam(name string, typ types.Type) *Parameter {
|
func (f *Function) addParam(name string, typ types.Type) *Parameter {
|
||||||
v := &Parameter{
|
v := &Parameter{
|
||||||
Name_: name,
|
Name_: name,
|
||||||
Type_: pointer(typ), // address of param
|
Type_: typ,
|
||||||
}
|
}
|
||||||
f.Params = append(f.Params, v)
|
f.Params = append(f.Params, v)
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Function) addObjParam(obj types.Object) *Parameter {
|
// addSpilledParam declares a parameter that is pre-spilled to the
|
||||||
p := f.addParam(obj.GetName(), obj.GetType())
|
// stack; the function body will load/store the spilled location.
|
||||||
f.objects[obj] = p
|
// Subsequent registerization will eliminate spills where possible.
|
||||||
return p
|
//
|
||||||
|
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.
|
// 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 {
|
if f.syntax.recvField != nil {
|
||||||
for _, field := range f.syntax.recvField.List {
|
for _, field := range f.syntax.recvField.List {
|
||||||
for _, n := range field.Names {
|
for _, n := range field.Names {
|
||||||
f.addObjParam(idents[n])
|
f.addSpilledParam(idents[n])
|
||||||
}
|
}
|
||||||
if field.Names == nil {
|
if field.Names == nil {
|
||||||
f.addParam(f.Signature.Recv.Name, f.Signature.Recv.Type)
|
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 {
|
if f.syntax.paramFields != nil {
|
||||||
for _, field := range f.syntax.paramFields.List {
|
for _, field := range f.syntax.paramFields.List {
|
||||||
for _, n := range field.Names {
|
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 {
|
func (f *Function) lookup(obj types.Object, escaping bool) Value {
|
||||||
if v, ok := f.objects[obj]; ok {
|
if v, ok := f.objects[obj]; ok {
|
||||||
if escaping {
|
if escaping {
|
||||||
switch v := v.(type) {
|
// Walk up the chain of Captures.
|
||||||
case *Capture:
|
x := v
|
||||||
// TODO(adonovan): fix: we must support this case.
|
for {
|
||||||
// Requires copying to a 'new' Alloc.
|
if c, ok := x.(*Capture); ok {
|
||||||
fmt.Fprintln(os.Stderr, "Error: escaping reference to Capture")
|
x = c.Outer
|
||||||
case *Parameter:
|
} else {
|
||||||
v.Heap = true
|
break
|
||||||
case *Alloc:
|
}
|
||||||
v.Heap = true
|
|
||||||
default:
|
|
||||||
panic(fmt.Sprintf("Unexpected Function.objects kind: %T", v))
|
|
||||||
}
|
}
|
||||||
|
// 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)
|
return v // function-local var (address)
|
||||||
}
|
}
|
||||||
|
|
@ -340,7 +351,7 @@ func (f *Function) emit(instr Instruction) Value {
|
||||||
func (f *Function) DumpTo(w io.Writer) {
|
func (f *Function) DumpTo(w io.Writer) {
|
||||||
fmt.Fprintf(w, "# Name: %s\n", f.FullName())
|
fmt.Fprintf(w, "# Name: %s\n", f.FullName())
|
||||||
fmt.Fprintf(w, "# Declared at %s\n", f.Prog.Files.Position(f.Pos))
|
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 {
|
if f.Enclosing != nil {
|
||||||
fmt.Fprintf(w, "# Parent: %s\n", f.Enclosing.Name())
|
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),
|
Name: fmt.Sprintf("%d.%s", len(f.Blocks), name),
|
||||||
Func: f,
|
Func: f,
|
||||||
}
|
}
|
||||||
|
b.Succs = b.succs2[:0]
|
||||||
f.Blocks = append(f.Blocks, b)
|
f.Blocks = append(f.Blocks, b)
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -246,19 +246,20 @@ type Function struct {
|
||||||
// instructions, respectively).
|
// instructions, respectively).
|
||||||
//
|
//
|
||||||
type BasicBlock struct {
|
type BasicBlock struct {
|
||||||
Name string // label; no semantic significance
|
Name string // label; no semantic significance
|
||||||
Func *Function // containing function
|
Func *Function // containing function
|
||||||
Instrs []Instruction // instructions in order
|
Instrs []Instruction // instructions in order
|
||||||
Preds, Succs []*BasicBlock // predecessors and successors
|
Preds, Succs []*BasicBlock // predecessors and successors
|
||||||
|
succs2 [2]*BasicBlock // initial space for Succs.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pure values ----------------------------------------
|
// Pure values ----------------------------------------
|
||||||
|
|
||||||
// A Capture is a pointer to a lexically enclosing local variable.
|
// A Capture is a pointer to a lexically enclosing local variable.
|
||||||
//
|
//
|
||||||
// The referent of a capture is a Parameter, Alloc or another Capture
|
// The referent of a capture is an Alloc or another Capture and is
|
||||||
// and is always considered potentially escaping, so Captures are
|
// always considered potentially escaping, so Captures are always
|
||||||
// always addresses in the heap, and have pointer types.
|
// addresses in the heap, and have pointer types.
|
||||||
//
|
//
|
||||||
type Capture struct {
|
type Capture struct {
|
||||||
Outer Value // the Value captured from the enclosing context.
|
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.
|
// 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 {
|
type Parameter struct {
|
||||||
Name_ string
|
Name_ string
|
||||||
Type_ *types.Pointer
|
Type_ types.Type
|
||||||
Heap bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Literal represents a literal nil, boolean, string or numeric
|
// A Literal represents a literal nil, boolean, string or numeric
|
||||||
|
|
|
||||||
|
|
@ -321,13 +321,7 @@ func (p *Package) IsCommand() bool {
|
||||||
// ImportDir is like Import but processes the Go package found in
|
// ImportDir is like Import but processes the Go package found in
|
||||||
// the named directory.
|
// the named directory.
|
||||||
func (ctxt *Context) ImportDir(dir string, mode ImportMode) (*Package, error) {
|
func (ctxt *Context) ImportDir(dir string, mode ImportMode) (*Package, error) {
|
||||||
p, err := ctxt.Import(".", dir, mode)
|
return 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NoGoError is the error used by Import to describe a directory
|
// NoGoError is the error used by Import to describe a directory
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@
|
||||||
package build
|
package build
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"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) {
|
func TestShouldBuild(t *testing.T) {
|
||||||
const file1 = "// +build tag1\n\n" +
|
const file1 = "// +build tag1\n\n" +
|
||||||
"package main\n"
|
"package main\n"
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,11 @@ runtime_traceback ()
|
||||||
int32 c;
|
int32 c;
|
||||||
|
|
||||||
c = runtime_callers (1, pcbuf, sizeof pcbuf / sizeof pcbuf[0]);
|
c = runtime_callers (1, pcbuf, sizeof pcbuf / sizeof pcbuf[0]);
|
||||||
runtime_printtrace (pcbuf, c);
|
runtime_printtrace (pcbuf, c, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
runtime_printtrace (uintptr *pcbuf, int32 c)
|
runtime_printtrace (uintptr *pcbuf, int32 c, bool current)
|
||||||
{
|
{
|
||||||
int32 i;
|
int32 i;
|
||||||
|
|
||||||
|
|
@ -32,7 +32,7 @@ runtime_printtrace (uintptr *pcbuf, int32 c)
|
||||||
intgo line;
|
intgo line;
|
||||||
|
|
||||||
if (__go_file_line (pcbuf[i], &fn, &file, &line)
|
if (__go_file_line (pcbuf[i], &fn, &file, &line)
|
||||||
&& runtime_showframe (fn))
|
&& runtime_showframe (fn, current))
|
||||||
{
|
{
|
||||||
runtime_printf ("%S\n", fn);
|
runtime_printf ("%S\n", fn);
|
||||||
runtime_printf ("\t%S:%D\n", file, (int64) line);
|
runtime_printf ("\t%S:%D\n", file, (int64) line);
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,11 @@ runtime_dopanic(int32 unused __attribute__ ((unused)))
|
||||||
void
|
void
|
||||||
runtime_throw(const char *s)
|
runtime_throw(const char *s)
|
||||||
{
|
{
|
||||||
|
M *mp;
|
||||||
|
|
||||||
|
mp = runtime_m();
|
||||||
|
if(mp->throwing == 0)
|
||||||
|
mp->throwing = 1;
|
||||||
runtime_startpanic();
|
runtime_startpanic();
|
||||||
runtime_printf("fatal error: %s\n", s);
|
runtime_printf("fatal error: %s\n", s);
|
||||||
runtime_dopanic(0);
|
runtime_dopanic(0);
|
||||||
|
|
|
||||||
|
|
@ -528,6 +528,7 @@ runtime_main(void)
|
||||||
setmcpumax(runtime_gomaxprocs);
|
setmcpumax(runtime_gomaxprocs);
|
||||||
runtime_sched.init = true;
|
runtime_sched.init = true;
|
||||||
scvg = __go_go(runtime_MHeap_Scavenger, nil);
|
scvg = __go_go(runtime_MHeap_Scavenger, nil);
|
||||||
|
scvg->issystem = true;
|
||||||
main_init();
|
main_init();
|
||||||
runtime_sched.init = false;
|
runtime_sched.init = false;
|
||||||
if(!runtime_sched.lockmain)
|
if(!runtime_sched.lockmain)
|
||||||
|
|
@ -638,12 +639,16 @@ void
|
||||||
runtime_tracebackothers(G * volatile me)
|
runtime_tracebackothers(G * volatile me)
|
||||||
{
|
{
|
||||||
G * volatile gp;
|
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) {
|
for(gp = runtime_allg; gp != nil; gp = gp->alllink) {
|
||||||
if(gp == me || gp->status == Gdead)
|
if(gp == me || gp->status == Gdead)
|
||||||
continue;
|
continue;
|
||||||
|
if(gp->issystem && traceback < 2)
|
||||||
|
continue;
|
||||||
runtime_printf("\n");
|
runtime_printf("\n");
|
||||||
runtime_goroutineheader(gp);
|
runtime_goroutineheader(gp);
|
||||||
|
|
||||||
|
|
@ -661,7 +666,7 @@ runtime_tracebackothers(G * volatile me)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
gp->traceback = &traceback;
|
gp->traceback = &tb;
|
||||||
|
|
||||||
#ifdef USING_SPLIT_STACK
|
#ifdef USING_SPLIT_STACK
|
||||||
__splitstack_getcontext(&me->stack_context[0]);
|
__splitstack_getcontext(&me->stack_context[0]);
|
||||||
|
|
@ -672,7 +677,7 @@ runtime_tracebackothers(G * volatile me)
|
||||||
runtime_gogo(gp);
|
runtime_gogo(gp);
|
||||||
}
|
}
|
||||||
|
|
||||||
runtime_printtrace(traceback.pcbuf, traceback.c);
|
runtime_printtrace(tb.pcbuf, tb.c, false);
|
||||||
runtime_goroutinetrailer(gp);
|
runtime_goroutinetrailer(gp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -975,6 +980,7 @@ top:
|
||||||
if((scvg == nil && runtime_sched.grunning == 0) ||
|
if((scvg == nil && runtime_sched.grunning == 0) ||
|
||||||
(scvg != nil && runtime_sched.grunning == 1 && runtime_sched.gwait == 0 &&
|
(scvg != nil && runtime_sched.grunning == 1 && runtime_sched.gwait == 0 &&
|
||||||
(scvg->status == Grunning || scvg->status == Gsyscall))) {
|
(scvg->status == Grunning || scvg->status == Gsyscall))) {
|
||||||
|
m->throwing = -1; // do not dump full stacks
|
||||||
runtime_throw("all goroutines are asleep - deadlock!");
|
runtime_throw("all goroutines are asleep - deadlock!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -132,10 +132,12 @@ runtime_cputicks(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
runtime_showframe(String s)
|
runtime_showframe(String s, bool current)
|
||||||
{
|
{
|
||||||
static int32 traceback = -1;
|
static int32 traceback = -1;
|
||||||
|
|
||||||
|
if(current && runtime_m()->throwing > 0)
|
||||||
|
return 1;
|
||||||
if(traceback < 0)
|
if(traceback < 0)
|
||||||
traceback = runtime_gotraceback();
|
traceback = runtime_gotraceback();
|
||||||
return traceback > 1 || (__builtin_memchr(s.str, '.', s.len) != nil && __builtin_memcmp(s.str, "runtime.", 7) != 0);
|
return traceback > 1 || (__builtin_memchr(s.str, '.', s.len) != nil && __builtin_memcmp(s.str, "runtime.", 7) != 0);
|
||||||
|
|
|
||||||
|
|
@ -178,6 +178,7 @@ struct G
|
||||||
G* schedlink;
|
G* schedlink;
|
||||||
bool readyonstop;
|
bool readyonstop;
|
||||||
bool ispanic;
|
bool ispanic;
|
||||||
|
bool issystem;
|
||||||
int8 raceignore; // ignore race detection events
|
int8 raceignore; // ignore race detection events
|
||||||
M* m; // for debuggers, but offset not hard-coded
|
M* m; // for debuggers, but offset not hard-coded
|
||||||
M* lockedm;
|
M* lockedm;
|
||||||
|
|
@ -208,6 +209,7 @@ struct M
|
||||||
G* curg; // current running goroutine
|
G* curg; // current running goroutine
|
||||||
int32 id;
|
int32 id;
|
||||||
int32 mallocing;
|
int32 mallocing;
|
||||||
|
int32 throwing;
|
||||||
int32 gcing;
|
int32 gcing;
|
||||||
int32 locks;
|
int32 locks;
|
||||||
int32 nomemprof;
|
int32 nomemprof;
|
||||||
|
|
@ -389,7 +391,7 @@ void runtime_goroutineheader(G*);
|
||||||
void runtime_goroutinetrailer(G*);
|
void runtime_goroutinetrailer(G*);
|
||||||
void runtime_traceback();
|
void runtime_traceback();
|
||||||
void runtime_tracebackothers(G*);
|
void runtime_tracebackothers(G*);
|
||||||
void runtime_printtrace(uintptr*, int32);
|
void runtime_printtrace(uintptr*, int32, bool);
|
||||||
String runtime_gostringnocopy(const byte*);
|
String runtime_gostringnocopy(const byte*);
|
||||||
void* runtime_mstart(void*);
|
void* runtime_mstart(void*);
|
||||||
G* runtime_malg(int32, byte**, size_t*);
|
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_LockOSThread(void) __asm__ (GOSYM_PREFIX "runtime.LockOSThread");
|
||||||
void runtime_UnlockOSThread(void) __asm__ (GOSYM_PREFIX "runtime.UnlockOSThread");
|
void runtime_UnlockOSThread(void) __asm__ (GOSYM_PREFIX "runtime.UnlockOSThread");
|
||||||
|
|
||||||
bool runtime_showframe(String);
|
bool runtime_showframe(String, bool);
|
||||||
|
|
||||||
uintptr runtime_memlimit(void);
|
uintptr runtime_memlimit(void);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -110,8 +110,10 @@ addtimer(Timer *t)
|
||||||
runtime_ready(timers.timerproc);
|
runtime_ready(timers.timerproc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(timers.timerproc == nil)
|
if(timers.timerproc == nil) {
|
||||||
timers.timerproc = __go_go(timerproc, nil);
|
timers.timerproc = __go_go(timerproc, nil);
|
||||||
|
timers.timerproc->issystem = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete timer t from the heap.
|
// Delete timer t from the heap.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue