diff mbox series

Go patch committed: Update to Go1.10beta1

Message ID CAOyqgcVjfA5w6qxyiCL+M=eb+Mu92nbqWSR4v6c9a1JkHHSZ7w@mail.gmail.com
State New
Headers show
Series Go patch committed: Update to Go1.10beta1 | expand

Commit Message

Ian Lance Taylor Jan. 9, 2018, 1:23 a.m. UTC
This patch updates libgo to the Go1.10beta1 release.  The final Go
1.10 release is expected around February 1, so it's not clear how the
release timing is going to work with GCC 8.  In any case this updates
GCC to something pretty close to the final Go 1.10 release.

A few changes to the frontend were required to match changes in the
runtime map code, and to handle some no-writebarrier cases in the
runtime package.

As usual with these updates the complete patch is too large to include
in this e-mail message.  I've just included the changes to
gccgo-specific code.

Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu.  Committed
to mainline.

Ian

2018-01-08  Ian Lance Taylor  <iant@golang.org>

* Makefile.am (go_cmd_vet_files): New variable.
(go_cmd_buildid_files, go_cmd_test2json_files): New variables.
(s-zdefaultcc): Change from constants to functions.
(noinst_PROGRAMS): Add vet, buildid, and test2json.
(cgo$(EXEEXT)): Link against $(LIBGOTOOL).
(vet$(EXEEXT)): New target.
(buildid$(EXEEXT)): New target.
(test2json$(EXEEXT)): New target.
(install-exec-local): Install all $(noinst_PROGRAMS).
(uninstall-local): Uninstasll all $(noinst_PROGRAMS).
(check-go-tool): Depend on $(noinst_PROGRAMS).  Copy down
objabi.go.
(check-runtime): Depend on $(noinst_PROGRAMS).
(check-cgo-test, check-carchive-test): Likewise.
(check-vet): New target.
(check): Depend on check-vet.  Look at cmd_vet-testlog.
(.PHONY): Add check-vet.
* Makefile.in: Rebuild.

Comments

Rainer Orth Jan. 9, 2018, 8:26 p.m. UTC | #1
Hi Ian,

> This patch updates libgo to the Go1.10beta1 release.  The final Go
> 1.10 release is expected around February 1, so it's not clear how the
> release timing is going to work with GCC 8.  In any case this updates
> GCC to something pretty close to the final Go 1.10 release.
>
> A few changes to the frontend were required to match changes in the
> runtime map code, and to handle some no-writebarrier cases in the
> runtime package.
>
> As usual with these updates the complete patch is too large to include
> in this e-mail message.  I've just included the changes to
> gccgo-specific code.
>
> Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu.  Committed
> to mainline.

the patch broke Solaris bootstrap:

mv: cannot stat 'os/signal/internal/pty.s-gox.tmp': No such file or directory
make[4]: *** [Makefile:3348: os/signal/internal/pty.s-gox] Error 1
make[4]: *** Waiting for unfinished jobs....

Fixed trivially as follows, which allowed the build to complete.  make
check still running...

	Rainer
Ian Lance Taylor Jan. 9, 2018, 9:43 p.m. UTC | #2
On Tue, Jan 9, 2018 at 12:26 PM, Rainer Orth
<ro@cebitec.uni-bielefeld.de> wrote:
> Hi Ian,
>
>> This patch updates libgo to the Go1.10beta1 release.  The final Go
>> 1.10 release is expected around February 1, so it's not clear how the
>> release timing is going to work with GCC 8.  In any case this updates
>> GCC to something pretty close to the final Go 1.10 release.
>>
>> A few changes to the frontend were required to match changes in the
>> runtime map code, and to handle some no-writebarrier cases in the
>> runtime package.
>>
>> As usual with these updates the complete patch is too large to include
>> in this e-mail message.  I've just included the changes to
>> gccgo-specific code.
>>
>> Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu.  Committed
>> to mainline.
>
> the patch broke Solaris bootstrap:
>
> mv: cannot stat 'os/signal/internal/pty.s-gox.tmp': No such file or directory
> make[4]: *** [Makefile:3348: os/signal/internal/pty.s-gox] Error 1
> make[4]: *** Waiting for unfinished jobs....
>
> Fixed trivially as follows, which allowed the build to complete.  make
> check still running...

Thanks.  Patch committed.

Ian
Rainer Orth Jan. 10, 2018, 11:44 a.m. UTC | #3
Hi Ian,

>> the patch broke Solaris bootstrap:
>>
>> mv: cannot stat 'os/signal/internal/pty.s-gox.tmp': No such file or directory
>> make[4]: *** [Makefile:3348: os/signal/internal/pty.s-gox] Error 1
>> make[4]: *** Waiting for unfinished jobs....
>>
>> Fixed trivially as follows, which allowed the build to complete.  make
>> check still running...
>
> Thanks.  Patch committed.

thanks.  Testing has now concluded as well.  x86 results are good (no
regressions except for cmd/internal/buildid which fails on Linux, too),
as are 64-bit sparc results.  However, 32-bit sparc shows lots of
execution failures:

* There's

FAIL: go.go-torture/execute/chan-1.go execution,  -O0

  at all optimization levels, with

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send]:
main.main
        /vol/gcc/src/hg/trunk/local/gcc/testsuite/go.go-torture/execute/chan-1.go:5

* but the vast majority of failures are like

FAIL: go.test/test/blank.go execution,  -O2 -g 

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=1 addr=44 pc=4259573728]

goroutine 1 [running]:
panic
        /vol/gcc/src/hg/trunk/local/libgo/go/runtime/panic.go:554
unicode..import
        /vol/gcc/src/hg/trunk/local/libgo/go/unicode/tables.go:15

Thread 2 received signal SIGSEGV, Segmentation fault.
[Switching to Thread 1 (LWP 1)]
runtime.makemap (
    t=t@entry=0xfef645b0 <__go_td_MN6_string__pN18_unicode.RangeTable>, 
    hint=0, h=0x24)
    at /vol/gcc/src/hg/trunk/local/libgo/go/runtime/hashmap.go:329
329             h.hash0 = fastrand()

=> 0xfead76bc <runtime.makemap+96>:     st  %o0, [ %i2 + 8 ]
(gdb) p $i2
$1 = 36

(gdb) where
#0  runtime.makemap (
    t=t@entry=0xfef645b0 <__go_td_MN6_string__pN18_unicode.RangeTable>, 
    hint=0, h=0x24)
    at /vol/gcc/src/hg/trunk/local/libgo/go/runtime/hashmap.go:329
#1  0xfe63efe0 in __go_construct_map (
    type=type@entry=0xfef645b0 <__go_td_MN6_string__pN18_unicode.RangeTable>, 
    count=count@entry=36, entry_size=entry_size@entry=12, 
    val_offset=val_offset@entry=8, ventries=ventries@entry=0x105815f4)
    at /vol/gcc/src/hg/trunk/local/libgo/runtime/go-construct-map.c:32
#2  0xfeb87b34 in unicode..import ()
    at /vol/gcc/src/hg/trunk/local/libgo/go/unicode/tables.go:15
#3  0x00014984 in main.init ()
    at /vol/gcc/src/hg/trunk/local/gcc/testsuite/go.test/test/blank.go:9
#4  0xfeac3960 in runtime.main ()
    at /vol/gcc/src/hg/trunk/local/libgo/go/runtime/proc.go:205
#5  0xfeac1734 in runtime.kickoff ()
    at /vol/gcc/src/hg/trunk/local/libgo/go/runtime/proc.go:1157
#6  0xfda8b24c in __makecontext_v2 () from /lib/libc.so.1

	Rainer
Ian Lance Taylor Jan. 10, 2018, 1:42 p.m. UTC | #4
On Wed, Jan 10, 2018 at 3:44 AM, Rainer Orth
<ro@cebitec.uni-bielefeld.de> wrote:
>
>>> the patch broke Solaris bootstrap:
>>>
>>> mv: cannot stat 'os/signal/internal/pty.s-gox.tmp': No such file or directory
>>> make[4]: *** [Makefile:3348: os/signal/internal/pty.s-gox] Error 1
>>> make[4]: *** Waiting for unfinished jobs....
>>>
>>> Fixed trivially as follows, which allowed the build to complete.  make
>>> check still running...
>>
>> Thanks.  Patch committed.
>
> thanks.  Testing has now concluded as well.  x86 results are good (no
> regressions except for cmd/internal/buildid which fails on Linux, too),
> as are 64-bit sparc results.  However, 32-bit sparc shows lots of
> execution failures:
>
> * There's
>
> FAIL: go.go-torture/execute/chan-1.go execution,  -O0
>
>   at all optimization levels, with
>
> fatal error: all goroutines are asleep - deadlock!
>
> goroutine 1 [chan send]:
> main.main
>         /vol/gcc/src/hg/trunk/local/gcc/testsuite/go.go-torture/execute/chan-1.go:5
>
> * but the vast majority of failures are like
>
> FAIL: go.test/test/blank.go execution,  -O2 -g
>
> panic: runtime error: invalid memory address or nil pointer dereference
> [signal SIGSEGV: segmentation violation code=1 addr=44 pc=4259573728]
>
> goroutine 1 [running]:
> panic
>         /vol/gcc/src/hg/trunk/local/libgo/go/runtime/panic.go:554
> unicode..import
>         /vol/gcc/src/hg/trunk/local/libgo/go/unicode/tables.go:15
>
> Thread 2 received signal SIGSEGV, Segmentation fault.
> [Switching to Thread 1 (LWP 1)]
> runtime.makemap (
>     t=t@entry=0xfef645b0 <__go_td_MN6_string__pN18_unicode.RangeTable>,
>     hint=0, h=0x24)
>     at /vol/gcc/src/hg/trunk/local/libgo/go/runtime/hashmap.go:329
> 329             h.hash0 = fastrand()
>
> => 0xfead76bc <runtime.makemap+96>:     st  %o0, [ %i2 + 8 ]
> (gdb) p $i2
> $1 = 36
>
> (gdb) where
> #0  runtime.makemap (
>     t=t@entry=0xfef645b0 <__go_td_MN6_string__pN18_unicode.RangeTable>,
>     hint=0, h=0x24)
>     at /vol/gcc/src/hg/trunk/local/libgo/go/runtime/hashmap.go:329
> #1  0xfe63efe0 in __go_construct_map (
>     type=type@entry=0xfef645b0 <__go_td_MN6_string__pN18_unicode.RangeTable>,
>     count=count@entry=36, entry_size=entry_size@entry=12,
>     val_offset=val_offset@entry=8, ventries=ventries@entry=0x105815f4)
>     at /vol/gcc/src/hg/trunk/local/libgo/runtime/go-construct-map.c:32
> #2  0xfeb87b34 in unicode..import ()
>     at /vol/gcc/src/hg/trunk/local/libgo/go/unicode/tables.go:15
> #3  0x00014984 in main.init ()
>     at /vol/gcc/src/hg/trunk/local/gcc/testsuite/go.test/test/blank.go:9
> #4  0xfeac3960 in runtime.main ()
>     at /vol/gcc/src/hg/trunk/local/libgo/go/runtime/proc.go:205
> #5  0xfeac1734 in runtime.kickoff ()
>     at /vol/gcc/src/hg/trunk/local/libgo/go/runtime/proc.go:1157
> #6  0xfda8b24c in __makecontext_v2 () from /lib/libc.so.1

Whoops, there's a bug on big-endian 32-bit systems.  I'm testing
https://golang.org/cl/87135.

Ian
Ian Lance Taylor Jan. 10, 2018, 2:57 p.m. UTC | #5
On Wed, Jan 10, 2018 at 3:44 AM, Rainer Orth
<ro@cebitec.uni-bielefeld.de> wrote:
>
> thanks.  Testing has now concluded as well.  x86 results are good (no
> regressions except for cmd/internal/buildid which fails on Linux, too),
> as are 64-bit sparc results.

The cmd/internal/buildid test does pass on my system.  What are you seeing?

Ian
Ian Lance Taylor Jan. 10, 2018, 3:04 p.m. UTC | #6
On Wed, Jan 10, 2018 at 5:42 AM, Ian Lance Taylor <iant@golang.org> wrote:
>
> Whoops, there's a bug on big-endian 32-bit systems.  I'm testing
> https://golang.org/cl/87135.

Committed as follows.

Ian
Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE	(revision 256419)
+++ gcc/go/gofrontend/MERGE	(working copy)
@@ -1,4 +1,4 @@
-c18c6bd80e0995827ad3396eb1c2401451de88fd
+c22eb29a62b4fd72ad2ea09ebe5fcea5b8ed78b8
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
Index: libgo/runtime/go-construct-map.c
===================================================================
--- libgo/runtime/go-construct-map.c	(revision 256366)
+++ libgo/runtime/go-construct-map.c	(working copy)
@@ -11,8 +11,8 @@
 #include "runtime.h"
 #include "go-type.h"
 
-extern void *makemap (const struct __go_map_type *, int64_t hint,
-		      void *, void *)
+extern void *makemap (const struct __go_map_type *, intgo hint,
+		      void *)
   __asm__ (GOSYM_PREFIX "runtime.makemap");
 
 extern void *mapassign (const struct __go_map_type *, void *hmap,
@@ -29,7 +29,7 @@ __go_construct_map (const struct __go_ma
   uintptr_t i;
   void *p;
 
-  ret = makemap(type, (int64_t) count, NULL, NULL);
+  ret = makemap(type, (intgo) count, NULL);
 
   entries = (const unsigned char *) ventries;
   for (i = 0; i < count; ++i)
Rainer Orth Jan. 10, 2018, 3:43 p.m. UTC | #7
Hi Ian,

> On Wed, Jan 10, 2018 at 3:44 AM, Rainer Orth
> <ro@cebitec.uni-bielefeld.de> wrote:
>>
>> thanks.  Testing has now concluded as well.  x86 results are good (no
>> regressions except for cmd/internal/buildid which fails on Linux, too),
>> as are 64-bit sparc results.
>
> The cmd/internal/buildid test does pass on my system.  What are you seeing?

the log shows

--- FAIL: TestReadFile (0.01s)
        buildid_test.go:40: ReadFile(testdata/p.a) = "", open testdata/p.a: no such file or directory, want "abcdefghijklmnopqrstuvwxyz.1234567890123456789012345678901234567890123456789012345678901234", nil
        buildid_test.go:47: ReadFile(testdata/p.a) [readSize=2k] = "", open testdata/p.a: no such file or directory, want "abcdefghijklmnopqrstuvwxyz.1234567890123456789012345678901234567890123456789012345678901234", nil
        buildid_test.go:52: open testdata/p.a: no such file or directory

libgo/go/cmd/internal/buildid/testdata/p.a is just missing.

	Rainer
Ian Lance Taylor Jan. 10, 2018, 6:05 p.m. UTC | #8
On Wed, Jan 10, 2018 at 7:43 AM, Rainer Orth
<ro@cebitec.uni-bielefeld.de> wrote:
> Hi Ian,
>
>> On Wed, Jan 10, 2018 at 3:44 AM, Rainer Orth
>> <ro@cebitec.uni-bielefeld.de> wrote:
>>>
>>> thanks.  Testing has now concluded as well.  x86 results are good (no
>>> regressions except for cmd/internal/buildid which fails on Linux, too),
>>> as are 64-bit sparc results.
>>
>> The cmd/internal/buildid test does pass on my system.  What are you seeing?
>
> the log shows
>
> --- FAIL: TestReadFile (0.01s)
>         buildid_test.go:40: ReadFile(testdata/p.a) = "", open testdata/p.a: no such file or directory, want "abcdefghijklmnopqrstuvwxyz.1234567890123456789012345678901234567890123456789012345678901234", nil
>         buildid_test.go:47: ReadFile(testdata/p.a) [readSize=2k] = "", open testdata/p.a: no such file or directory, want "abcdefghijklmnopqrstuvwxyz.1234567890123456789012345678901234567890123456789012345678901234", nil
>         buildid_test.go:52: open testdata/p.a: no such file or directory
>
> libgo/go/cmd/internal/buildid/testdata/p.a is just missing.

Ah.  Turns out it was being ignored by the default global-ignores
setting in the Subversion configuration, which ignores all .a files.
I found a couple of other .a files that were missing in the gofrontend
git repo (dropped by merge.sh) and copied them over.  Then I committed
all the missing .a files to the gcc Subversion repository (there were
five missing files; the others were not causing a test failure).

Ian
Rainer Orth Jan. 11, 2018, 9:46 a.m. UTC | #9
Hi Ian,

> On Wed, Jan 10, 2018 at 5:42 AM, Ian Lance Taylor <iant@golang.org> wrote:
>>
>> Whoops, there's a bug on big-endian 32-bit systems.  I'm testing
>> https://golang.org/cl/87135.
>
> Committed as follows.

thanks, that fixed quite a lot of the failures.

However, many others remain, too many to report here.  I've filed PR
go/83787 to capture those.

	Rainer
Rainer Orth Jan. 11, 2018, 4:56 p.m. UTC | #10
Hi Ian,

>> This patch updates libgo to the Go1.10beta1 release.  The final Go
>> 1.10 release is expected around February 1, so it's not clear how the
>> release timing is going to work with GCC 8.  In any case this updates
>> GCC to something pretty close to the final Go 1.10 release.
>>
>> A few changes to the frontend were required to match changes in the
>> runtime map code, and to handle some no-writebarrier cases in the
>> runtime package.
>>
>> As usual with these updates the complete patch is too large to include
>> in this e-mail message.  I've just included the changes to
>> gccgo-specific code.
>>
>> Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu.  Committed
>> to mainline.
>
> the patch broke Solaris bootstrap:
>
> mv: cannot stat 'os/signal/internal/pty.s-gox.tmp': No such file or directory
> make[4]: *** [Makefile:3348: os/signal/internal/pty.s-gox] Error 1
> make[4]: *** Waiting for unfinished jobs....
>
> Fixed trivially as follows, which allowed the build to complete.  make
> check still running...

there's another build failure, only affecting Solaris 10:

/vol/gcc/src/hg/trunk/local/libgo/go/os/user/cgo_lookup_unix.go:274:20: error: integer constant overflow
  sp.Pw_uid = 1<<32 - 2
                    ^
/vol/gcc/src/hg/trunk/local/libgo/go/os/user/cgo_lookup_unix.go:275:20: error: integer constant overflow
  sp.Pw_gid = 1<<32 - 3
                    ^
make[8]: *** [Makefile:3313: os/user.lo] Error 1

sysinfo.go has

type Passwd struct { Pw_name *int8; Pw_passwd *int8; Pw_uid int32; Pw_gid int32; Pw_age *int8; Pw_comment *int8; Pw_gecos *int8; Pw_dir *int8; Pw_shell *int8; }

while on S11 there is

type Passwd struct { Pw_name *int8; Pw_passwd *int8; Pw_uid uint32; Pw_gid uint32; Pw_age *int8; Pw_comment *int8; Pw_gecos *int8; Pw_dir *int8; Pw_shell *int8; }

	Rainer
Ian Lance Taylor Jan. 18, 2018, 4:24 a.m. UTC | #11
On Thu, Jan 11, 2018 at 1:46 AM, Rainer Orth
<ro@cebitec.uni-bielefeld.de> wrote:
>
>> On Wed, Jan 10, 2018 at 5:42 AM, Ian Lance Taylor <iant@golang.org> wrote:
>>>
>>> Whoops, there's a bug on big-endian 32-bit systems.  I'm testing
>>> https://golang.org/cl/87135.
>>
>> Committed as follows.
>
> thanks, that fixed quite a lot of the failures.
>
> However, many others remain, too many to report here.  I've filed PR
> go/83787 to capture those.

Thanks.  I found the problem: there is a new function makechan that
takes a size argument of type int, and the old makechan, that took
int64, is now makechan64.  Since the size argument was the last one,
this worked fine except on 32-bit big-endian systems.  Fixed with this
patch.  Bootstrapped and tested on x86_64-pc-linux-gnu and
sparc-sun-solaris2.12.  Committed to mainline.

Ian
Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE	(revision 256820)
+++ gcc/go/gofrontend/MERGE	(working copy)
@@ -1,4 +1,4 @@
-1072286ca9249bd6f75628aead325a66286bcf5b
+925635f067d40d30acf565b620cc859ee7cbc990
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
Index: gcc/go/gofrontend/escape.cc
===================================================================
--- gcc/go/gofrontend/escape.cc	(revision 256820)
+++ gcc/go/gofrontend/escape.cc	(working copy)
@@ -360,6 +360,7 @@ Node::op_format() const
 		  break;
 
 		case Runtime::MAKECHAN:
+		case Runtime::MAKECHAN64:
 		case Runtime::MAKEMAP:
 		case Runtime::MAKESLICE:
 		case Runtime::MAKESLICE64:
@@ -1602,6 +1603,7 @@ Escape_analysis_assign::expression(Expre
 	    switch (fe->runtime_code())
 	      {
 	      case Runtime::MAKECHAN:
+	      case Runtime::MAKECHAN64:
 	      case Runtime::MAKEMAP:
 	      case Runtime::MAKESLICE:
 	      case Runtime::MAKESLICE64:
@@ -2284,6 +2286,7 @@ Escape_analysis_assign::assign(Node* dst
 		switch (fe->runtime_code())
 		  {
 		  case Runtime::MAKECHAN:
+		  case Runtime::MAKECHAN64:
 		  case Runtime::MAKEMAP:
 		  case Runtime::MAKESLICE:
 		  case Runtime::MAKESLICE64:
@@ -3056,6 +3059,7 @@ Escape_analysis_flood::flood(Level level
               switch (call->fn()->func_expression()->runtime_code())
                 {
                 case Runtime::MAKECHAN:
+		case Runtime::MAKECHAN64:
                 case Runtime::MAKEMAP:
                 case Runtime::MAKESLICE:
                 case Runtime::MAKESLICE64:
Index: gcc/go/gofrontend/expressions.cc
===================================================================
--- gcc/go/gofrontend/expressions.cc	(revision 256820)
+++ gcc/go/gofrontend/expressions.cc	(working copy)
@@ -7565,7 +7565,10 @@ Builtin_call_expression::lower_make(Stat
   else if (is_chan)
     {
       Expression* type_arg = Expression::make_type_descriptor(type, type_loc);
-      call = Runtime::make_call(Runtime::MAKECHAN, loc, 2, type_arg, len_arg);
+      Runtime::Function code = Runtime::MAKECHAN;
+      if (!len_small)
+	code = Runtime::MAKECHAN64;
+      call = Runtime::make_call(code, loc, 2, type_arg, len_arg);
     }
   else
     go_unreachable();
Index: gcc/go/gofrontend/runtime.def
===================================================================
--- gcc/go/gofrontend/runtime.def	(revision 256593)
+++ gcc/go/gofrontend/runtime.def	(working copy)
@@ -139,7 +139,8 @@ DEF_GO_RUNTIME(MAPITERNEXT, "runtime.map
 
 
 // Make a channel.
-DEF_GO_RUNTIME(MAKECHAN, "runtime.makechan", P2(TYPE, INT64), R1(CHAN))
+DEF_GO_RUNTIME(MAKECHAN, "runtime.makechan", P2(TYPE, INT), R1(CHAN))
+DEF_GO_RUNTIME(MAKECHAN64, "runtime.makechan64", P2(TYPE, INT64), R1(CHAN))
 
 // Send a value on a channel.
 DEF_GO_RUNTIME(CHANSEND, "runtime.chansend1", P2(CHAN, POINTER), R0())
Index: libgo/go/runtime/chan.go
===================================================================
--- libgo/go/runtime/chan.go	(revision 256593)
+++ libgo/go/runtime/chan.go	(working copy)
@@ -26,6 +26,7 @@ import (
 // themselves, so that the compiler will export them.
 //
 //go:linkname makechan runtime.makechan
+//go:linkname makechan64 runtime.makechan64
 //go:linkname chansend1 runtime.chansend1
 //go:linkname chanrecv1 runtime.chanrecv1
 //go:linkname chanrecv2 runtime.chanrecv2
Rainer Orth Jan. 18, 2018, 8:02 a.m. UTC | #12
Hi Ian,

> On Thu, Jan 11, 2018 at 1:46 AM, Rainer Orth
> <ro@cebitec.uni-bielefeld.de> wrote:
>>
>>> On Wed, Jan 10, 2018 at 5:42 AM, Ian Lance Taylor <iant@golang.org> wrote:
>>>>
>>>> Whoops, there's a bug on big-endian 32-bit systems.  I'm testing
>>>> https://golang.org/cl/87135.
>>>
>>> Committed as follows.
>>
>> thanks, that fixed quite a lot of the failures.
>>
>> However, many others remain, too many to report here.  I've filed PR
>> go/83787 to capture those.
>
> Thanks.  I found the problem: there is a new function makechan that
> takes a size argument of type int, and the old makechan, that took
> int64, is now makechan64.  Since the size argument was the last one,
> this worked fine except on 32-bit big-endian systems.  Fixed with this
> patch.  Bootstrapped and tested on x86_64-pc-linux-gnu and
> sparc-sun-solaris2.12.  Committed to mainline.

great, thanks for fixing this.

One related question: I mentioned in passing in the PR that four go test
invocations in gotools would hang indefinitely.  I noticed that they
weren't called with -test.timeout, unlike libgo's gotest.  However, in
exceptional cases like this this probably can't be helped short of
adding an external timeout mechanism.

	Rainer
Ian Lance Taylor Jan. 19, 2018, 4:52 a.m. UTC | #13
On Thu, Jan 11, 2018 at 8:56 AM, Rainer Orth
<ro@cebitec.uni-bielefeld.de> wrote:
>
>>> This patch updates libgo to the Go1.10beta1 release.  The final Go
>>> 1.10 release is expected around February 1, so it's not clear how the
>>> release timing is going to work with GCC 8.  In any case this updates
>>> GCC to something pretty close to the final Go 1.10 release.
>>>
>>> A few changes to the frontend were required to match changes in the
>>> runtime map code, and to handle some no-writebarrier cases in the
>>> runtime package.
>>>
>>> As usual with these updates the complete patch is too large to include
>>> in this e-mail message.  I've just included the changes to
>>> gccgo-specific code.
>>>
>>> Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu.  Committed
>>> to mainline.
>>
>> the patch broke Solaris bootstrap:
>>
>> mv: cannot stat 'os/signal/internal/pty.s-gox.tmp': No such file or directory
>> make[4]: *** [Makefile:3348: os/signal/internal/pty.s-gox] Error 1
>> make[4]: *** Waiting for unfinished jobs....
>>
>> Fixed trivially as follows, which allowed the build to complete.  make
>> check still running...
>
> there's another build failure, only affecting Solaris 10:
>
> /vol/gcc/src/hg/trunk/local/libgo/go/os/user/cgo_lookup_unix.go:274:20: error: integer constant overflow
>   sp.Pw_uid = 1<<32 - 2
>                     ^
> /vol/gcc/src/hg/trunk/local/libgo/go/os/user/cgo_lookup_unix.go:275:20: error: integer constant overflow
>   sp.Pw_gid = 1<<32 - 3
>                     ^
> make[8]: *** [Makefile:3313: os/user.lo] Error 1
>
> sysinfo.go has
>
> type Passwd struct { Pw_name *int8; Pw_passwd *int8; Pw_uid int32; Pw_gid int32; Pw_age *int8; Pw_comment *int8; Pw_gecos *int8; Pw_dir *int8; Pw_shell *int8; }
>
> while on S11 there is
>
> type Passwd struct { Pw_name *int8; Pw_passwd *int8; Pw_uid uint32; Pw_gid uint32; Pw_age *int8; Pw_comment *int8; Pw_gecos *int8; Pw_dir *int8; Pw_shell *int8; }

I fixed this by clobbering the types used in Go, as follows.
Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu, committed to
mainline.

Ian
Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE	(revision 256874)
+++ gcc/go/gofrontend/MERGE	(working copy)
@@ -1,4 +1,4 @@
-8195b62d353026256037fa44409c4ad95762e6b7
+bce8720d4eb662f31026e9c7be6ce4d0aeb4ae3b
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
Index: libgo/mksysinfo.sh
===================================================================
--- libgo/mksysinfo.sh	(revision 256593)
+++ libgo/mksysinfo.sh	(working copy)
@@ -685,9 +685,13 @@ if ! grep "const EAI_OVERFLOW " ${OUT} >
 fi
 
 # The passwd struct.
+# Force uid and gid from int32 to uint32 for consistency; they are
+# int32 on Solaris 10 but uint32 everywhere else including Solaris 11.
 grep '^type _passwd ' gen-sysinfo.go | \
     sed -e 's/_passwd/Passwd/' \
       -e 's/ pw_/ Pw_/g' \
+      -e 's/ Pw_uid int32/ Pw_uid uint32/' \
+      -e 's/ Pw_gid int32/ Pw_gid uint32/' \
     >> ${OUT}
 
 # The group struct.
Ian Lance Taylor Jan. 19, 2018, 5:06 a.m. UTC | #14
On Thu, Jan 18, 2018 at 12:02 AM, Rainer Orth
<ro@cebitec.uni-bielefeld.de> wrote:
>
>> On Thu, Jan 11, 2018 at 1:46 AM, Rainer Orth
>> <ro@cebitec.uni-bielefeld.de> wrote:
>>>
>>>> On Wed, Jan 10, 2018 at 5:42 AM, Ian Lance Taylor <iant@golang.org> wrote:
>>>>>
>>>>> Whoops, there's a bug on big-endian 32-bit systems.  I'm testing
>>>>> https://golang.org/cl/87135.
>>>>
>>>> Committed as follows.
>>>
>>> thanks, that fixed quite a lot of the failures.
>>>
>>> However, many others remain, too many to report here.  I've filed PR
>>> go/83787 to capture those.
>>
>> Thanks.  I found the problem: there is a new function makechan that
>> takes a size argument of type int, and the old makechan, that took
>> int64, is now makechan64.  Since the size argument was the last one,
>> this worked fine except on 32-bit big-endian systems.  Fixed with this
>> patch.  Bootstrapped and tested on x86_64-pc-linux-gnu and
>> sparc-sun-solaris2.12.  Committed to mainline.
>
> great, thanks for fixing this.
>
> One related question: I mentioned in passing in the PR that four go test
> invocations in gotools would hang indefinitely.  I noticed that they
> weren't called with -test.timeout, unlike libgo's gotest.  However, in
> exceptional cases like this this probably can't be helped short of
> adding an external timeout mechanism.

Thanks, I missed that.  This patch adds -test.timeout arguments to at
least set a timeout where possible.  I used the same 240s value used
by libgo by default.  Bootstrapped and ran gotools testsuite on
x86_64-pc-linux-gnu.  Committed to mainline.

Ian

2018-01-18  Ian Lance Taylor  <iant@golang.org>

* Makefile.am (GOTOOLS_TEST_TIMEOUT): Define.
(check-go-tool): Pass -test.timeout with GOTOOLS_TEST_TIMEOUT.
(check-cgo-test, check-carchive-test, check-vet): Likewise.
* Makefile.in: Rebuild.
Index: Makefile.am
===================================================================
--- Makefile.am	(revision 256398)
+++ Makefile.am	(working copy)
@@ -161,6 +161,9 @@ uninstall-local:
 
 GOTESTFLAGS =
 
+# Number of seconds before tests time out.
+GOTOOLS_TEST_TIMEOUT = 240
+
 # Run tests using the go tool, and frob the output to look like that
 # generated by DejaGNU.  The main output of this is two files:
 # gotools.sum and gotools.log.
@@ -234,11 +237,11 @@ check-go-tool: go$(EXEEXT) $(noinst_PROG
 	cp $(libgodir)/objabi.go check-go-dir/src/cmd/internal/objabi/
 	@abs_libgodir=`cd $(libgodir) && $(PWD_COMMAND)`; \
 	abs_checkdir=`cd check-go-dir && $(PWD_COMMAND)`; \
-	echo "cd check-go-dir/src/cmd/go && $(ECHO_ENV) GOPATH=$${abs_checkdir} $(abs_builddir)/go$(EXEEXT) test -test.short -test.v" > cmd_go-testlog
+	echo "cd check-go-dir/src/cmd/go && $(ECHO_ENV) GOPATH=$${abs_checkdir} $(abs_builddir)/go$(EXEEXT) test -test.short -test.timeout=$(GOTOOLS_TEST_TIMEOUT)s -test.v" > cmd_go-testlog
 	$(CHECK_ENV) \
 	GOPATH=`cd check-go-dir && $(PWD_COMMAND)`; \
 	export GOPATH; \
-	(cd check-go-dir/src/cmd/go && $(abs_builddir)/go$(EXEEXT) test -test.short -test.v) >> cmd_go-testlog 2>&1 || echo "--- $${fl}: go test cmd/go (0.00s)" >> cmd_go-testlog
+	(cd check-go-dir/src/cmd/go && $(abs_builddir)/go$(EXEEXT) test -test.short -test.timeout=$(GOTOOLS_TEST_TIMEOUT)s -test.v) >> cmd_go-testlog 2>&1 || echo "--- $${fl}: go test cmd/go (0.00s)" >> cmd_go-testlog
 	grep '^--- ' cmd_go-testlog | sed -e 's/^--- \(.*\) ([^)]*)$$/\1/' | sort -k 2
 
 # check-runtime runs `go test runtime` in our environment.
@@ -269,11 +272,11 @@ check-cgo-test: go$(EXEEXT) $(noinst_PRO
 	$(MKDIR_P) cgo-test-dir/misc/cgo
 	cp -r $(libgomiscdir)/cgo/test cgo-test-dir/misc/cgo/
 	@abs_libgodir=`cd $(libgodir) && $(PWD_COMMAND)`; \
-	echo "cd cgo-test-dir/misc/cgo/test && $(ECHO_ENV) GOTRACEBACK=2 $(abs_builddir)/go$(EXEEXT) test -test.short -test.v" > cgo-testlog
+	echo "cd cgo-test-dir/misc/cgo/test && $(ECHO_ENV) GOTRACEBACK=2 $(abs_builddir)/go$(EXEEXT) test -test.short -test.timeout=$(GOTOOLS_TEST_TIMEOUT)s -test.v" > cgo-testlog
 	$(CHECK_ENV) \
 	GOTRACEBACK=2; \
 	export GOTRACEBACK; \
-	(cd cgo-test-dir/misc/cgo/test && $(abs_builddir)/go$(EXEEXT) test -test.short -test.v) >> cgo-testlog 2>&1 || echo "--- $${fl}: go test misc/cgo/test (0.00s)" >> cgo-testlog
+	(cd cgo-test-dir/misc/cgo/test && $(abs_builddir)/go$(EXEEXT) test -test.short -test.timeout=$(GOTOOLS_TEST_TIMEOUT)s -test.v) >> cgo-testlog 2>&1 || echo "--- $${fl}: go test misc/cgo/test (0.00s)" >> cgo-testlog
 	grep '^--- ' cgo-testlog | sed -e 's/^--- \(.*\) ([^)]*)$$/\1/' | sort -k 2
 
 # check-carchive-test runs `go test misc/cgo/testcarchive/carchive_test.go`
@@ -283,11 +286,11 @@ check-carchive-test: go$(EXEEXT) $(noins
 	$(MKDIR_P) carchive-test-dir/misc/cgo
 	cp -r $(libgomiscdir)/cgo/testcarchive carchive-test-dir/misc/cgo/
 	@abs_libgodir=`cd $(libgodir) && $(PWD_COMMAND)`; \
-	echo "cd carchive-test-dir/misc/cgo/testcarchive && $(ECHO_ENV) LIBRARY_PATH=`echo $${abs_libgodir}/.libs` $(abs_builddir)/go$(EXEEXT) test -test.v carchive_test.go" > carchive-testlog
+	echo "cd carchive-test-dir/misc/cgo/testcarchive && $(ECHO_ENV) LIBRARY_PATH=`echo $${abs_libgodir}/.libs` $(abs_builddir)/go$(EXEEXT) test -test.timeout=$(GOTOOLS_TEST_TIMEOUT)s -test.v carchive_test.go" > carchive-testlog
 	$(CHECK_ENV) \
 	LIBRARY_PATH=`echo $${abs_libgodir}/.libs:$${LIBRARY_PATH} | sed 's,::*,:,g;s,^:*,,;s,:*$$,,'`; \
 	export LIBRARY_PATH; \
-	(cd carchive-test-dir/misc/cgo/testcarchive && $(abs_builddir)/go$(EXEEXT) test -test.v carchive_test.go) >> carchive-testlog 2>&1 || echo "--- $${fl}: go test misc/cgo/testcarchive (0.00s)" >> carchive-testlog
+	(cd carchive-test-dir/misc/cgo/testcarchive && $(abs_builddir)/go$(EXEEXT) test -test.timeout=$(GOTOOLS_TEST_TIMEOUT)s -test.v carchive_test.go) >> carchive-testlog 2>&1 || echo "--- $${fl}: go test misc/cgo/testcarchive (0.00s)" >> carchive-testlog
 	grep '^--- ' carchive-testlog | sed -e 's/^--- \(.*\) ([^)]*)$$/\1/' | sort -k 2
 
 # check-vet runs `go test cmd/vet` in our environment.
@@ -297,11 +300,11 @@ check-vet: go$(EXEEXT) $(noinst_PROGRAMS
 	cp -r $(cmdsrcdir)/vet check-vet-dir/src/cmd/
 	@abs_libgodir=`cd $(libgodir) && $(PWD_COMMAND)`; \
 	abs_checkdir=`cd check-vet-dir && $(PWD_COMMAND)`; \
-	echo "cd check-vet-dir/src/cmd/vet && $(ECHO_ENV) GOPATH=$${abs_checkdir} $(abs_builddir)/go$(EXEEXT) test -test.short -test.v" > cmd_vet-testlog
+	echo "cd check-vet-dir/src/cmd/vet && $(ECHO_ENV) GOPATH=$${abs_checkdir} $(abs_builddir)/go$(EXEEXT) test -test.short -test.timeout=$(GOTOOLS_TEST_TIMEOUT)s -test.v" > cmd_vet-testlog
 	$(CHECK_ENV) \
 	GOPATH=`cd check-vet-dir && $(PWD_COMMAND)`; \
 	export GOPATH; \
-	(cd check-vet-dir/src/cmd/vet && $(abs_builddir)/go$(EXEEXT) test -test.short -test.v) >> cmd_vet-testlog 2>&1 || echo "--- $${fl}: go test cmd/vet (0.00s)" >> cmd_vet-testlog
+	(cd check-vet-dir/src/cmd/vet && $(abs_builddir)/go$(EXEEXT) test -test.short -test.timeout=$(GOTOOLS_TEST_TIMEOUT)s -test.v) >> cmd_vet-testlog 2>&1 || echo "--- $${fl}: go test cmd/vet (0.00s)" >> cmd_vet-testlog
 	grep '^--- ' cmd_vet-testlog | sed -e 's/^--- \(.*\) ([^)]*)$$/\1/' | sort -k 2
 
 # The check targets runs the tests and assembles the output files.
diff mbox series

Patch

Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE	(revision 256306)
+++ gcc/go/gofrontend/MERGE	(working copy)
@@ -1,4 +1,4 @@ 
-1319f36ccc65cf802b8e17ddd3d2da3ca6d82f4c
+dbc0c7e4329aada2ae3554c20cfb8cfa48041213
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
Index: gcc/go/gofrontend/expressions.cc
===================================================================
--- gcc/go/gofrontend/expressions.cc	(revision 256262)
+++ gcc/go/gofrontend/expressions.cc	(working copy)
@@ -7483,6 +7483,7 @@  Builtin_call_expression::lower_make(Stat
 	  return Expression::make_error(this->location());
 	}
       len_arg = Expression::make_integer_ul(0, NULL, loc);
+      len_small = true;
     }
   else
     {
@@ -7551,9 +7552,23 @@  Builtin_call_expression::lower_make(Stat
   else if (is_map)
     {
       Expression* type_arg = Expression::make_type_descriptor(type, type_loc);
-      call = Runtime::make_call(Runtime::MAKEMAP, loc, 4, type_arg, len_arg,
-				Expression::make_nil(loc),
-				Expression::make_nil(loc));
+      if (!len_small)
+	call = Runtime::make_call(Runtime::MAKEMAP64, loc, 3, type_arg,
+				  len_arg,
+				  Expression::make_nil(loc));
+      else
+	{
+	  Numeric_constant nclen;
+	  unsigned long vlen;
+	  if (len_arg->numeric_constant_value(&nclen)
+	      && nclen.to_unsigned_long(&vlen) == Numeric_constant::NC_UL_VALID
+	      && vlen <= Map_type::bucket_size)
+	    call = Runtime::make_call(Runtime::MAKEMAP_SMALL, loc, 0);
+	  else
+	    call = Runtime::make_call(Runtime::MAKEMAP, loc, 3, type_arg,
+				      len_arg,
+				      Expression::make_nil(loc));
+	}
     }
   else if (is_chan)
     {
@@ -9503,14 +9518,8 @@  Call_expression::do_lower(Gogo* gogo, Na
   // could implement them in normal code, but then we would have to
   // explicitly unwind the stack.  These functions are intended to be
   // efficient.  Note that this technique obviously only works for
-  // direct calls, but that is the only way they are used.  The actual
-  // argument to these functions is always the address of a parameter;
-  // we don't need that for the GCC builtin functions, so we just
-  // ignore it.
-  if (gogo->compiling_runtime()
-      && this->args_ != NULL
-      && this->args_->size() == 1
-      && gogo->package_name() == "runtime")
+  // direct calls, but that is the only way they are used.
+  if (gogo->compiling_runtime() && gogo->package_name() == "runtime")
     {
       Func_expression* fe = this->fn_->func_expression();
       if (fe != NULL
@@ -9518,15 +9527,21 @@  Call_expression::do_lower(Gogo* gogo, Na
 	  && fe->named_object()->package() == NULL)
 	{
 	  std::string n = Gogo::unpack_hidden_name(fe->named_object()->name());
-	  if (n == "getcallerpc")
+	  if ((this->args_ == NULL || this->args_->size() == 0)
+	      && n == "getcallerpc")
 	    {
 	      static Named_object* builtin_return_address;
 	      return this->lower_to_builtin(&builtin_return_address,
 					    "__builtin_return_address",
 					    0);
 	    }
-	  else if (n == "getcallersp")
+	  else if (this->args_ != NULL
+		   && this->args_->size() == 1
+		   && n == "getcallersp")
 	    {
+	      // The actual argument to getcallersp is always the
+	      // address of a parameter; we don't need that for the
+	      // GCC builtin function, so we just ignore it.
 	      static Named_object* builtin_frame_address;
 	      return this->lower_to_builtin(&builtin_frame_address,
 					    "__builtin_frame_address",
@@ -10027,7 +10042,7 @@  Call_expression::do_check_types(Gogo*)
     }
 
   const Typed_identifier_list* parameters = fntype->parameters();
-  if (this->args_ == NULL)
+  if (this->args_ == NULL || this->args_->size() == 0)
     {
       if (parameters != NULL && !parameters->empty())
 	this->report_error(_("not enough arguments"));
Index: gcc/go/gofrontend/runtime.def
===================================================================
--- gcc/go/gofrontend/runtime.def	(revision 256262)
+++ gcc/go/gofrontend/runtime.def	(working copy)
@@ -91,9 +91,14 @@  DEF_GO_RUNTIME(MAKESLICE64, "runtime.mak
 	       R1(SLICE))
 
 
-// Make a map.
-DEF_GO_RUNTIME(MAKEMAP, "runtime.makemap", P4(TYPE, INT64, POINTER, POINTER),
-	       R1(MAP))
+// Make a map with a hint and an (optional, unused) map structure.
+DEF_GO_RUNTIME(MAKEMAP, "runtime.makemap", P3(TYPE, INT, POINTER),
+		R1(MAP))
+DEF_GO_RUNTIME(MAKEMAP64, "runtime.makemap64", P3(TYPE, INT64, POINTER),
+		R1(MAP))
+
+// Make a map with no hint, or a small constant hint.
+DEF_GO_RUNTIME(MAKEMAP_SMALL, "runtime.makemap_small", P0(), R1(MAP))
 
 // Build a map from a composite literal.
 DEF_GO_RUNTIME(CONSTRUCT_MAP, "__go_construct_map",
Index: gcc/go/gofrontend/types.cc
===================================================================
--- gcc/go/gofrontend/types.cc	(revision 256262)
+++ gcc/go/gofrontend/types.cc	(working copy)
@@ -7830,7 +7830,7 @@  Map_type::do_get_backend(Gogo* gogo)
       bfields[7].btype = uintptr_type->get_backend(gogo);
       bfields[7].location = bloc;
 
-      bfields[8].name = "overflow";
+      bfields[8].name = "extra";
       bfields[8].btype = bpvt;
       bfields[8].location = bloc;
 
@@ -8144,21 +8144,23 @@  Map_type::hmap_type(Type* bucket_type)
 
   Type* int_type = Type::lookup_integer_type("int");
   Type* uint8_type = Type::lookup_integer_type("uint8");
+  Type* uint16_type = Type::lookup_integer_type("uint16");
   Type* uint32_type = Type::lookup_integer_type("uint32");
   Type* uintptr_type = Type::lookup_integer_type("uintptr");
   Type* void_ptr_type = Type::make_pointer_type(Type::make_void_type());
 
   Type* ptr_bucket_type = Type::make_pointer_type(bucket_type);
 
-  Struct_type* ret = make_builtin_struct_type(8,
+  Struct_type* ret = make_builtin_struct_type(9,
 					      "count", int_type,
 					      "flags", uint8_type,
 					      "B", uint8_type,
+					      "noverflow", uint16_type,
 					      "hash0", uint32_type,
 					      "buckets", ptr_bucket_type,
 					      "oldbuckets", ptr_bucket_type,
 					      "nevacuate", uintptr_type,
-					      "overflow", void_ptr_type);
+					      "extra", void_ptr_type);
   ret->set_is_struct_incomparable();
   this->hmap_type_ = ret;
   return ret;
@@ -8191,18 +8193,22 @@  Map_type::hiter_type(Gogo* gogo)
   Type* hmap_type = this->hmap_type(bucket_type);
   Type* hmap_ptr_type = Type::make_pointer_type(hmap_type);
   Type* void_ptr_type = Type::make_pointer_type(Type::make_void_type());
+  Type* bool_type = Type::lookup_bool_type();
 
-  Struct_type* ret = make_builtin_struct_type(12,
+  Struct_type* ret = make_builtin_struct_type(15,
 					      "key", key_ptr_type,
 					      "val", val_ptr_type,
 					      "t", uint8_ptr_type,
 					      "h", hmap_ptr_type,
 					      "buckets", bucket_ptr_type,
 					      "bptr", bucket_ptr_type,
-					      "overflow0", void_ptr_type,
-					      "overflow1", void_ptr_type,
+					      "overflow", void_ptr_type,
+					      "oldoverflow", void_ptr_type,
 					      "startBucket", uintptr_type,
-					      "stuff", uintptr_type,
+					      "offset", uint8_type,
+					      "wrapped", bool_type,
+					      "B", uint8_type,
+					      "i", uint8_type,
 					      "bucket", uintptr_type,
 					      "checkBucket", uintptr_type);
   ret->set_is_struct_incomparable();
Index: gcc/go/gofrontend/types.h
===================================================================
--- gcc/go/gofrontend/types.h	(revision 256262)
+++ gcc/go/gofrontend/types.h	(working copy)
@@ -2826,6 +2826,9 @@  class Map_type : public Type
   static Type*
   make_map_type_descriptor_type();
 
+  // This must be in  sync with libgo/go/runtime/hashmap.go.
+  static const int bucket_size = 8;
+
  protected:
   int
   do_traverse(Traverse*);
@@ -2867,7 +2870,6 @@  class Map_type : public Type
 
  private:
   // These must be in sync with libgo/go/runtime/hashmap.go.
-  static const int bucket_size = 8;
   static const int max_key_size = 128;
   static const int max_val_size = 128;
   static const int max_zero_size = 1024;
Index: gcc/go/gofrontend/wb.cc
===================================================================
--- gcc/go/gofrontend/wb.cc	(revision 256262)
+++ gcc/go/gofrontend/wb.cc	(working copy)
@@ -331,6 +331,25 @@  Gogo::assign_needs_write_barrier(Express
   if (!lhs->type()->has_pointer())
     return false;
 
+  // An assignment to a field is handled like an assignment to the
+  // struct.
+  while (true)
+    {
+      // Nothing to do for a type that can not be in the heap, or a
+      // pointer to a type that can not be in the heap.  We check this
+      // at each level of a struct.
+      if (!lhs->type()->in_heap())
+	return false;
+      if (lhs->type()->points_to() != NULL
+	  && !lhs->type()->points_to()->in_heap())
+	return false;
+
+      Field_reference_expression* fre = lhs->field_reference_expression();
+      if (fre == NULL)
+	break;
+      lhs = fre->expr();
+    }
+
   // Nothing to do for an assignment to a temporary.
   if (lhs->temporary_reference_expression() != NULL)
     return false;
@@ -359,12 +378,30 @@  Gogo::assign_needs_write_barrier(Express
 	}
     }
 
-  // Nothing to do for a type that can not be in the heap, or a
-  // pointer to a type that can not be in the heap.
-  if (!lhs->type()->in_heap())
-    return false;
-  if (lhs->type()->points_to() != NULL && !lhs->type()->points_to()->in_heap())
-    return false;
+  // For a struct assignment, we don't need a write barrier if all the
+  // pointer types can not be in the heap.
+  Struct_type* st = lhs->type()->struct_type();
+  if (st != NULL)
+    {
+      bool in_heap = false;
+      const Struct_field_list* fields = st->fields();
+      for (Struct_field_list::const_iterator p = fields->begin();
+	   p != fields->end();
+	   p++)
+	{
+	  Type* ft = p->type();
+	  if (!ft->has_pointer())
+	    continue;
+	  if (!ft->in_heap())
+	    continue;
+	  if (ft->points_to() != NULL && !ft->points_to()->in_heap())
+	    continue;
+	  in_heap = true;
+	  break;
+	}
+      if (!in_heap)
+	return false;
+    }
 
   // Write barrier needed in other cases.
   return true;
Index: libgo/MERGE
===================================================================
--- libgo/MERGE	(revision 256262)
+++ libgo/MERGE	(working copy)
@@ -1,4 +1,4 @@ 
-c8aec4095e089ff6ac50d18e97c3f46561f14f48
+9ce6b5c2ed5d3d5251b9a6a0c548d5fb2c8567e8
 
 The first line of this file holds the git revision number of the
 last merge done from the master library sources.
Index: libgo/Makefile.am
===================================================================
--- libgo/Makefile.am	(revision 256262)
+++ libgo/Makefile.am	(working copy)
@@ -400,8 +400,11 @@  toolexeclibgounicode_DATA = \
 # internal packages nothing will explicitly depend on them.
 # Force them to be built.
 noinst_DATA = \
+	golang_org/x/net/internal/nettest.gox \
+	golang_org/x/net/nettest.gox \
 	internal/testenv.gox \
-	net/internal/socktest.gox
+	net/internal/socktest.gox \
+	os/signal/internal/pty.gox
 
 if LIBGO_IS_RTEMS
 rtems_task_variable_add_file = runtime/rtems-task-variable-add.c
@@ -533,6 +536,24 @@  s-version: Makefile
 	$(SHELL) $(srcdir)/mvifdiff.sh version.go.tmp version.go
 	$(STAMP) $@
 
+objabi.go: s-objabi; @true
+s-objabi: Makefile
+	rm -f objabi.go.tmp
+	echo "package objabi" > objabi.go.tmp
+	echo "import \"runtime\"" >> objabi.go.tmp
+	echo 'const defaultGOROOT = `$(prefix)`' >> objabi.go.tmp
+	echo 'const defaultGO386 = `sse2`' >> objabi.go.tmp
+	echo 'const defaultGOARM = `5`' >> objabi.go.tmp
+	echo 'const defaultGOMIPS = `hardfloat`' >> objabi.go.tmp
+	echo 'const defaultGOOS = runtime.GOOS' >> objabi.go.tmp
+	echo 'const defaultGOARCH = runtime.GOARCH' >> objabi.go.tmp
+	echo 'const defaultGO_EXTLINK_ENABLED = ``' >> objabi.go.tmp
+	echo 'const version = `'`cat $(srcdir)/VERSION | sed 1q`' '`$(GOC) --version | sed 1q`'`' >> objabi.go.tmp
+	echo 'const stackGuardMultiplier = 1' >> objabi.go.tmp
+	echo 'const goexperiment = ``' >> objabi.go.tmp
+	$(SHELL) $(srcdir)/mvifdiff.sh objabi.go.tmp objabi.go
+	$(STAMP) $@
+
 runtime_sysinfo.go: s-runtime_sysinfo; @true
 s-runtime_sysinfo: $(srcdir)/mkrsysinfo.sh gen-sysinfo.go
 	GOARCH=$(GOARCH) GOOS=$(GOOS) $(SHELL) $(srcdir)/mkrsysinfo.sh
@@ -553,10 +574,11 @@  zdefaultcc.go: s-zdefaultcc; @true
 s-zdefaultcc: Makefile
 	echo 'package cfg' > zdefaultcc.go.tmp
 	echo >> zdefaultcc.go.tmp
-	echo 'const DefaultGCCGO = "$(bindir)/$(GCCGO_INSTALL_NAME)"' >> zdefaultcc.go.tmp
-	echo 'const DefaultCC = "$(GCC_INSTALL_NAME)"' >> zdefaultcc.go.tmp
-	echo 'const DefaultCXX = "$(GXX_INSTALL_NAME)"' >> zdefaultcc.go.tmp
+	echo 'func DefaultGCCGO(goos, goarch string) string { return "$(bindir)/$(GCCGO_INSTALL_NAME)" }' >> zdefaultcc.go.tmp
+	echo 'func DefaultCC(goos, goarch string) string { return "$(GCC_INSTALL_NAME)" }' >> zdefaultcc.go.tmp
+	echo 'func DefaultCXX(goos, goarch string) string { return "$(GXX_INSTALL_NAME)" }' >> zdefaultcc.go.tmp
 	echo 'const DefaultPkgConfig = "pkg-config"' >> zdefaultcc.go.tmp
+	echo 'var OSArchSupportsCgo = map[string]bool{}' >> zdefaultcc.go.tmp
 	$(SHELL) $(srcdir)/../move-if-change zdefaultcc.go.tmp zdefaultcc.go
 	$(STAMP) $@ 
 
@@ -758,11 +780,15 @@  PACKAGES = \
 	go/types \
 	golang_org/x/crypto/chacha20poly1305 \
 	golang_org/x/crypto/chacha20poly1305/internal/chacha20 \
+	golang_org/x/crypto/cryptobyte \
+	golang_org/x/crypto/cryptobyte/asn1 \
 	golang_org/x/crypto/curve25519 \
 	golang_org/x/crypto/poly1305 \
 	golang_org/x/net/http2/hpack \
 	golang_org/x/net/idna \
+	golang_org/x/net/internal/nettest \
 	golang_org/x/net/lex/httplex \
+	golang_org/x/net/nettest \
 	golang_org/x/net/proxy \
 	golang_org/x/text/secure/bidirule \
 	golang_org/x/text/transform \
@@ -824,6 +850,7 @@  PACKAGES = \
 	os \
 	os/exec \
 	os/signal \
+	os/signal/internal/pty \
 	os/user \
 	path \
 	path/filepath \
@@ -905,7 +932,7 @@  libgolibbegin_a_CFLAGS = $(AM_CFLAGS) -f
 GOTOOL_PACKAGES = \
 	cmd/go/internal/base \
 	cmd/go/internal/bug \
-	cmd/go/internal/buildid \
+	cmd/go/internal/cache \
 	cmd/go/internal/cfg \
 	cmd/go/internal/clean \
 	cmd/go/internal/cmdflag \
@@ -927,7 +954,12 @@  GOTOOL_PACKAGES = \
 	cmd/go/internal/web \
 	cmd/go/internal/work \
 	cmd/internal/browser \
-	cmd/internal/objabi
+	cmd/internal/buildid \
+	cmd/internal/edit \
+	cmd/internal/objabi \
+	cmd/internal/test2json \
+	cmd/vet/internal/cfg \
+	cmd/vet/internal/whitelist
 
 libgotool_a_SOURCES =
 libgotool_a_DEPENDENCIES = $(addsuffix .lo,$(GOTOOL_PACKAGES))
@@ -1136,17 +1168,23 @@  runtime_pprof_check_GOCFLAGS = -static-l
 extra_go_files_runtime_internal_sys = version.go
 runtime/internal/sys.lo.dep: $(extra_go_files_runtime_internal_sys)
 
+extra_go_files_cmd_internal_objabi = objabi.go
+cmd/internal/objabi.lo.dep: $(extra_go_files_cmd_internal_objabi)
+
 extra_go_files_cmd_go_internal_cfg = zdefaultcc.go
 cmd/go/internal/cfg.lo.dep: $(extra_go_files_cmd_go_internal_cfg)
 
 extra_go_files_cmd_go_internal_load = zstdpkglist.go
 cmd/go/internal/load.lo.dep: $(extra_go_files_cmd_go_internal_load)
 
+extra_check_libs_cmd_go_internal_cache = $(abs_builddir)/libgotool.a
 extra_check_libs_cmd_go_internal_generate = $(abs_builddir)/libgotool.a
 extra_check_libs_cmd_go_internal_get = $(abs_builddir)/libgotool.a
 extra_check_libs_cmd_go_internal_load = $(abs_builddir)/libgotool.a
 extra_check_libs_cmd_go_internal_work = $(abs_builddir)/libgotool.a
 
+extra_check_libs_cmd_vet_internal_cfg = $(abs_builddir)/libgotool.a
+
 # FIXME: The following C files may as well move to the runtime
 # directory and be treated like other C files.
 
@@ -1233,10 +1271,12 @@  TEST_PACKAGES = \
 	bufio/check \
 	bytes/check \
 	context/check \
+	crypto/check \
 	errors/check \
 	expvar/check \
 	flag/check \
 	fmt/check \
+	hash/check \
 	html/check \
 	image/check \
 	io/check \
@@ -1258,11 +1298,16 @@  TEST_PACKAGES = \
 	unicode/check \
 	archive/tar/check \
 	archive/zip/check \
+	cmd/go/internal/cache/check \
 	cmd/go/internal/generate/check \
 	cmd/go/internal/get/check \
 	cmd/go/internal/load/check \
 	cmd/go/internal/work/check \
+	cmd/internal/buildid/check \
+	cmd/internal/edit/check \
 	cmd/internal/objabi/check \
+	cmd/internal/test2json/check \
+	cmd/vet/internal/cfg/check \
 	compress/bzip2/check \
 	compress/flate/check \
 	compress/gzip/check \
@@ -1315,6 +1360,7 @@  TEST_PACKAGES = \
 	go/constant/check \
 	go/doc/check \
 	go/format/check \
+	go/importer/check \
 	go/internal/gcimporter/check \
 	go/internal/gccgoimporter/check \
 	go/internal/srcimporter/check \
@@ -1325,6 +1371,7 @@  TEST_PACKAGES = \
 	go/types/check \
 	golang_org/x/crypto/chacha20poly1305/check \
 	golang_org/x/crypto/chacha20poly1305/internal/chacha20/check \
+	golang_org/x/crypto/cryptobyte/check \
 	golang_org/x/crypto/curve25519/check \
 	golang_org/x/crypto/poly1305/check \
 	golang_org/x/net/http2/hpack/check \
Index: libgo/VERSION
===================================================================
--- libgo/VERSION	(revision 256262)
+++ libgo/VERSION	(working copy)
@@ -1 +1 @@ 
-go1.9
+go1.10beta1
Index: libgo/configure.ac
===================================================================
--- libgo/configure.ac	(revision 256306)
+++ libgo/configure.ac	(working copy)
@@ -11,7 +11,7 @@  AC_INIT(package-unused, version-unused,,
 AC_CONFIG_SRCDIR(Makefile.am)
 AC_CONFIG_HEADER(config.h)
 
-libtool_VERSION=12:0:0
+libtool_VERSION=13:0:0
 AC_SUBST(libtool_VERSION)
 
 AM_ENABLE_MULTILIB(, ..)
@@ -215,7 +215,7 @@  ALLGOARCHFAMILY="I386 ALPHA AMD64 ARM AR
 
 GOARCH=unknown
 GOARCH_FAMILY=unknown
-GOARCH_BIGENDIAN=0
+GOARCH_BIGENDIAN=false
 GOARCH_CACHELINESIZE=64
 GOARCH_PHYSPAGESIZE=4096
 GOARCH_PCQUANTUM=1
@@ -243,6 +243,12 @@  case ${host} in
     GOARCH_CACHELINESIZE=32
     GOARCH_PCQUANTUM=4
     GOARCH_MINFRAMESIZE=4
+    case ${host} in
+      arm*b*-*-*)
+	GOARCH=armbe
+        GOARCH_BIGENDIAN=true
+	;;
+    esac
     ;;
 changequote(,)dnl
   i[34567]86-*-* | x86_64-*-*)
@@ -270,7 +276,7 @@  GOARCH_HUGEPAGESIZE="1 << 21"
   m68k*-*-*)
     GOARCH=m68k
     GOARCH_FAMILY=M68K
-    GOARCH_BIGENDIAN=1
+    GOARCH_BIGENDIAN=true
     GOARCH_CACHELINESIZE=16
     GOARCH_PCQUANTUM=4
     GOARCH_INT64ALIGN=2
@@ -313,7 +319,7 @@  GOARCH_HUGEPAGESIZE="1 << 21"
         GOARCH="${GOARCH}le"
         ;;
     *)
-	GOARCH_BIGENDIAN=1
+	GOARCH_BIGENDIAN=true
         ;;
     esac
     GOARCH_CACHELINESIZE=32
@@ -327,7 +333,7 @@  GOARCH_HUGEPAGESIZE="1 << 21"
 #endif],
 [GOARCH=ppc
 GOARCH_FAMILY=PPC
-GOARCH_BIGENDIAN=1
+GOARCH_BIGENDIAN=true
 ],
     [
 GOARCH_FAMILY=PPC64
@@ -338,7 +344,7 @@  AC_COMPILE_IFELSE([
 [GOARCH=ppc64le
 ],
 [GOARCH=ppc64
-GOARCH_BIGENDIAN=1
+GOARCH_BIGENDIAN=true
 ])])
     GOARCH_PHYSPAGESIZE=65536
     GOARCH_PCQUANTUM=4
@@ -356,7 +362,7 @@  GOARCH_MINFRAMESIZE=4
 GOARCH_FAMILY=S390X
 GOARCH_MINFRAMESIZE=8
 ])
-    GOARCH_BIGENDIAN=1
+    GOARCH_BIGENDIAN=true
     GOARCH_CACHELINESIZE=256
     GOARCH_PCQUANTUM=2
     ;;
@@ -371,7 +377,7 @@  GOARCH_FAMILY=SPARC
 [GOARCH=sparc64
 GOARCH_FAMILY=SPARC64
 ])
-    GOARCH_BIGENDIAN=1
+    GOARCH_BIGENDIAN=true
     GOARCH_PHYSPAGESIZE=8192
     GOARCH_PCQUANTUM=4
     ;;
@@ -718,7 +724,7 @@  AC_COMPILE_IFELSE([int i;],
 CFLAGS=$CFLAGS_hold])
 MATH_FLAG=
 if test "$libgo_cv_c_fancymath" = yes; then
-  MATH_FLAG="-mfancy-math-387 -funsafe-math-optimizations"
+  MATH_FLAG="-mfancy-math-387 -funsafe-math-optimizations -fno-math-errno"
 else
   MATH_FLAG="-ffp-contract=off"
 fi
Index: libgo/runtime/go-callers.c
===================================================================
--- libgo/runtime/go-callers.c	(revision 256262)
+++ libgo/runtime/go-callers.c	(working copy)
@@ -127,8 +127,12 @@  callback (void *data, uintptr_t pc, cons
 	    p = filename;
 	  if (__builtin_strcmp (p, "/proc.c") == 0)
 	    {
-	      if (__builtin_strcmp (function, "kickoff") == 0
-		  || __builtin_strcmp (function, "runtime.mstart") == 0
+	      if (__builtin_strcmp (function, "runtime_mstart") == 0)
+		return 1;
+	    }
+	  else if (__builtin_strcmp (p, "/proc.go") == 0)
+	    {
+	      if (__builtin_strcmp (function, "runtime.kickoff") == 0
 		  || __builtin_strcmp (function, "runtime.main") == 0)
 		return 1;
 	    }
@@ -184,6 +188,21 @@  runtime_callers (int32 skip, Location *l
   backtrace_full (__go_get_backtrace_state (), 0, callback, error_callback,
 		  &data);
   runtime_xadd (&runtime_in_callers, -1);
+
+  /* For some reason GCC sometimes loses the name of a thunk function
+     at the top of the stack.  If we are skipping thunks, skip that
+     one too.  */
+  if (!keep_thunks
+      && data.index > 2
+      && locbuf[data.index - 2].function.len == 0
+      && locbuf[data.index - 1].function.str != NULL
+      && __builtin_strcmp ((const char *) locbuf[data.index - 1].function.str,
+			   "runtime.kickoff") == 0)
+    {
+      locbuf[data.index - 2] = locbuf[data.index - 1];
+      --data.index;
+    }
+
   return data.index;
 }
 
Index: libgo/runtime/proc.c
===================================================================
--- libgo/runtime/proc.c	(revision 256262)
+++ libgo/runtime/proc.c	(working copy)
@@ -32,6 +32,8 @@  extern void *__splitstack_makecontext(si
 
 extern void * __splitstack_resetcontext(void *context[10], size_t *);
 
+extern void __splitstack_releasecontext(void *context[10]);
+
 extern void *__splitstack_find(void *, void *, size_t *, void **, void **,
 			       void **);
 
@@ -269,6 +271,9 @@  runtime_newosproc(M *mp)
 		runtime_printf("pthread_create failed: %d\n", ret);
 		runtime_throw("pthread_create");
 	}
+
+	if(pthread_attr_destroy(&attr) != 0)
+		runtime_throw("pthread_attr_destroy");
 }
 
 // Switch context to a different goroutine.  This is like longjmp.
@@ -377,10 +382,12 @@  extern void kickoff(void)
   __asm__(GOSYM_PREFIX "runtime.kickoff");
 extern void minit(void)
   __asm__(GOSYM_PREFIX "runtime.minit");
-extern void mstart1(void)
+extern void mstart1(int32)
   __asm__(GOSYM_PREFIX "runtime.mstart1");
 extern void stopm(void)
   __asm__(GOSYM_PREFIX "runtime.stopm");
+extern void mexit(bool)
+  __asm__(GOSYM_PREFIX "runtime.mexit");
 extern void handoffp(P*)
   __asm__(GOSYM_PREFIX "runtime.handoffp");
 extern void wakep(void)
@@ -519,6 +526,11 @@  runtime_mstart(void *arg)
 		*(int*)0x21 = 0x21;
 	}
 
+	if(mp->exiting) {
+		mexit(true);
+		return nil;
+	}
+
 	// Initial call to getcontext--starting thread.
 
 #ifdef USING_SPLIT_STACK
@@ -528,7 +540,7 @@  runtime_mstart(void *arg)
 	}
 #endif
 
-	mstart1();
+	mstart1(0);
 
 	// mstart1 does not return, but we need a return statement
 	// here to avoid a compiler warning.
@@ -751,6 +763,30 @@  runtime_malg(bool allocatestack, bool si
 	return newg;
 }
 
+void stackfree(G*)
+  __asm__(GOSYM_PREFIX "runtime.stackfree");
+
+// stackfree frees the stack of a g.
+void
+stackfree(G* gp)
+{
+#if USING_SPLIT_STACK
+  __splitstack_releasecontext((void*)(&gp->stackcontext[0]));
+#else
+  // If gcstacksize is 0, the stack is allocated by libc and will be
+  // released when the thread exits. Otherwise, in 64-bit mode it was
+  // allocated using sysAlloc and in 32-bit mode it was allocated
+  // using garbage collected memory.
+  if (gp->gcstacksize != 0) {
+    if (sizeof(void*) == 8) {
+      runtime_sysFree(gp->gcinitialsp, gp->gcstacksize, &getMemstats()->stacks_sys);
+    }
+    gp->gcinitialsp = nil;
+    gp->gcstacksize = 0;
+  }
+#endif
+}
+
 void resetNewG(G*, void **, uintptr*)
   __asm__(GOSYM_PREFIX "runtime.resetNewG");
 
Index: libgo/runtime/runtime.h
===================================================================
--- libgo/runtime/runtime.h	(revision 256262)
+++ libgo/runtime/runtime.h	(working copy)
@@ -265,11 +265,12 @@  void*	runtime_mallocgc(uintptr, const Ty
   __asm__ (GOSYM_PREFIX "runtime.mallocgc");
 void*	runtime_sysAlloc(uintptr, uint64*)
   __asm__ (GOSYM_PREFIX "runtime.sysAlloc");
+void	runtime_sysFree(void*, uintptr, uint64*)
+  __asm__ (GOSYM_PREFIX "runtime.sysFree");
 void	runtime_mprofinit(void);
 #define runtime_getcallersp(p) __builtin_frame_address(0)
 void	runtime_mcall(FuncVal*)
   __asm__ (GOSYM_PREFIX "runtime.mcall");
-uint32	runtime_fastrand(void) __asm__ (GOSYM_PREFIX "runtime.fastrand");
 int32	runtime_timediv(int64, int32, int32*)
   __asm__ (GOSYM_PREFIX "runtime.timediv");
 int32	runtime_round2(int32 x); // round x up to a power of 2.
Index: libgo/runtime/runtime_c.c
===================================================================
--- libgo/runtime/runtime_c.c	(revision 256262)
+++ libgo/runtime/runtime_c.c	(working copy)
@@ -33,21 +33,6 @@  runtime_atoi(const byte *p, intgo len)
 	return n;
 }
 
-uint32
-runtime_fastrand(void)
-{
-	M *m;
-	uint32 x;
-
-	m = runtime_m();
-	x = m->fastrand;
-	x += x;
-	if(x & 0x80000000L)
-		x ^= 0x88888eefUL;
-	m->fastrand = x;
-	return x;
-}
-
 int64
 runtime_cputicks(void)
 {
Index: libgo/testsuite/gotest
===================================================================
--- libgo/testsuite/gotest	(revision 256262)
+++ libgo/testsuite/gotest	(working copy)
@@ -510,7 +510,7 @@  localname() {
 	ppc64*) text="[TD]" ;;
 	esac
 
-	symtogo='sed -e s/_test/XXXtest/ -e s/.*_\([^_]*\.\)/\1/ -e s/XXXtest/_test/'
+	symtogo='sed -e s/_test\([^A-Za-z0-9]\)/XXXtest\1/ -e s/.*_\([^_]*\.\)/\1/ -e s/XXXtest/_test/'
 
 	# test functions are named TestFoo
 	# the grep -v eliminates methods and other special names
Index: libgo/go/runtime/cgo_gccgo.go
===================================================================
--- libgo/go/runtime/cgo_gccgo.go	(revision 256262)
+++ libgo/go/runtime/cgo_gccgo.go	(working copy)
@@ -27,6 +27,13 @@  var iscgo bool
 // The extra M must be created before any C/C++ code calls cgocallback.
 var cgoHasExtraM bool
 
+// cgoAlwaysFalse is a boolean value that is always false.
+// The cgo-generated code says if cgoAlwaysFalse { cgoUse(p) }.
+// The compiler cannot see that cgoAlwaysFalse is always false,
+// so it emits the test and keeps the call, giving the desired
+// escape analysis result. The test is cheaper than the call.
+var cgoAlwaysFalse bool
+
 // Cgocall prepares to call from code written in Go to code written in
 // C/C++. This takes the current goroutine out of the Go scheduler, as
 // though it were making a system call. Otherwise the program can
@@ -37,12 +44,11 @@  var cgoHasExtraM bool
 //     defer syscall.Cgocalldone()
 //     cfunction()
 func Cgocall() {
-	lockOSThread()
 	mp := getg().m
 	mp.ncgocall++
 	mp.ncgo++
-	mp.incgo = true
 	entersyscall(0)
+	mp.incgo = true
 }
 
 // CgocallDone prepares to return to Go code from C/C++ code.
@@ -59,8 +65,6 @@  func CgocallDone() {
 	if readgstatus(gp)&^_Gscan == _Gsyscall {
 		exitsyscall(0)
 	}
-
-	unlockOSThread()
 }
 
 // CgocallBack is used when calling from C/C++ code into Go code.
@@ -78,6 +82,8 @@  func CgocallBack() {
 		mp.dropextram = true
 	}
 
+	lockOSThread()
+
 	exitsyscall(0)
 	gp.m.incgo = false
 
@@ -100,6 +106,8 @@  func CgocallBack() {
 // CgocallBackDone prepares to return to C/C++ code that has called
 // into Go code.
 func CgocallBackDone() {
+	unlockOSThread()
+
 	// If we are the top level Go function called from C/C++, then
 	// we need to release the m. But don't release it if we are
 	// panicing; since this is the top level, we are going to
Index: libgo/go/runtime/mem_gccgo.go
===================================================================
--- libgo/go/runtime/mem_gccgo.go	(revision 256262)
+++ libgo/go/runtime/mem_gccgo.go	(working copy)
@@ -13,9 +13,10 @@  import (
 
 // Functions called by C code.
 //go:linkname sysAlloc runtime.sysAlloc
+//go:linkname sysFree runtime.sysFree
 
 //extern mmap
-func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uintptr) unsafe.Pointer
+func sysMmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uintptr) unsafe.Pointer
 
 //extern munmap
 func munmap(addr unsafe.Pointer, length uintptr) int32
@@ -40,6 +41,14 @@  func init() {
 	}
 }
 
+func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uintptr) (unsafe.Pointer, int) {
+	p := sysMmap(addr, n, prot, flags, fd, off)
+	if uintptr(p) == _MAP_FAILED {
+		return nil, errno()
+	}
+	return p, 0
+}
+
 // NOTE: vec must be just 1 byte long here.
 // Mincore returns ENOMEM if any of the pages are unmapped,
 // but we want to know that all of the pages are unmapped.
@@ -75,31 +84,30 @@  func addrspace_free(v unsafe.Pointer, n
 	return true
 }
 
-func mmap_fixed(v unsafe.Pointer, n uintptr, prot, flags, fd int32, offset uintptr) unsafe.Pointer {
-	p := mmap(v, n, prot, flags, fd, offset)
+func mmap_fixed(v unsafe.Pointer, n uintptr, prot, flags, fd int32, offset uintptr) (unsafe.Pointer, int) {
+	p, err := mmap(v, n, prot, flags, fd, offset)
 	// On some systems, mmap ignores v without
 	// MAP_FIXED, so retry if the address space is free.
 	if p != v && addrspace_free(v, n) {
-		if uintptr(p) != _MAP_FAILED {
+		if err == 0 {
 			munmap(p, n)
 		}
-		p = mmap(v, n, prot, flags|_MAP_FIXED, fd, offset)
+		p, err = mmap(v, n, prot, flags|_MAP_FIXED, fd, offset)
 	}
-	return p
+	return p, err
 }
 
 // Don't split the stack as this method may be invoked without a valid G, which
 // prevents us from allocating more stack.
 //go:nosplit
 func sysAlloc(n uintptr, sysStat *uint64) unsafe.Pointer {
-	p := mmap(nil, n, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_PRIVATE, mmapFD, 0)
-	if uintptr(p) == _MAP_FAILED {
-		errval := errno()
-		if errval == _EACCES {
+	p, err := mmap(nil, n, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_PRIVATE, mmapFD, 0)
+	if err != 0 {
+		if err == _EACCES {
 			print("runtime: mmap: access denied\n")
 			exit(2)
 		}
-		if errval == _EAGAIN {
+		if err == _EAGAIN {
 			print("runtime: mmap: too much locked memory (check 'ulimit -l').\n")
 			exit(2)
 		}
@@ -225,9 +233,9 @@  func sysReserve(v unsafe.Pointer, n uint
 	// if we can reserve at least 64K and check the assumption in SysMap.
 	// Only user-mode Linux (UML) rejects these requests.
 	if sys.PtrSize == 8 && uint64(n) > 1<<32 {
-		p := mmap_fixed(v, 64<<10, _PROT_NONE, _MAP_ANON|_MAP_PRIVATE, mmapFD, 0)
-		if p != v {
-			if uintptr(p) != _MAP_FAILED {
+		p, err := mmap_fixed(v, 64<<10, _PROT_NONE, _MAP_ANON|_MAP_PRIVATE, mmapFD, 0)
+		if p != v || err != 0 {
+			if err == 0 {
 				munmap(p, 64<<10)
 			}
 			return nil
@@ -237,8 +245,8 @@  func sysReserve(v unsafe.Pointer, n uint
 		return v
 	}
 
-	p := mmap(v, n, _PROT_NONE, _MAP_ANON|_MAP_PRIVATE, mmapFD, 0)
-	if uintptr(p) == _MAP_FAILED {
+	p, err := mmap(v, n, _PROT_NONE, _MAP_ANON|_MAP_PRIVATE, mmapFD, 0)
+	if err != 0 {
 		return nil
 	}
 	*reserved = true
@@ -259,12 +267,12 @@  func sysMap(v unsafe.Pointer, n uintptr,
 			// to do this - we do not on other platforms.
 			flags |= _MAP_FIXED
 		}
-		p := mmap_fixed(v, n, _PROT_READ|_PROT_WRITE, flags, mmapFD, 0)
-		if uintptr(p) == _MAP_FAILED && errno() == _ENOMEM {
+		p, err := mmap_fixed(v, n, _PROT_READ|_PROT_WRITE, flags, mmapFD, 0)
+		if err == _ENOMEM {
 			throw("runtime: out of memory")
 		}
-		if p != v {
-			print("runtime: address space conflict: map(", v, ") = ", p, "\n")
+		if p != v || err != 0 {
+			print("runtime: address space conflict: map(", v, ") = ", p, " (err ", err, ")\n")
 			throw("runtime: address space conflict")
 		}
 		return
@@ -275,11 +283,11 @@  func sysMap(v unsafe.Pointer, n uintptr,
 		// So always unmap first even if it is already unmapped.
 		munmap(v, n)
 	}
-	p := mmap(v, n, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_FIXED|_MAP_PRIVATE, mmapFD, 0)
-	if uintptr(p) == _MAP_FAILED && errno() == _ENOMEM {
+	p, err := mmap(v, n, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_FIXED|_MAP_PRIVATE, mmapFD, 0)
+	if err == _ENOMEM {
 		throw("runtime: out of memory")
 	}
-	if p != v {
+	if p != v || err != 0 {
 		throw("runtime: cannot map pages in arena address space")
 	}
 }
Index: libgo/go/runtime/mgc_gccgo.go
===================================================================
--- libgo/go/runtime/mgc_gccgo.go	(revision 256262)
+++ libgo/go/runtime/mgc_gccgo.go	(working copy)
@@ -6,7 +6,10 @@ 
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 // gcRoot is a single GC root: a variable plus a ptrmask.
 type gcRoot struct {
@@ -85,3 +88,21 @@  func checkPreempt() {
 	gp.scanningself = false
 	mcall(gopreempt_m)
 }
+
+// gcWriteBarrier implements a write barrier. This is implemented in
+// assembly in the gc library, but there is no special advantage to
+// doing so with gccgo.
+//go:nosplit
+//go:nowritebarrier
+func gcWriteBarrier(dst *uintptr, src uintptr) {
+	buf := &getg().m.p.ptr().wbBuf
+	next := buf.next
+	np := next + 2*sys.PtrSize
+	buf.next = np
+	*(*uintptr)(unsafe.Pointer(next)) = src
+	*(*uintptr)(unsafe.Pointer(next + sys.PtrSize)) = *dst
+	if np >= buf.end {
+		wbBufFlush(dst, src)
+	}
+	*dst = src
+}
Index: libgo/go/runtime/signal_gccgo.go
===================================================================
--- libgo/go/runtime/signal_gccgo.go	(revision 256262)
+++ libgo/go/runtime/signal_gccgo.go	(working copy)
@@ -46,11 +46,6 @@  func kill(pid _pid_t, sig uint32) int32
 //extern setitimer
 func setitimer(which int32, new *_itimerval, old *_itimerval) int32
 
-type sigTabT struct {
-	flags int32
-	name  string
-}
-
 type sigctxt struct {
 	info *_siginfo_t
 	ctxt unsafe.Pointer
Index: libgo/go/runtime/traceback_gccgo.go
===================================================================
--- libgo/go/runtime/traceback_gccgo.go	(revision 256262)
+++ libgo/go/runtime/traceback_gccgo.go	(working copy)
@@ -52,7 +52,7 @@  func c_callers(skip int32, locbuf *locat
 // callers returns a stack trace of the current goroutine.
 // The gc version of callers takes []uintptr, but we take []location.
 func callers(skip int, locbuf []location) int {
-	n := c_callers(int32(skip), &locbuf[0], int32(len(locbuf)), false)
+	n := c_callers(int32(skip)+1, &locbuf[0], int32(len(locbuf)), false)
 	return int(n)
 }
 
@@ -156,7 +156,7 @@  func goroutineheader(gp *g) {
 	if waitfor >= 1 {
 		print(", ", waitfor, " minutes")
 	}
-	if gp.lockedm != nil {
+	if gp.lockedm != 0 {
 		print(", locked to thread")
 	}
 	print("]:\n")