public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Re: Go patch committed: Update Go library
@ 2011-10-27 17:24 Uros Bizjak
  2011-11-01  9:57 ` Uros Bizjak
  0 siblings, 1 reply; 19+ messages in thread
From: Uros Bizjak @ 2011-10-27 17:24 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: Rainer Orth, gcc-patches

Hello!

> This patch updates the Go library to the most recent weekly release.  I
> think the only potential portability issues here are the use of the
> ipv6_mreq struct.  I'm not entirely sure the new exp/terminal package is
> portable, but it might be.

There are still problems with EpollEvent definition on Alpha, please
see [1] for the analysis.

[1] http://gcc.gnu.org/ml/gcc-patches/2011-07/msg00457.html

Uros.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Go patch committed: Update Go library
  2011-10-27 17:24 Go patch committed: Update Go library Uros Bizjak
@ 2011-11-01  9:57 ` Uros Bizjak
  0 siblings, 0 replies; 19+ messages in thread
From: Uros Bizjak @ 2011-11-01  9:57 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: Rainer Orth, gcc-patches

On Thu, Oct 27, 2011 at 6:42 PM, Uros Bizjak <ubizjak@gmail.com> wrote:

>> This patch updates the Go library to the most recent weekly release.  I
>> think the only potential portability issues here are the use of the
>> ipv6_mreq struct.  I'm not entirely sure the new exp/terminal package is
>> portable, but it might be.
>
> There are still problems with EpollEvent definition on Alpha, please
> see [1] for the analysis.
>
> [1] http://gcc.gnu.org/ml/gcc-patches/2011-07/msg00457.html

Thanks, the resulting epoll.go on Alpha reads as:

epoll.go
package syscall
type EpollEvent struct {
	Events uint32
	Pad [4]byte
	Fd int32
	Pad2 [4]byte
}

However, I am not able to finish compilation of libgo due to unrelated
problem (reported in [1]) with TC[GS]ETS define:

libtool: compile:  /space/uros/gcc-build-go/./gcc/gccgo
-B/space/uros/gcc-build-go/./gcc/
-B/usr/local/alphaev68-unknown-linux-gnu/bin/
-B/usr/local/alphaev68-unknown-linux-gnu/lib/ -isystem
/usr/local/alphaev68-unknown-linux-gnu/include -isystem
/usr/local/alphaev68-unknown-linux-gnu/sys-include -O2 -g -mieee -I .
-c -fgo-prefix=libgo_bytes
../../../gcc-svn/trunk/libgo/go/bytes/buffer.go
../../../gcc-svn/trunk/libgo/go/bytes/bytes.go
../../../gcc-svn/trunk/libgo/go/bytes/bytes_decl.go -o bytes/bytes.o
>/dev/null 2>&1
../../../gcc-svn/trunk/libgo/go/exp/terminal/terminal.go:31:78: error:
reference to undefined identifier ‘syscall.TCGETS’
../../../gcc-svn/trunk/libgo/go/exp/terminal/terminal.go:40:81: error:
reference to undefined identifier ‘syscall.TCGETS’
../../../gcc-svn/trunk/libgo/go/exp/terminal/terminal.go:47:81: error:
reference to undefined identifier ‘syscall.TCSETS’
../../../gcc-svn/trunk/libgo/go/exp/terminal/terminal.go:57:78: error:
reference to undefined identifier ‘syscall.TCSETS’
../../../gcc-svn/trunk/libgo/go/exp/terminal/terminal.go:66:81: error:
reference to undefined identifier ‘syscall.TCGETS’
../../../gcc-svn/trunk/libgo/go/exp/terminal/terminal.go:72:81: error:
reference to undefined identifier ‘syscall.TCSETS’
../../../gcc-svn/trunk/libgo/go/exp/terminal/terminal.go:77:68: error:
reference to undefined identifier ‘syscall.TCSETS’
make[4]: *** [exp/terminal.lo] Error 1


[1] http://gcc.gnu.org/ml/gcc/2011-10/msg00488.html

Uros.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Go patch committed: Update Go library
@ 2011-11-30  4:05 Ian Lance Taylor
  0 siblings, 0 replies; 19+ messages in thread
From: Ian Lance Taylor @ 2011-11-30  4:05 UTC (permalink / raw)
  To: gcc-patches, gofrontend-dev

[-- Attachment #1: Type: text/plain, Size: 224 bytes --]

This patch, arranged by Rémy Oudompheng, updates the Go library to the
weekly.2011-10-25 version of the master Go library.  Bootstrapped and
ran Go testsuite on x86_64-unknown-linux-gnu.  Committed to mainline.

Ian


[-- Attachment #2: patch --]
[-- Type: application/x-bzip, Size: 53450 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Go patch committed: Update Go library
  2011-11-02 18:04     ` David Daney
  2011-11-02 18:23       ` Ian Lance Taylor
@ 2011-11-02 20:24       ` Joseph S. Myers
  1 sibling, 0 replies; 19+ messages in thread
From: Joseph S. Myers @ 2011-11-02 20:24 UTC (permalink / raw)
  To: David Daney; +Cc: Ian Lance Taylor, Rainer Orth, gcc-patches, gofrontend-dev

On Wed, 2 Nov 2011, David Daney wrote:

> On Linux you also have iopl and ioperm which are x86 only.

ARM and Alpha appear to have them as well, though I don't know if anyone 
actually uses them on those targets.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Go patch committed: Update Go library
  2011-11-02 18:23       ` Ian Lance Taylor
@ 2011-11-02 20:23         ` Joseph S. Myers
  0 siblings, 0 replies; 19+ messages in thread
From: Joseph S. Myers @ 2011-11-02 20:23 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: David Daney, Rainer Orth, gcc-patches, gofrontend-dev

On Wed, 2 Nov 2011, Ian Lance Taylor wrote:

> David Daney <david.daney@cavium.com> writes:
> 
> > On MIPS we fail because of those.  I was going to create a patch to
> > move those two to libcall_linux_{386,amd64}.go.  An alternative would
> > be to remove them too.
> 
> Moving them sounds good to me.  libgo already has a framework for
> architecture specific system calls.  It doesn't have a framework for
> glibc version.

autoconf detection of available functions (for functions that aren't 
always available for a given target) would be better than basing things on 
glibc version, anyway - and in libgo, just as in libstdc++, you can safely 
assume target libc is available for running link tests.  autoconf 
detection will probably be required if anyone wants to build libgo with 
uClibc, for example.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Go patch committed: Update Go library
  2011-11-02 18:04     ` David Daney
@ 2011-11-02 18:23       ` Ian Lance Taylor
  2011-11-02 20:23         ` Joseph S. Myers
  2011-11-02 20:24       ` Joseph S. Myers
  1 sibling, 1 reply; 19+ messages in thread
From: Ian Lance Taylor @ 2011-11-02 18:23 UTC (permalink / raw)
  To: David Daney; +Cc: Rainer Orth, gcc-patches, gofrontend-dev

David Daney <david.daney@cavium.com> writes:

> On MIPS we fail because of those.  I was going to create a patch to
> move those two to libcall_linux_{386,amd64}.go.  An alternative would
> be to remove them too.

Moving them sounds good to me.  libgo already has a framework for
architecture specific system calls.  It doesn't have a framework for
glibc version.

Ian

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Go patch committed: Update Go library
  2011-11-02 18:01   ` Ian Lance Taylor
  2011-11-02 18:04     ` David Daney
@ 2011-11-02 18:17     ` Rainer Orth
  1 sibling, 0 replies; 19+ messages in thread
From: Rainer Orth @ 2011-11-02 18:17 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-patches, gofrontend-dev

Ian Lance Taylor <iant@google.com> writes:

> I assume that CentOS 5.5 uses some version of glibc before version 2.6.

Right:

$ /lib/libc.so.6 
GNU C Library stable release version 2.5, by Roland McGrath et al.

> The three functions you mention are not supported in older versions of
> glibc.  Fortunately, they are not called anywhere else in the library,
> so this patch takes the easy way out and simply removes them.
> Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu.
> Committed to mainline.

Fine, thanks.

      Rainer

-- 
-----------------------------------------------------------------------------
Rainer Orth, Center for Biotechnology, Bielefeld University

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Go patch committed: Update Go library
  2011-11-02 18:01   ` Ian Lance Taylor
@ 2011-11-02 18:04     ` David Daney
  2011-11-02 18:23       ` Ian Lance Taylor
  2011-11-02 20:24       ` Joseph S. Myers
  2011-11-02 18:17     ` Rainer Orth
  1 sibling, 2 replies; 19+ messages in thread
From: David Daney @ 2011-11-02 18:04 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: Rainer Orth, gcc-patches, gofrontend-dev

On 11/02/2011 10:54 AM, Ian Lance Taylor wrote:
> Rainer Orth<ro@CeBiTec.Uni-Bielefeld.DE>  writes:
>
>> All go and libgo execution tests are failing for me with this patch on
>> x86_64-unknown-linux-gnu (CentOS 5.5, I think):
>>
>> output is:
>> /var/gcc/regression/trunk/2.6.18-gcc-gas-gld/build/x86_64-unknown-linux-gnu/./li
>> bgo/.libs/libgo.so: undefined reference to `inotify_init1'
>> /var/gcc/regression/trunk/2.6.18-gcc-gas-gld/build/x86_64-unknown-linux-gnu/./li
>> bgo/.libs/libgo.so: undefined reference to `fallocate'
>> /var/gcc/regression/trunk/2.6.18-gcc-gas-gld/build/x86_64-unknown-linux-gnu/./li
>> bgo/.libs/libgo.so: undefined reference to `sync_file_range'
>> collect2: error: ld returned 1 exit status
>>
>> FAIL: go.go-torture/execute/array-1.go compilation,  -O0
>
> I assume that CentOS 5.5 uses some version of glibc before version 2.6.
> The three functions you mention are not supported in older versions of
> glibc.  Fortunately, they are not called anywhere else in the library,
> so this patch takes the easy way out and simply removes them.
> Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu.
> Committed to mainline.

On Linux you also have iopl and ioperm which are x86 only.

On MIPS we fail because of those.  I was going to create a patch to move 
those two to libcall_linux_{386,amd64}.go.  An alternative would be to 
remove them too.

David Daney

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Go patch committed: Update Go library
  2011-11-02 17:11 ` Rainer Orth
@ 2011-11-02 18:01   ` Ian Lance Taylor
  2011-11-02 18:04     ` David Daney
  2011-11-02 18:17     ` Rainer Orth
  0 siblings, 2 replies; 19+ messages in thread
From: Ian Lance Taylor @ 2011-11-02 18:01 UTC (permalink / raw)
  To: Rainer Orth; +Cc: gcc-patches, gofrontend-dev

[-- Attachment #1: Type: text/plain, Size: 1095 bytes --]

Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> writes:

> All go and libgo execution tests are failing for me with this patch on
> x86_64-unknown-linux-gnu (CentOS 5.5, I think):
>
> output is:
> /var/gcc/regression/trunk/2.6.18-gcc-gas-gld/build/x86_64-unknown-linux-gnu/./li
> bgo/.libs/libgo.so: undefined reference to `inotify_init1'
> /var/gcc/regression/trunk/2.6.18-gcc-gas-gld/build/x86_64-unknown-linux-gnu/./li
> bgo/.libs/libgo.so: undefined reference to `fallocate'
> /var/gcc/regression/trunk/2.6.18-gcc-gas-gld/build/x86_64-unknown-linux-gnu/./li
> bgo/.libs/libgo.so: undefined reference to `sync_file_range'
> collect2: error: ld returned 1 exit status
>
> FAIL: go.go-torture/execute/array-1.go compilation,  -O0 

I assume that CentOS 5.5 uses some version of glibc before version 2.6.
The three functions you mention are not supported in older versions of
glibc.  Fortunately, they are not called anywhere else in the library,
so this patch takes the easy way out and simply removes them.
Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu.
Committed to mainline.

Ian


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: patch --]
[-- Type: text/x-diff, Size: 1785 bytes --]

diff -r c0c039af2298 libgo/go/syscall/libcall_linux.go
--- a/libgo/go/syscall/libcall_linux.go	Wed Nov 02 09:48:33 2011 -0700
+++ b/libgo/go/syscall/libcall_linux.go	Wed Nov 02 10:32:33 2011 -0700
@@ -186,8 +186,9 @@
 //sys	Faccessat(dirfd int, path string, mode uint32, flags int) (errno int)
 //faccessat(dirfd int, pathname *byte, mode int, flags int) int
 
-//sys	Fallocate(fd int, mode uint32, off int64, len int64) (errno int)
-//fallocate(fd int, mode int, offset Offset_t, len Offset_t) int
+// FIXME: Only in glibc 2.10 and later.
+// //sys	Fallocate(fd int, mode uint32, off int64, len int64) (errno int)
+// //fallocate(fd int, mode int, offset Offset_t, len Offset_t) int
 
 //sys	Fchmodat(dirfd int, path string, mode uint32, flags int) (errno int)
 //fchmodat(dirfd int, pathname *byte, mode Mode_t, flags int) int
@@ -223,8 +224,9 @@
 //sysnb	InotifyInit() (fd int, errno int)
 //inotify_init() int
 
-//sysnb	InotifyInit1(flags int) (fd int, errno int)
-//inotify_init1(flags int) int
+// FIXME: Only in glibc 2.9 and later.
+// //sysnb	InotifyInit1(flags int) (fd int, errno int)
+// //inotify_init1(flags int) int
 
 //sysnb	InotifyRmWatch(fd int, watchdesc uint32) (success int, errno int)
 //inotify_rm_watch(fd int, wd uint32) int
@@ -298,8 +300,9 @@
 // //sys	Statfs(path string, buf *Statfs_t) (errno int)
 // //statfs(path *byte, buf *Statfs_t) int
 
-//sys	SyncFileRange(fd int, off int64, n int64, flags int) (errno int)
-//sync_file_range(fd int, off Offset_t, n Offset_t, flags uint) int
+// FIXME: Only in glibc 2.6 and later.
+// //sys	SyncFileRange(fd int, off int64, n int64, flags int) (errno int)
+// //sync_file_range(fd int, off Offset_t, n Offset_t, flags uint) int
 
 // FIXME: mksysinfo Sysinfo_t
 // //sysnb	Sysinfo(info *Sysinfo_t) (errno int)

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Go patch committed: Update Go library
  2011-10-27  3:07 Ian Lance Taylor
                   ` (2 preceding siblings ...)
       [not found] ` <4EB15B7E.4050006@ubuntu.com>
@ 2011-11-02 17:11 ` Rainer Orth
  2011-11-02 18:01   ` Ian Lance Taylor
  3 siblings, 1 reply; 19+ messages in thread
From: Rainer Orth @ 2011-11-02 17:11 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-patches, gofrontend-dev

Ian Lance Taylor <iant@google.com> writes:

> This patch updates the Go library to the most recent weekly release.  I
> think the only potential portability issues here are the use of the
> ipv6_mreq struct.  I'm not entirely sure the new exp/terminal package is
> portable, but it might be.

All go and libgo execution tests are failing for me with this patch on
x86_64-unknown-linux-gnu (CentOS 5.5, I think):

output is:
/var/gcc/regression/trunk/2.6.18-gcc-gas-gld/build/x86_64-unknown-linux-gnu/./li
bgo/.libs/libgo.so: undefined reference to `inotify_init1'
/var/gcc/regression/trunk/2.6.18-gcc-gas-gld/build/x86_64-unknown-linux-gnu/./li
bgo/.libs/libgo.so: undefined reference to `fallocate'
/var/gcc/regression/trunk/2.6.18-gcc-gas-gld/build/x86_64-unknown-linux-gnu/./li
bgo/.libs/libgo.so: undefined reference to `sync_file_range'
collect2: error: ld returned 1 exit status

FAIL: go.go-torture/execute/array-1.go compilation,  -O0 

	Rainer

-- 
-----------------------------------------------------------------------------
Rainer Orth, Center for Biotechnology, Bielefeld University

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Go patch committed: Update Go library
       [not found] ` <4EB15B7E.4050006@ubuntu.com>
@ 2011-11-02 16:21   ` Ian Lance Taylor
  0 siblings, 0 replies; 19+ messages in thread
From: Ian Lance Taylor @ 2011-11-02 16:21 UTC (permalink / raw)
  To: Matthias Klose; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2585 bytes --]

Matthias Klose <doko@ubuntu.com> writes:

> I see a build failure with the last update, not yet sure what is going wrong.
>
> /bin/mkdir -p exp; files=`echo ../../../src/libgo/go/exp/ebnf/ebnf.go
> ../../../src/libgo/go/exp/ebnf/parser.go go/scanner.gox go/token.gox os.gox
> strconv.gox unicode.gox utf8.gox | sed -e 's/[^ ]*\.gox//g'`; /bin/bash
> ./libtool --tag GO --mode=compile
> /home/packages/gcc/snap/gcc-snapshot-20111101/build/./gcc/gccgo
> -B/home/packages/gcc/snap/gcc-snapshot-20111101/build/./gcc/
> -B/usr/lib/gcc-snapshot/x86_64-linux-gnu/bin/
> -B/usr/lib/gcc-snapshot/x86_64-linux-gnu/lib/ -isystem
> /usr/lib/gcc-snapshot/x86_64-linux-gnu/include -isystem
> /usr/lib/gcc-snapshot/x86_64-linux-gnu/sys-include     -minline-all-stringops
> -O2 -g -I . -c -fgo-prefix="libgo_exp" -o exp/ebnf.lo $files
> libtool: compile:
> /home/packages/gcc/snap/gcc-snapshot-20111101/build/./gcc/gccgo
> -B/home/packages/gcc/snap/gcc-snapshot-20111101/build/./gcc/
> -B/usr/lib/gcc-snapshot/x86_64-linux-gnu/bin/
> -B/usr/lib/gcc-snapshot/x86_64-linux-gnu/lib/ -isystem
> /usr/lib/gcc-snapshot/x86_64-linux-gnu/include -isystem
> /usr/lib/gcc-snapshot/x86_64-linux-gnu/sys-include -minline-all-stringops -O2 -g
> -I . -c -fgo-prefix=libgo_exp ../../../src/libgo/go/exp/ebnf/ebnf.go
> ../../../src/libgo/go/exp/ebnf/parser.go  -fPIC -o exp/.libs/ebnf.o
> ../../../src/libgo/go/exp/ebnf/ebnf.go:28:9: error: import file 'scanner' not found
> ../../../src/libgo/go/exp/ebnf/ebnf.go:55:26: error: expected package
> ../../../src/libgo/go/exp/ebnf/ebnf.go:66:16: error: expected package
> ../../../src/libgo/go/exp/ebnf/ebnf.go:77:20: error: expected package
> ../../../src/libgo/go/exp/ebnf/ebnf.go:83:20: error: expected package
> ../../../src/libgo/go/exp/ebnf/ebnf.go:94:17: error: expected package
> ../../../src/libgo/go/exp/ebnf/ebnf.go:100:17: error: expected package
> ../../../src/libgo/go/exp/ebnf/ebnf.go:106:17: error: expected package
> ../../../src/libgo/go/exp/ebnf/ebnf.go:118:17: error: expected package
> ../../../src/libgo/go/exp/ebnf/ebnf.go:128:35: error: expected package
> ../../../src/libgo/go/exp/ebnf/ebnf.go:128:45: error: expected ';' or newline
> after top level declaration
> ../../../src/libgo/go/exp/ebnf/ebnf.go:129:32: error: expected package
> ../../../src/libgo/go/exp/ebnf/ebnf.go:129:45: error: expected ';' or newline
> after top level declaration
> ../../../src/libgo/go/exp/ebnf/ebnf.go:130:29: error: expected package


I messed up a Makefile dependency.  Fixed like so.  Bootstrapped on
x86_64-unknown-linux-gnu.  Committed to mainline.

Ian


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: patch --]
[-- Type: text/x-diff, Size: 439 bytes --]

diff -r d884462fd93f libgo/Makefile.am
--- a/libgo/Makefile.am	Mon Oct 31 22:19:13 2011 -0700
+++ b/libgo/Makefile.am	Wed Nov 02 08:57:56 2011 -0700
@@ -2639,7 +2639,7 @@
 	@$(CHECK)
 .PHONY: encoding/pem/check
 
-exp/ebnf.lo: $(go_exp_ebnf_files) go/scanner.gox go/token.gox os.gox \
+exp/ebnf.lo: $(go_exp_ebnf_files) scanner.gox go/token.gox os.gox \
 		strconv.gox unicode.gox utf8.gox
 	$(BUILDPACKAGE)
 exp/ebnf/check: $(CHECK_DEPS)

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Go patch committed: Update Go library
  2011-10-31 17:57 ` Rainer Orth
  2011-11-01  4:55   ` Ian Lance Taylor
@ 2011-11-01  5:21   ` Ian Lance Taylor
  1 sibling, 0 replies; 19+ messages in thread
From: Ian Lance Taylor @ 2011-11-01  5:21 UTC (permalink / raw)
  To: Rainer Orth; +Cc: gcc-patches, gofrontend-dev

[-- Attachment #1: Type: text/plain, Size: 1504 bytes --]

Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> writes:

> After this change, I'm seeing another issue: most 32-bit go execution
> tests fail like this on Solaris 11/x86:
>
> /vol/gcc/src/hg/trunk/local/libgo/runtime/malloc.goc:366: libgo assertion failure
> FAIL: go.go-torture/execute/array-1.go execution,  -O0 
>
> Running the test under truss, I find:
>
> 14261:	mmap(0xFF000000, 805306368, PROT_NONE, MAP_PRIVATE|MAP_ANON, -1, 0) Err#12 ENOMEM
>
> With truss -u (user function tracing), I see:
>
> 14285/1@1:	-> libgo:runtime_mallocinit()
> 14285/1@1:	  -> libgo:runtime_InitSizes()
> 14285/1@1:	  <- libgo:runtime_InitSizes() = 2
> 14285/1@1:	  -> libgo:runtime_SysReserve()
> 14285/1:	mmap(0xFF000000, 805306368, PROT_NONE, MAP_PRIVATE|MAP_ANON, -1, 0) Err#12 ENOMEM
> 14285/1@1:	  <- libgo:runtime_SysReserve() = -1
> 14285/1@1:	  -> libgo:__go_assert_fail()
>
> If I remove the adjustment in runtime/malloc.goc (runtime_mallocinit),
> the test passes:
>
> 14445/1:	mmap(0xFEF78114, 805306368, PROT_NONE, MAP_PRIVATE|MAP_ANON, -1, 0) = 0xCE000000
>
> This stuff seems incredibly fragile, and I don't exactly understand
> why.

I don't understand why one case passes and the other fails.  In an
attempt to make this work better, I committed the appended patch.  It
will at least avoid asking for impossible situations, such as the one in
this example.  Bootstrapped and ran Go testsuite on
x86_64-unknown-linux-gnu (including the 32-bit tests, which I always run
anyhow).  Committed to mainline.

Ian


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: patch --]
[-- Type: text/x-diff, Size: 571 bytes --]

diff -r 250b34075533 libgo/runtime/malloc.goc
--- a/libgo/runtime/malloc.goc	Mon Oct 31 21:54:06 2011 -0700
+++ b/libgo/runtime/malloc.goc	Mon Oct 31 22:18:21 2011 -0700
@@ -358,6 +358,8 @@
 		// away from the running binary image and then round up
 		// to a MB boundary.
 		want = (byte*)(((uintptr)end + (1<<18) + (1<<20) - 1)&~((1<<20)-1));
+		if(0xffffffff - (uintptr)want <= bitmap_size + arena_size)
+		  want = 0;
 		p = runtime_SysReserve(want, bitmap_size + arena_size);
 		if(p == nil)
 			runtime_throw("runtime: cannot reserve arena virtual address space");

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Go patch committed: Update Go library
  2011-10-31 17:57 ` Rainer Orth
@ 2011-11-01  4:55   ` Ian Lance Taylor
  2011-11-01  5:21   ` Ian Lance Taylor
  1 sibling, 0 replies; 19+ messages in thread
From: Ian Lance Taylor @ 2011-11-01  4:55 UTC (permalink / raw)
  To: Rainer Orth; +Cc: gcc-patches, gofrontend-dev

[-- Attachment #1: Type: text/plain, Size: 587 bytes --]

Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> writes:

> * The message points to the wrong line due to a broken test: malloc.goc
>   has:
>
> 		p = runtime_SysReserve((void*)(0x00f8ULL<<32), bitmap_size + arena_size);
> 		if(p == nil)
> 			runtime_throw("runtime: cannot reserve arena virtual address space");
>
>   On failure, p will be MAP_FAILED ((void *)-1), not nil, so the wrong
>   assertion it thrown.

I fixed this particular issue as follows, copying the code from the
other Go library.  Bootstrapped and ran Go testsuite on
x86_64-unknown-linux-gnu.  Committed to mainline.

Ian


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: patch --]
[-- Type: text/x-diff, Size: 657 bytes --]

diff -r 1bc825e20b21 libgo/runtime/mem.c
--- a/libgo/runtime/mem.c	Mon Oct 31 21:07:36 2011 -0700
+++ b/libgo/runtime/mem.c	Mon Oct 31 21:53:12 2011 -0700
@@ -85,6 +85,7 @@
 runtime_SysReserve(void *v, uintptr n)
 {
 	int fd = -1;
+	void *p;
 
 	// On 64-bit, people with ulimit -v set complain if we reserve too
 	// much address space.  Instead, assume that the reservation is okay
@@ -103,7 +104,11 @@
 	fd = dev_zero;
 #endif
 
-	return runtime_mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, fd, 0);
+	p = runtime_mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, fd, 0);
+	if((uintptr)p < 4096 || -(uintptr)p < 4096) {
+		return nil;
+	}
+	return p;
 }
 
 void

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Go patch committed: Update Go library
  2011-10-27 14:46 ` Rainer Orth
  2011-10-27 17:36   ` Ian Lance Taylor
@ 2011-10-31 23:06   ` Ian Lance Taylor
  1 sibling, 0 replies; 19+ messages in thread
From: Ian Lance Taylor @ 2011-10-31 23:06 UTC (permalink / raw)
  To: Rainer Orth; +Cc: gcc-patches, gofrontend-dev

[-- Attachment #1: Type: text/plain, Size: 575 bytes --]

Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> writes:

> the only issue I've found on Solaris is the use of pthread_yield, which
> doesn't exist even on Solaris 11.  The following patch checks for this,
> and falls back to thr_yield if available.

Rather than that patch, I changed the code to use sched_yield rather
than pthread_yield.  I realized that libgo is already using sched_yield,
in runtime/go-sched.c.  There shouldn't be any portability penalty to
also using it in yield.c.

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

Ian


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: patch --]
[-- Type: text/x-diff, Size: 479 bytes --]

diff -r 7135ea46b116 libgo/runtime/yield.c
--- a/libgo/runtime/yield.c	Mon Oct 31 14:53:56 2011 -0700
+++ b/libgo/runtime/yield.c	Mon Oct 31 14:58:19 2011 -0700
@@ -9,7 +9,7 @@
 #include <stddef.h>
 #include <sys/types.h>
 #include <sys/time.h>
-#include <pthread.h>
+#include <sched.h>
 #include <unistd.h>
 
 #ifdef HAVE_SYS_SELECT_H
@@ -38,7 +38,7 @@
 void
 runtime_osyield (void)
 {
-  pthread_yield ();
+  sched_yield ();
 }
 
 /* Sleep for some number of microseconds.  */

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Go patch committed: Update Go library
  2011-10-27  3:07 Ian Lance Taylor
  2011-10-27 14:46 ` Rainer Orth
@ 2011-10-31 17:57 ` Rainer Orth
  2011-11-01  4:55   ` Ian Lance Taylor
  2011-11-01  5:21   ` Ian Lance Taylor
       [not found] ` <4EB15B7E.4050006@ubuntu.com>
  2011-11-02 17:11 ` Rainer Orth
  3 siblings, 2 replies; 19+ messages in thread
From: Rainer Orth @ 2011-10-31 17:57 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-patches, gofrontend-dev

Ian Lance Taylor <iant@google.com> writes:

> This patch updates the Go library to the most recent weekly release.  I
> think the only potential portability issues here are the use of the
> ipv6_mreq struct.  I'm not entirely sure the new exp/terminal package is
> portable, but it might be.
>
> I have not included the entire patch here, because it is too large and
> it's just copying changes anyhow.  I've included all patches to files
> which are specific to the Go frontend version.

After this change, I'm seeing another issue: most 32-bit go execution
tests fail like this on Solaris 11/x86:

/vol/gcc/src/hg/trunk/local/libgo/runtime/malloc.goc:366: libgo assertion failure
FAIL: go.go-torture/execute/array-1.go execution,  -O0 

Running the test under truss, I find:

14261:	mmap(0xFF000000, 805306368, PROT_NONE, MAP_PRIVATE|MAP_ANON, -1, 0) Err#12 ENOMEM

With truss -u (user function tracing), I see:

14285/1@1:	-> libgo:runtime_mallocinit()
14285/1@1:	  -> libgo:runtime_InitSizes()
14285/1@1:	  <- libgo:runtime_InitSizes() = 2
14285/1@1:	  -> libgo:runtime_SysReserve()
14285/1:	mmap(0xFF000000, 805306368, PROT_NONE, MAP_PRIVATE|MAP_ANON, -1, 0) Err#12 ENOMEM
14285/1@1:	  <- libgo:runtime_SysReserve() = -1
14285/1@1:	  -> libgo:__go_assert_fail()

If I remove the adjustment in runtime/malloc.goc (runtime_mallocinit),
the test passes:

14445/1:	mmap(0xFEF78114, 805306368, PROT_NONE, MAP_PRIVATE|MAP_ANON, -1, 0) = 0xCE000000

This stuff seems incredibly fragile, and I don't exactly understand
why.  Besides, the assertion failure above is strange/wrong in two ways:

/vol/gcc/src/hg/trunk/local/libgo/runtime/malloc.goc:366: libgo assertion failure

* I'd expect to see the message from runtime_throw() here, not just
  `libgo assertion failure'.

* The message points to the wrong line due to a broken test: malloc.goc
  has:

		p = runtime_SysReserve((void*)(0x00f8ULL<<32), bitmap_size + arena_size);
		if(p == nil)
			runtime_throw("runtime: cannot reserve arena virtual address space");

  On failure, p will be MAP_FAILED ((void *)-1), not nil, so the wrong
  assertion it thrown.

	Rainer

-- 
-----------------------------------------------------------------------------
Rainer Orth, Center for Biotechnology, Bielefeld University

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Go patch committed: Update Go library
  2011-10-27 17:36   ` Ian Lance Taylor
@ 2011-10-27 17:50     ` Rainer Orth
  0 siblings, 0 replies; 19+ messages in thread
From: Rainer Orth @ 2011-10-27 17:50 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-patches, gofrontend-dev

Ian Lance Taylor <iant@google.com> writes:

> Thanks--but is sched_yield available?  I realized that I misread the man
> page; it looks like sched_yield is more portable than pthread_yield.

It is, but before Solaris 11 it only lives in librt.

	Rainer

-- 
-----------------------------------------------------------------------------
Rainer Orth, Center for Biotechnology, Bielefeld University

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Go patch committed: Update Go library
  2011-10-27 14:46 ` Rainer Orth
@ 2011-10-27 17:36   ` Ian Lance Taylor
  2011-10-27 17:50     ` Rainer Orth
  2011-10-31 23:06   ` Ian Lance Taylor
  1 sibling, 1 reply; 19+ messages in thread
From: Ian Lance Taylor @ 2011-10-27 17:36 UTC (permalink / raw)
  To: Rainer Orth; +Cc: gcc-patches, gofrontend-dev

Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> writes:

> the only issue I've found on Solaris is the use of pthread_yield, which
> doesn't exist even on Solaris 11.  The following patch checks for this,
> and falls back to thr_yield if available.

Thanks--but is sched_yield available?  I realized that I misread the man
page; it looks like sched_yield is more portable than pthread_yield.

Ian

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Go patch committed: Update Go library
  2011-10-27  3:07 Ian Lance Taylor
@ 2011-10-27 14:46 ` Rainer Orth
  2011-10-27 17:36   ` Ian Lance Taylor
  2011-10-31 23:06   ` Ian Lance Taylor
  2011-10-31 17:57 ` Rainer Orth
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 19+ messages in thread
From: Rainer Orth @ 2011-10-27 14:46 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-patches, gofrontend-dev

[-- Attachment #1: Type: text/plain, Size: 840 bytes --]

Ian,

> This patch updates the Go library to the most recent weekly release.  I
> think the only potential portability issues here are the use of the
> ipv6_mreq struct.  I'm not entirely sure the new exp/terminal package is
> portable, but it might be.

the only issue I've found on Solaris is the use of pthread_yield, which
doesn't exist even on Solaris 11.  The following patch checks for this,
and falls back to thr_yield if available.

It allowed i386-pc-solaris2.1[01] bootstraps to complete without
regressions.

	Rainer


2011-10-27  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>

	* configure.ac: Check for <thread.h>.
	Check for pthread_yield, thr_yield.
	* configure: Regenerate.
	* config.h.in: Regenerate.
	* runtime/yield.c [HAVE_THREAD_H]: Include <thread.h>.
	(runtime_osyield): Call thr_yield or pthread_yield if available.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: sol2-libgo-pthread_yield.patch --]
[-- Type: text/x-patch, Size: 1510 bytes --]

diff --git a/libgo/configure.ac b/libgo/configure.ac
--- a/libgo/configure.ac
+++ b/libgo/configure.ac
@@ -442,7 +442,7 @@ no)
   ;;
 esac
 
-AC_CHECK_HEADERS(sys/mman.h syscall.h sys/epoll.h sys/ptrace.h sys/syscall.h sys/user.h sys/utsname.h sys/select.h sys/socket.h net/if.h)
+AC_CHECK_HEADERS(sys/mman.h syscall.h sys/epoll.h sys/ptrace.h sys/syscall.h sys/user.h sys/utsname.h sys/select.h sys/socket.h net/if.h thread.h)
 
 AC_CHECK_HEADERS([linux/filter.h linux/netlink.h linux/rtnetlink.h], [], [],
 [#ifdef HAVE_SYS_SOCKET_H
@@ -452,7 +452,7 @@ AC_CHECK_HEADERS([linux/filter.h linux/n
 
 AM_CONDITIONAL(HAVE_SYS_MMAN_H, test "$ac_cv_header_sys_mman_h" = yes)
 
-AC_CHECK_FUNCS(srandom random strerror_r strsignal wait4 mincore setenv)
+AC_CHECK_FUNCS(srandom random strerror_r strsignal wait4 mincore setenv pthread_yield thr_yield)
 AM_CONDITIONAL(HAVE_STRERROR_R, test "$ac_cv_func_strerror_r" = yes)
 AM_CONDITIONAL(HAVE_WAIT4, test "$ac_cv_func_wait4" = yes)
 
diff --git a/libgo/runtime/yield.c b/libgo/runtime/yield.c
--- a/libgo/runtime/yield.c
+++ b/libgo/runtime/yield.c
@@ -9,6 +9,9 @@
 #include <stddef.h>
 #include <sys/types.h>
 #include <sys/time.h>
+#ifdef HAVE_THREAD_H
+#include <thread.h>
+#endif
 #include <pthread.h>
 #include <unistd.h>
 
@@ -38,7 +41,11 @@ runtime_procyield (uint32 cnt)
 void
 runtime_osyield (void)
 {
+#ifdef HAVE_THR_YIELD
+  thr_yield ();
+#elif defined(HAVE_PTHREAD_YIELD)
   pthread_yield ();
+#endif
 }
 
 /* Sleep for some number of microseconds.  */

[-- Attachment #3: Type: text/plain, Size: 144 bytes --]



-- 
-----------------------------------------------------------------------------
Rainer Orth, Center for Biotechnology, Bielefeld University

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Go patch committed: Update Go library
@ 2011-10-27  3:07 Ian Lance Taylor
  2011-10-27 14:46 ` Rainer Orth
                   ` (3 more replies)
  0 siblings, 4 replies; 19+ messages in thread
From: Ian Lance Taylor @ 2011-10-27  3:07 UTC (permalink / raw)
  To: gcc-patches, gofrontend-dev; +Cc: Rainer Orth

[-- Attachment #1: Type: text/plain, Size: 522 bytes --]

This patch updates the Go library to the most recent weekly release.  I
think the only potential portability issues here are the use of the
ipv6_mreq struct.  I'm not entirely sure the new exp/terminal package is
portable, but it might be.

I have not included the entire patch here, because it is too large and
it's just copying changes anyhow.  I've included all patches to files
which are specific to the Go frontend version.

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

Ian


[-- Attachment #2: patch --]
[-- Type: text/x-diff, Size: 98529 bytes --]

diff -r c36211271569 libgo/MERGE
--- a/libgo/MERGE	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/MERGE	Wed Oct 26 16:12:38 2011 -0700
@@ -1,4 +1,4 @@
-c1702f36df03
+6d7136d74b65
 
 The first line of this file holds the Mercurial revision number of the
 last merge done from the master library sources.
diff -r c36211271569 libgo/Makefile.am
--- a/libgo/Makefile.am	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/Makefile.am	Wed Oct 26 16:12:38 2011 -0700
@@ -107,7 +107,6 @@
 	cmath.gox \
 	crypto.gox \
 	csv.gox \
-	ebnf.gox \
 	exec.gox \
 	expvar.gox \
 	flag.gox \
@@ -124,7 +123,6 @@
 	mail.gox \
 	mime.gox \
 	net.gox \
-	netchan.gox \
 	os.gox \
 	patch.gox \
 	path.gox \
@@ -145,7 +143,6 @@
 	template.gox \
 	testing.gox \
 	time.gox \
-	try.gox \
 	unicode.gox \
 	url.gox \
 	utf16.gox \
@@ -173,13 +170,13 @@
 toolexeclibgocontainer_DATA = \
 	container/heap.gox \
 	container/list.gox \
-	container/ring.gox \
-	container/vector.gox
+	container/ring.gox
 
 toolexeclibgocryptodir = $(toolexeclibgodir)/crypto
 
 toolexeclibgocrypto_DATA = \
 	crypto/aes.gox \
+	crypto/bcrypt.gox \
 	crypto/blowfish.gox \
 	crypto/cast5.gox \
 	crypto/cipher.gox \
@@ -242,19 +239,24 @@
 toolexeclibgoexpdir = $(toolexeclibgodir)/exp
 
 toolexeclibgoexp_DATA = \
+	exp/ebnf.gox \
 	exp/gui.gox \
 	exp/norm.gox \
-	exp/regexp.gox
+	exp/spdy.gox \
+	exp/sql.gox \
+	exp/ssh.gox \
+	exp/terminal.gox \
+	exp/types.gox
 
 toolexeclibgoexpguidir = $(toolexeclibgoexpdir)/gui
 
 toolexeclibgoexpgui_DATA = \
 	exp/gui/x11.gox
 
-toolexeclibgoexpregexpdir = $(toolexeclibgoexpdir)/regexp
-
-toolexeclibgoexpregexp_DATA = \
-	exp/regexp/syntax.gox
+toolexeclibgoexpsqldir = $(toolexeclibgoexpdir)/sql
+
+toolexeclibgoexpsql_DATA = \
+	exp/sql/driver.gox
 
 toolexeclibgoexptemplatedir = $(toolexeclibgoexpdir)/template
 
@@ -270,9 +272,7 @@
 	go/parser.gox \
 	go/printer.gox \
 	go/scanner.gox \
-	go/token.gox \
-	go/typechecker.gox \
-	go/types.gox
+	go/token.gox
 
 toolexeclibgohashdir = $(toolexeclibgodir)/hash
 
@@ -288,13 +288,13 @@
 	http/cgi.gox \
 	http/fcgi.gox \
 	http/httptest.gox \
-	http/pprof.gox \
-	http/spdy.gox
+	http/pprof.gox
 
 toolexeclibgoimagedir = $(toolexeclibgodir)/image
 
 toolexeclibgoimage_DATA = \
 	image/bmp.gox \
+	image/color.gox \
 	image/draw.gox \
 	image/gif.gox \
 	image/jpeg.gox \
@@ -326,6 +326,8 @@
 toolexeclibgoolddir = $(toolexeclibgodir)/old
 
 toolexeclibgoold_DATA = \
+	old/netchan.gox \
+	old/regexp.gox \
 	old/template.gox
 
 toolexeclibgoosdir = $(toolexeclibgodir)/os
@@ -347,6 +349,11 @@
 toolexeclibgopath_DATA = \
 	path/filepath.gox
 
+toolexeclibgoregexpdir = $(toolexeclibgodir)/regexp
+
+toolexeclibgoregexp_DATA = \
+	regexp/syntax.gox
+
 toolexeclibgorpcdir = $(toolexeclibgodir)/rpc
 
 toolexeclibgorpc_DATA = \
@@ -479,6 +486,7 @@
 	runtime/msize.c \
 	runtime/proc.c \
 	runtime/thread.c \
+	runtime/yield.c \
 	$(rtems_task_variable_add_file) \
 	chan.c \
 	iface.c \
@@ -559,10 +567,6 @@
 	go/csv/reader.go \
 	go/csv/writer.go
 
-go_ebnf_files = \
-	go/ebnf/ebnf.go \
-	go/ebnf/parser.go
-
 go_exec_files = \
 	go/exec/exec.go \
 	go/exec/lp_unix.go
@@ -598,6 +602,7 @@
 	go/html/escape.go \
 	go/html/node.go \
 	go/html/parse.go \
+	go/html/render.go \
 	go/html/token.go
 
 go_http_files = \
@@ -605,6 +610,7 @@
 	go/http/client.go \
 	go/http/cookie.go \
 	go/http/dump.go \
+	go/http/filetransport.go \
 	go/http/fs.go \
 	go/http/header.go \
 	go/http/lex.go \
@@ -619,7 +625,6 @@
 	go/http/transport.go
 
 go_image_files = \
-	go/image/color.go \
 	go/image/format.go \
 	go/image/geom.go \
 	go/image/image.go \
@@ -642,6 +647,7 @@
 	go/log/log.go
 
 go_math_files = \
+	go/math/abs.go \
 	go/math/acosh.go \
 	go/math/asin.go \
 	go/math/asinh.go \
@@ -652,15 +658,13 @@
 	go/math/cbrt.go \
 	go/math/const.go \
 	go/math/copysign.go \
+	go/math/dim.go \
 	go/math/erf.go \
 	go/math/exp.go \
 	go/math/exp_port.go \
 	go/math/exp2.go \
 	go/math/expm1.go \
-	go/math/fabs.go \
-	go/math/fdim.go \
 	go/math/floor.go \
-	go/math/fmod.go \
 	go/math/frexp.go \
 	go/math/gamma.go \
 	go/math/hypot.go \
@@ -674,6 +678,7 @@
 	go/math/log1p.go \
 	go/math/log10.go \
 	go/math/logb.go \
+	go/math/mod.go \
 	go/math/modf.go \
 	go/math/nextafter.go \
 	go/math/pow.go \
@@ -777,11 +782,6 @@
 	go/net/unixsock.go \
 	go/net/unixsock_posix.go
 
-go_netchan_files = \
-	go/netchan/common.go \
-	go/netchan/export.go \
-	go/netchan/import.go
-
 if LIBGO_IS_SOLARIS
 if LIBGO_IS_386
 go_os_dir_file = go/os/dir_largefile.go
@@ -865,6 +865,7 @@
 	go/reflect/value.go
 
 go_regexp_files = \
+	go/regexp/exec.go \
 	go/regexp/regexp.go
 
 go_rpc_files = \
@@ -915,6 +916,7 @@
 
 go_strings_files = \
 	go/strings/reader.go \
+	go/strings/replace.go \
 	go/strings/strings.go
 
 go_sync_files = \
@@ -953,21 +955,19 @@
 
 go_testing_files = \
 	go/testing/benchmark.go \
+	go/testing/example.go \
 	go/testing/testing.go
 
 go_time_files = \
 	go/time/format.go \
 	go/time/sleep.go \
 	go/time/sys.go \
-	go/time/sys_posix.go \
+	go/time/sys_unix.go \
 	go/time/tick.go \
 	go/time/time.go \
 	go/time/zoneinfo_posix.go \
 	go/time/zoneinfo_unix.go
 
-go_try_files = \
-	go/try/try.go
-
 go_unicode_files = \
 	go/unicode/casetables.go \
 	go/unicode/digit.go \
@@ -987,6 +987,8 @@
 
 go_websocket_files = \
 	go/websocket/client.go \
+	go/websocket/hixie.go \
+	go/websocket/hybi.go \
 	go/websocket/server.go \
 	go/websocket/websocket.go
 
@@ -1041,16 +1043,13 @@
 go_container_ring_files = \
 	go/container/ring/ring.go
 
-go_container_vector_files = \
-	go/container/vector/defs.go \
-	go/container/vector/intvector.go \
-	go/container/vector/stringvector.go \
-	go/container/vector/vector.go
-
 go_crypto_aes_files = \
 	go/crypto/aes/block.go \
 	go/crypto/aes/cipher.go \
 	go/crypto/aes/const.go
+go_crypto_bcrypt_files = \
+	go/crypto/bcrypt/base64.go \
+	go/crypto/bcrypt/bcrypt.go
 go_crypto_blowfish_files = \
 	go/crypto/blowfish/block.go \
 	go/crypto/blowfish/const.go \
@@ -1123,11 +1122,13 @@
 	go/crypto/tls/handshake_server.go \
 	go/crypto/tls/key_agreement.go \
 	go/crypto/tls/prf.go \
+	go/crypto/tls/root_unix.go \
 	go/crypto/tls/tls.go
 go_crypto_twofish_files = \
 	go/crypto/twofish/twofish.go
 go_crypto_x509_files = \
 	go/crypto/x509/cert_pool.go \
+	go/crypto/x509/pkcs1.go \
 	go/crypto/x509/verify.go \
 	go/crypto/x509/x509.go
 go_crypto_xtea_files = \
@@ -1187,7 +1188,8 @@
 go_encoding_base64_files = \
 	go/encoding/base64/base64.go
 go_encoding_binary_files = \
-	go/encoding/binary/binary.go
+	go/encoding/binary/binary.go \
+	go/encoding/binary/varint.go
 go_encoding_git85_files = \
 	go/encoding/git85/git.go
 go_encoding_hex_files = \
@@ -1195,33 +1197,66 @@
 go_encoding_pem_files = \
 	go/encoding/pem/pem.go
 
+go_exp_ebnf_files = \
+	go/exp/ebnf/ebnf.go \
+	go/exp/ebnf/parser.go
 go_exp_gui_files = \
 	go/exp/gui/gui.go
 go_exp_norm_files = \
 	go/exp/norm/composition.go \
 	go/exp/norm/forminfo.go \
+	go/exp/norm/input.go \
 	go/exp/norm/normalize.go \
+	go/exp/norm/readwriter.go \
 	go/exp/norm/tables.go \
 	go/exp/norm/trie.go
-go_exp_regexp_files = \
-	go/exp/regexp/exec.go \
-	go/exp/regexp/regexp.go
+go_exp_spdy_files = \
+	go/exp/spdy/read.go \
+	go/exp/spdy/types.go \
+	go/exp/spdy/write.go
+go_exp_sql_files = \
+	go/exp/sql/convert.go \
+	go/exp/sql/sql.go
+go_exp_ssh_files = \
+	go/exp/ssh/channel.go \
+	go/exp/ssh/common.go \
+	go/exp/ssh/doc.go \
+	go/exp/ssh/messages.go \
+	go/exp/ssh/server.go \
+	go/exp/ssh/server_shell.go \
+	go/exp/ssh/transport.go
+go_exp_terminal_files = \
+	go/exp/terminal/shell.go \
+	go/exp/terminal/terminal.go
+go_exp_types_files = \
+	go/exp/types/check.go \
+	go/exp/types/const.go \
+	go/exp/types/exportdata.go \
+	go/exp/types/gcimporter.go \
+	go/exp/types/types.go \
+	go/exp/types/universe.go
 
 go_exp_gui_x11_files = \
 	go/exp/gui/x11/auth.go \
 	go/exp/gui/x11/conn.go
 
+go_exp_sql_driver_files = \
+	go/exp/sql/driver/driver.go \
+	go/exp/sql/driver/types.go
+
 go_exp_template_html_files = \
+	go/exp/template/html/attr.go \
+	go/exp/template/html/clone.go \
+	go/exp/template/html/content.go \
 	go/exp/template/html/context.go \
-	go/exp/template/html/escape.go
-
-go_exp_regexp_syntax_files = \
-	go/exp/regexp/syntax/compile.go \
-	go/exp/regexp/syntax/parse.go \
-	go/exp/regexp/syntax/perl_groups.go \
-	go/exp/regexp/syntax/prog.go \
-	go/exp/regexp/syntax/regexp.go \
-	go/exp/regexp/syntax/simplify.go
+	go/exp/template/html/css.go \
+	go/exp/template/html/doc.go \
+	go/exp/template/html/error.go \
+	go/exp/template/html/escape.go \
+	go/exp/template/html/html.go \
+	go/exp/template/html/js.go \
+	go/exp/template/html/transition.go \
+	go/exp/template/html/url.go
 
 go_go_ast_files = \
 	go/go/ast/ast.go \
@@ -1237,7 +1272,8 @@
 	syslist.go
 go_go_doc_files = \
 	go/go/doc/comment.go \
-	go/go/doc/doc.go
+	go/go/doc/doc.go \
+	go/go/doc/example.go
 go_go_parser_files = \
 	go/go/parser/interface.go \
 	go/go/parser/parser.go
@@ -1249,19 +1285,8 @@
 	go/go/scanner/scanner.go
 go_go_token_files = \
 	go/go/token/position.go \
+	go/go/token/serialize.go \
 	go/go/token/token.go
-go_go_typechecker_files = \
-	go/go/typechecker/scope.go \
-	go/go/typechecker/type.go \
-	go/go/typechecker/typechecker.go \
-	go/go/typechecker/universe.go
-go_go_types_files = \
-	go/go/types/check.go \
-	go/go/types/const.go \
-	go/go/types/exportdata.go \
-	go/go/types/gcimporter.go \
-	go/go/types/types.go \
-	go/go/types/universe.go
 
 go_hash_adler32_files = \
 	go/hash/adler32/adler32.go
@@ -1284,14 +1309,13 @@
 	go/http/httptest/server.go
 go_http_pprof_files = \
 	go/http/pprof/pprof.go
-go_http_spdy_files = \
-	go/http/spdy/read.go \
-	go/http/spdy/types.go \
-	go/http/spdy/write.go
 
 go_image_bmp_files = \
 	go/image/bmp/reader.go
 
+go_image_color_files = \
+	go/image/color/color.go
+
 go_image_draw_files = \
 	go/image/draw/draw.go
 
@@ -1311,6 +1335,7 @@
 
 go_image_tiff_files = \
 	go/image/tiff/buffer.go \
+	go/image/tiff/compress.go \
 	go/image/tiff/consts.go \
 	go/image/tiff/reader.go
 
@@ -1340,6 +1365,12 @@
 	go/net/textproto/textproto.go \
 	go/net/textproto/writer.go
 
+go_old_netchan_files = \
+	go/old/netchan/common.go \
+	go/old/netchan/export.go \
+	go/old/netchan/import.go
+go_old_regexp_files = \
+	go/old/regexp/regexp.go
 go_old_template_files = \
 	go/old/template/doc.go \
 	go/old/template/execute.go \
@@ -1361,6 +1392,14 @@
 	go/path/filepath/path.go \
 	go/path/filepath/path_unix.go
 
+go_regexp_syntax_files = \
+	go/regexp/syntax/compile.go \
+	go/regexp/syntax/parse.go \
+	go/regexp/syntax/perl_groups.go \
+	go/regexp/syntax/prog.go \
+	go/regexp/syntax/regexp.go \
+	go/regexp/syntax/simplify.go
+
 go_rpc_jsonrpc_files = \
 	go/rpc/jsonrpc/client.go \
 	go/rpc/jsonrpc/server.go
@@ -1559,7 +1598,6 @@
 	cmath/cmath.lo \
 	crypto/crypto.lo \
 	csv/csv.lo \
-	ebnf/ebnf.lo \
 	exec/exec.lo \
 	expvar/expvar.lo \
 	flag/flag.lo \
@@ -1576,7 +1614,6 @@
 	mail/mail.lo \
 	mime/mime.lo \
 	net/net.lo \
-	netchan/netchan.lo \
 	os/os.lo \
 	patch/patch.lo \
 	path/path.lo \
@@ -1596,7 +1633,6 @@
 	tabwriter/tabwriter.lo \
 	template/template.lo \
 	time/time.lo \
-	try/try.lo \
 	unicode/unicode.lo \
 	url/url.lo \
 	utf16/utf16.lo \
@@ -1613,8 +1649,8 @@
 	container/heap.lo \
 	container/list.lo \
 	container/ring.lo \
-	container/vector.lo \
 	crypto/aes.lo \
+	crypto/bcrypt.lo \
 	crypto/blowfish.lo \
 	crypto/cast5.lo \
 	crypto/cipher.lo \
@@ -1657,11 +1693,16 @@
 	encoding/git85.lo \
 	encoding/hex.lo \
 	encoding/pem.lo \
+	exp/ebnf.lo \
 	exp/gui.lo \
 	exp/norm.lo \
-	exp/regexp.lo \
+	exp/spdy.lo \
+	exp/sql.lo \
+	exp/ssh.lo \
+	exp/terminal.lo \
+	exp/types.lo \
 	exp/gui/x11.lo \
-	exp/regexp/syntax.lo \
+	exp/sql/driver.lo \
 	exp/template/html.lo \
 	go/ast.lo \
 	go/build.lo \
@@ -1670,8 +1711,6 @@
 	go/printer.lo \
 	go/scanner.lo \
 	go/token.lo \
-	go/typechecker.lo \
-	go/types.lo \
 	hash/adler32.lo \
 	hash/crc32.lo \
 	hash/crc64.lo \
@@ -1680,8 +1719,8 @@
 	http/fcgi.lo \
 	http/httptest.lo \
 	http/pprof.lo \
-	http/spdy.lo \
 	image/bmp.lo \
+	image/color.lo \
 	image/draw.lo \
 	image/gif.lo \
 	image/jpeg.lo \
@@ -1693,11 +1732,14 @@
 	mime/multipart.lo \
 	net/dict.lo \
 	net/textproto.lo \
+	old/netchan.lo \
+	old/regexp.lo \
 	old/template.lo \
 	$(os_lib_inotify_lo) \
 	os/user.lo \
 	os/signal.lo \
 	path/filepath.lo \
+	regexp/syntax.lo \
 	rpc/jsonrpc.lo \
 	runtime/debug.lo \
 	runtime/pprof.lo \
@@ -1853,13 +1895,6 @@
 	@$(CHECK)
 .PHONY: csv/check
 
-ebnf/ebnf.lo: $(go_ebnf_files) container/vector.gox go/scanner.gox \
-		go/token.gox os.gox strconv.gox unicode.gox utf8.gox
-	$(BUILDPACKAGE)
-ebnf/check: $(CHECK_DEPS)
-	@$(CHECK)
-.PHONY: ebnf/check
-
 exec/exec.lo: $(go_exec_files) bytes.gox io.gox os.gox strconv.gox \
 		strings.gox syscall.gox
 	$(BUILDPACKAGE)
@@ -1881,7 +1916,7 @@
 .PHONY: flag/check
 
 fmt/fmt.lo: $(go_fmt_files) bytes.gox io.gox math.gox os.gox reflect.gox \
-		strconv.gox strings.gox unicode.gox utf8.gox
+		strconv.gox strings.gox sync.gox unicode.gox utf8.gox
 	$(BUILDPACKAGE)
 fmt/check: $(CHECK_DEPS)
 	@$(CHECK)
@@ -1901,8 +1936,8 @@
 	@$(CHECK)
 .PHONY: hash/check
 
-html/html.lo: $(go_html_files) bytes.gox io.gox os.gox strconv.gox strings.gox \
-		utf8.gox
+html/html.lo: $(go_html_files) bufio.gox bytes.gox fmt.gox io.gox os.gox \
+		strconv.gox strings.gox utf8.gox
 	$(BUILDPACKAGE)
 html/check: $(CHECK_DEPS)
 	@$(CHECK)
@@ -1919,7 +1954,8 @@
 	@$(CHECK)
 .PHONY: http/check
 
-image/image.lo: $(go_image_files) bufio.gox io.gox os.gox strconv.gox
+image/image.lo: $(go_image_files) bufio.gox image/color.gox io.gox os.gox \
+		strconv.gox
 	$(BUILDPACKAGE)
 image/check: $(CHECK_DEPS)
 	@$(CHECK)
@@ -1975,13 +2011,6 @@
 	@$(CHECK)
 .PHONY: net/check
 
-netchan/netchan.lo: $(go_netchan_files) gob.gox io.gox log.gox net.gox os.gox \
-		reflect.gox strconv.gox sync.gox time.gox
-	$(BUILDPACKAGE)
-netchan/check: $(CHECK_DEPS)
-	@$(CHECK)
-.PHONY: netchan/check
-
 os/os.lo: $(go_os_files) runtime.gox sync.gox syscall.gox
 	$(BUILDPACKAGE)
 os/check: $(CHECK_DEPS)
@@ -2019,8 +2048,8 @@
 	@$(CHECK)
 .PHONY: reflect/check
 
-regexp/regexp.lo: $(go_regexp_files) bytes.gox io.gox os.gox strings.gox \
-		utf8.gox
+regexp/regexp.lo: $(go_regexp_files) bytes.gox io.gox os.gox \
+		regexp/syntax.gox strconv.gox strings.gox sync.gox utf8.gox
 	$(BUILDPACKAGE)
 regexp/check: $(CHECK_DEPS)
 	@$(CHECK)
@@ -2067,7 +2096,7 @@
 	@$(CHECK)
 .PHONY: strconv/check
 
-strings/strings.lo: $(go_strings_files) os.gox unicode.gox utf8.gox
+strings/strings.lo: $(go_strings_files) io.gox os.gox unicode.gox utf8.gox
 	$(BUILDPACKAGE)
 strings/check: $(CHECK_DEPS)
 	@$(CHECK)
@@ -2102,8 +2131,9 @@
 	@$(CHECK)
 .PHONY: template/check
 
-testing/testing.lo: $(go_testing_files) flag.gox fmt.gox os.gox regexp.gox \
-		runtime.gox runtime/pprof.gox strings.gox strconv.gox time.gox
+testing/testing.lo: $(go_testing_files) bytes.gox flag.gox fmt.gox io.gox \
+		os.gox regexp.gox runtime.gox runtime/pprof.gox strings.gox \
+		strconv.gox time.gox
 	$(BUILDPACKAGE)
 testing/check: $(CHECK_DEPS)
 	@$(CHECK)
@@ -2116,12 +2146,6 @@
 	@$(CHECK)
 .PHONY: time/check
 
-try/try.lo: $(go_try_files) fmt.gox io.gox os.gox reflect.gox unicode.gox
-	$(BUILDPACKAGE)
-try/check: $(CHECK_DEPS)
-	@$(CHECK)
-.PHONY: try/check
-
 unicode/unicode.lo: $(go_unicode_files)
 	$(BUILDPACKAGE)
 unicode/check: $(CHECK_DEPS)
@@ -2147,8 +2171,10 @@
 .PHONY: utf8/check
 
 websocket/websocket.lo: $(go_websocket_files) bufio.gox bytes.gox \
-		crypto/md5.gox crypto/tls.gox encoding/binary.gox fmt.gox \
-		http.gox io.gox net.gox os.gox rand.gox strings.gox url.gox
+		crypto/md5.gox crypto/rand.gox crypto/sha1.gox crypto/tls.gox \
+		encoding/base64.gox encoding/binary.gox fmt.gox http.gox \
+		io.gox io/ioutil.gox json.gox net.gox os.gox rand.gox \
+		strings.gox strconv.gox sync.gox url.gox
 	$(BUILDPACKAGE)
 websocket/check: $(CHECK_DEPS)
 	@$(CHECK)
@@ -2237,13 +2263,6 @@
 	@$(CHECK)
 .PHONY: container/ring/check
 
-container/vector.lo: $(go_container_vector_files)
-	$(BUILDPACKAGE)
-container/vector/check: $(CHECK_DEPS)
-	@$(MKDIR_P) container/vector
-	@$(CHECK)
-.PHONY: container/vector/check
-
 crypto/aes.lo: $(go_crypto_aes_files) os.gox strconv.gox
 	$(BUILDPACKAGE)
 crypto/aes/check: $(CHECK_DEPS)
@@ -2251,6 +2270,15 @@
 	@$(CHECK)
 .PHONY: crypto/aes/check
 
+crypto/bcrypt.lo: $(go_crypto_bcrypt_files) crypto/blowfish.gox \
+		crypto/rand.gox crypto/subtle.gox encoding/base64.gox \
+		fmt.gox io.gox os.gox strconv.gox
+	$(BUILDPACKAGE)
+crypto/bcrypt/check: $(CHECK_DEPS)
+	@$(MKDIR_P) crypto/bcrypt
+	@$(CHECK)
+.PHONY: crypto/bcrypt/check
+
 crypto/blowfish.lo: $(go_crypto_blowfish_files) os.gox strconv.gox
 	$(BUILDPACKAGE)
 crypto/blowfish/check: $(CHECK_DEPS)
@@ -2403,12 +2431,12 @@
 .PHONY: crypto/subtle/check
 
 crypto/tls.lo: $(go_crypto_tls_files) big.gox bytes.gox crypto.gox \
-		crypto/aes.gox crypto/cipher.gox crypto/elliptic.gox \
-		crypto/hmac.gox crypto/md5.gox crypto/rand.gox crypto/rc4.gox \
-		crypto/rsa.gox crypto/sha1.gox crypto/subtle.gox \
-		crypto/x509.gox crypto/x509/pkix.gox encoding/pem.gox \
-		hash.gox io.gox io/ioutil.gox net.gox os.gox strconv.gox \
-		strings.gox sync.gox time.gox
+		crypto/aes.gox crypto/cipher.gox crypto/des.gox \
+		crypto/elliptic.gox crypto/hmac.gox crypto/md5.gox \
+		crypto/rand.gox crypto/rc4.gox crypto/rsa.gox crypto/sha1.gox \
+		crypto/subtle.gox crypto/x509.gox crypto/x509/pkix.gox \
+		encoding/pem.gox hash.gox io.gox io/ioutil.gox net.gox os.gox \
+		strconv.gox strings.gox sync.gox time.gox
 	$(BUILDPACKAGE)
 crypto/tls/check: $(CHECK_DEPS)
 	@$(MKDIR_P) crypto/tls
@@ -2583,6 +2611,14 @@
 	@$(CHECK)
 .PHONY: encoding/pem/check
 
+exp/ebnf.lo: $(go_exp_ebnf_files) go/scanner.gox go/token.gox os.gox \
+		strconv.gox unicode.gox utf8.gox
+	$(BUILDPACKAGE)
+exp/ebnf/check: $(CHECK_DEPS)
+	@$(MKDIR_P) exp/ebnf
+	@$(CHECK)
+.PHONY: exp/ebnf/check
+
 exp/gui.lo: $(go_exp_gui_files) image.gox image/draw.gox os.gox
 	$(BUILDPACKAGE)
 exp/gui/check: $(CHECK_DEPS)
@@ -2590,20 +2626,55 @@
 	@$(CHECK)
 .PHONY: exp/gui/check
 
-exp/norm.lo: $(go_exp_norm_files) utf8.gox
+exp/norm.lo: $(go_exp_norm_files) io.gox os.gox utf8.gox
 	$(BUILDPACKAGE)
 exp/norm/check: $(CHECK_DEPS)
 	@$(MKDIR_P) exp/norm
 	@$(CHECK)
 .PHONY: exp/norm/check
 
-exp/regexp.lo: $(go_exp_regexp_files) bytes.gox exp/regexp/syntax.gox io.gox \
-		os.gox strings.gox sync.gox utf8.gox
+exp/spdy.lo: $(go_exp_spdy_files) bytes.gox compress/zlib.gox \
+		encoding/binary.gox http.gox io.gox os.gox strings.gox
 	$(BUILDPACKAGE)
-exp/regexp/check: $(CHECK_DEPS)
-	@$(MKDIR_P) exp/regexp
+exp/spdy/check: $(CHECK_DEPS)
+	@$(MKDIR_P) exp/spdy
 	@$(CHECK)
-.PHONY: exp/regexp/check
+.PHONY: exp/spdy/check
+
+exp/sql.lo: $(go_exp_sql_files) exp/sql/driver.gox fmt.gox os.gox reflect.gox \
+		runtime.gox strconv.gox sync.gox
+	$(BUILDPACKAGE)
+exp/sql/check: $(CHECK_DEPS)
+	@$(MKDIR_P) exp/sql
+	@$(CHECK)
+.PHONY: exp/sql/check
+
+exp/ssh.lo: $(go_exp_ssh_files) big.gox bufio.gox bytes.gox crypto.gox \
+		crypto/aes.gox crypto/cipher.gox crypto/hmac.gox \
+		crypto/rand.gox crypto/rsa.gox crypto/sha1.gox \
+		crypto/subtle.gox crypto/x509.gox encoding/pem.gox hash.gox \
+		io.gox net.gox os.gox reflect.gox strconv.gox sync.gox
+	$(BUILDPACKAGE)
+exp/ssh/check: $(CHECK_DEPS)
+	@$(MKDIR_P) exp/ssh
+	@$(CHECK)
+.PHONY: exp/ssh/check
+
+exp/terminal.lo: $(go_exp_terminal_files) io.gox os.gox syscall.gox
+	$(BUILDPACKAGE)
+exp/terminal/check: $(CHECK_DEPS)
+	@$(MKDIR_P) exp/terminal
+	@$(CHECK)
+.PHONY: exp/terminal/check
+
+exp/types.lo: $(go_exp_types_files) big.gox bufio.gox fmt.gox go/ast.gox \
+		go/token.gox io.gox os.gox path/filepath.gox runtime.gox \
+		scanner.gox sort.gox strconv.gox strings.gox
+	$(BUILDPACKAGE)
+exp/types/check: $(CHECK_DEPS)
+	@$(MKDIR_P) exp/types
+	@$(CHECK)
+.PHONY: exp/types/check
 
 exp/gui/x11.lo: $(go_exp_gui_x11_files) bufio.gox exp/gui.gox image.gox \
 		image/draw.gox io.gox log.gox net.gox os.gox strconv.gox \
@@ -2614,15 +2685,17 @@
 	@$(CHECK)
 .PHONY: exp/gui/x11/check
 
-exp/regexp/syntax.lo: $(go_exp_regexp_syntax_files) bytes.gox os.gox sort.gox strconv.gox strings.gox unicode.gox utf8.gox
+exp/sql/driver.lo: $(go_exp_sql_driver_files) fmt.gox os.gox reflect.gox \
+		strconv.gox
 	$(BUILDPACKAGE)
-exp/regexp/syntax/check: $(CHECK_DEPS)
-	@$(MKDIR_P) exp/regexp/syntax
+exp/sql/driver/check: $(CHECK_DEPS)
+	@$(MKDIR_P) exp/sql/driver
 	@$(CHECK)
-.PHONY: exp/regexp/syntax/check
-
-exp/template/html.lo: $(go_exp_template_html_files) fmt.gox template.gox \
-		template/parse.gox
+.PHONY: exp/sql/driver/check
+
+exp/template/html.lo: $(go_exp_template_html_files) bytes.gox fmt.gox \
+		html.gox json.gox os.gox strings.gox template.gox \
+		template/parse.gox unicode.gox utf8.gox 
 	$(BUILDPACKAGE)
 exp/template/html/check: $(CHECK_DEPS)
 	@$(MKDIR_P) exp/template/html
@@ -2637,9 +2710,10 @@
 	@$(CHECK)
 .PHONY: go/ast/check
 
-go/build.lo: $(go_go_build_files) bytes.gox exec.gox fmt.gox go/parser.gox \
-		go/token.gox log.gox os.gox path/filepath.gox regexp.gox \
-		runtime.gox strconv.gox strings.gox runtime.gox
+go/build.lo: $(go_go_build_files) bytes.gox exec.gox fmt.gox go/ast.gox \
+		go/doc.gox go/parser.gox go/token.gox io/ioutil.gox log.gox \
+		os.gox path.gox path/filepath.gox regexp.gox runtime.gox \
+		sort.gox strconv.gox strings.gox runtime.gox unicode.gox
 	$(BUILDPACKAGE)
 go/build/check: $(CHECK_DEPS)
 	@$(MKDIR_P) go/build
@@ -2656,7 +2730,7 @@
 	$(STAMP) $@
 
 go/doc.lo: $(go_go_doc_files) go/ast.gox go/token.gox io.gox regexp.gox \
-		sort.gox strings.gox template.gox
+		sort.gox strings.gox template.gox unicode.gox utf8.gox
 	$(BUILDPACKAGE)
 go/doc/check: $(CHECK_DEPS)
 	@$(MKDIR_P) go/doc
@@ -2674,7 +2748,7 @@
 
 go/printer.lo: $(go_go_printer_files) bytes.gox fmt.gox go/ast.gox \
 		go/token.gox io.gox os.gox path/filepath.gox reflect.gox \
-		runtime.gox strings.gox tabwriter.gox
+		strings.gox tabwriter.gox
 	$(BUILDPACKAGE)
 go/printer/check: $(CHECK_DEPS)
 	@$(MKDIR_P) go/printer
@@ -2690,30 +2764,14 @@
 	@$(CHECK)
 .PHONY: go/scanner/check
 
-go/token.lo: $(go_go_token_files) fmt.gox strconv.gox
+go/token.lo: $(go_go_token_files) fmt.gox gob.gox io.gox os.gox sort.gox \
+		strconv.gox sync.gox
 	$(BUILDPACKAGE)
 go/token/check: $(CHECK_DEPS)
 	@$(MKDIR_P) go/token
 	@$(CHECK)
 .PHONY: go/token/check
 
-go/typechecker.lo: $(go_go_typechecker_files) fmt.gox go/ast.gox go/token.gox \
-		go/scanner.gox os.gox
-	$(BUILDPACKAGE)
-go/typechecker/check: $(CHECK_DEPS)
-	@$(MKDIR_P) go/typechecker
-	@$(CHECK)
-.PHONY: go/typechecker/check
-
-go/types.lo: $(go_go_types_files) big.gox bufio.gox fmt.gox go/ast.gox \
-		go/token.gox io.gox os.gox path/filepath.gox runtime.gox \
-		scanner.gox sort.gox strconv.gox strings.gox
-	$(BUILDPACKAGE)
-go/types/check: $(CHECK_DEPS)
-	@$(MKDIR_P) go/types
-	@$(CHECK)
-.PHONY: go/types/check
-
 hash/adler32.lo: $(go_hash_adler32_files) hash.gox os.gox
 	$(BUILDPACKAGE)
 hash/adler32/check: $(CHECK_DEPS)
@@ -2777,23 +2835,21 @@
 	@$(CHECK)
 .PHONY: http/pprof/check
 
-http/spdy.lo: $(go_http_spdy_files) bytes.gox compress/zlib.gox \
-		encoding/binary.gox http.gox io.gox os.gox strconv.gox \
-		strings.gox sync.gox
-	$(BUILDPACKAGE)
-http/spdy/check: $(CHECK_DEPS)
-	@$(MKDIR_P) http/spdy
-	@$(CHECK)
-.PHONY: http/spdy/check
-
-image/bmp.lo: $(go_image_bmp_files) image.gox io.gox os.gox
+image/bmp.lo: $(go_image_bmp_files) image.gox image/color.gox io.gox os.gox
 	$(BUILDPACKAGE)
 image/bmp/check: $(CHECK_DEPS)
 	@$(MKDIR_P) image/bmp
 	@$(CHECK)
 .PHONY: image/bmp/check
 
-image/draw.lo: $(go_image_draw_files) image.gox image/ycbcr.gox
+image/color.lo: $(go_image_color_files)
+	$(BUILDPACKAGE)
+image/color/check: $(CHECK_DEPS)
+	@$(MKDIR_P) image/color
+	@$(CHECK)
+.PHONY: image/color/check
+
+image/draw.lo: $(go_image_draw_files) image.gox image/color.gox image/ycbcr.gox
 	$(BUILDPACKAGE)
 image/draw/check: $(CHECK_DEPS)
 	@$(MKDIR_P) image/draw
@@ -2801,46 +2857,48 @@
 .PHONY: image/draw/check
 
 image/gif.lo: $(go_image_gif_files) bufio.gox compress/lzw.gox fmt.gox \
-		image.gox io.gox os.gox
+		image.gox image/color.gox io.gox os.gox
 	$(BUILDPACKAGE)
 image/gif/check: $(CHECK_DEPS)
 	@$(MKDIR_P) image/gif
 	@$(CHECK)
 .PHONY: image/gif/check
 
-image/jpeg.lo: $(go_image_jpeg_files) bufio.gox image.gox image/ycbcr.gox \
-		io.gox os.gox
+image/jpeg.lo: $(go_image_jpeg_files) bufio.gox image.gox image/color.gox \
+		image/ycbcr.gox io.gox os.gox
 	$(BUILDPACKAGE)
 image/jpeg/check: $(CHECK_DEPS)
 	@$(MKDIR_P) image/jpeg
 	@$(CHECK)
 .PHONY: image/jpeg/check
 
-image/png.lo: $(go_image_png_files) bufio.gox compress/zlib.gox fmt.gox \
-		hash.gox hash/crc32.gox image.gox io.gox os.gox strconv.gox
+image/png.lo: $(go_image_png_files) bufio.gox compress/zlib.gox \
+		encoding/binary.gox fmt.gox hash.gox hash/crc32.gox image.gox \
+		image/color.gox io.gox os.gox strconv.gox
 	$(BUILDPACKAGE)
 image/png/check: $(CHECK_DEPS)
 	@$(MKDIR_P) image/png
 	@$(CHECK)
 .PHONY: image/png/check
 
-image/tiff.lo: $(go_image_tiff_files) compress/lzw.gox compress/zlib.gox \
-		encoding/binary.gox image.gox io.gox io/ioutil.gox os.gox
+image/tiff.lo: $(go_image_tiff_files) bufio.gox compress/lzw.gox \
+		compress/zlib.gox encoding/binary.gox image.gox \
+		image/color.gox io.gox io/ioutil.gox os.gox
 	$(BUILDPACKAGE)
 image/tiff/check: $(CHECK_DEPS)
 	@$(MKDIR_P) image/tiff
 	@$(CHECK)
 .PHONY: image/tiff/check
 
-image/ycbcr.lo: $(go_image_ycbcr_files) image.gox
+image/ycbcr.lo: $(go_image_ycbcr_files) image.gox image/color.gox
 	$(BUILDPACKAGE)
 image/ycbcr/check: $(CHECK_DEPS)
 	@$(MKDIR_P) image/ycbcr
 	@$(CHECK)
 .PHONY: image/ycbcr/check
 
-index/suffixarray.lo: $(go_index_suffixarray_files) bytes.gox regexp.gox \
-		sort.gox
+index/suffixarray.lo: $(go_index_suffixarray_files) bytes.gox \
+		encoding/binary.gox io.gox os.gox regexp.gox sort.gox
 	$(BUILDPACKAGE)
 index/suffixarray/check: $(CHECK_DEPS)
 	@$(MKDIR_P) index/suffixarray
@@ -2869,13 +2927,30 @@
 	$(BUILDPACKAGE)
 
 net/textproto.lo: $(go_net_textproto_files) bufio.gox bytes.gox fmt.gox \
-		io.gox io/ioutil.gox net.gox os.gox strconv.gox sync.gox
+		io.gox io/ioutil.gox net.gox os.gox strings.gox strconv.gox \
+		sync.gox
 	$(BUILDPACKAGE)
 net/textproto/check: $(CHECK_DEPS)
 	@$(MKDIR_P) net/textproto
 	@$(CHECK)
 .PHONY: net/textproto/check
 
+old/netchan.lo: $(go_old_netchan_files) gob.gox io.gox log.gox net.gox os.gox \
+		reflect.gox strconv.gox sync.gox time.gox
+	$(BUILDPACKAGE)
+old/netchan/check: $(CHECK_DEPS)
+	@$(MKDIR_P) old/netchan
+	@$(CHECK)
+.PHONY: old/netchan/check
+
+old/regexp.lo: $(go_old_regexp_files) bytes.gox io.gox os.gox strings.gox \
+		utf8.gox
+	$(BUILDPACKAGE)
+old/regexp/check: $(CHECK_DEPS)
+	@$(MKDIR_P) old/regexp
+	@$(CHECK)
+.PHONY: old/regexp/check
+
 old/template.lo: $(go_old_template_files) bytes.gox fmt.gox io.gox \
 		io/ioutil.gox os.gox reflect.gox strconv.gox strings.gox \
 		unicode.gox utf8.gox
@@ -2915,6 +2990,14 @@
 	@$(CHECK)
 .PHONY: path/filepath/check
 
+regexp/syntax.lo: $(go_regexp_syntax_files) bytes.gox os.gox sort.gox \
+		strconv.gox strings.gox unicode.gox utf8.gox
+	$(BUILDPACKAGE)
+regexp/syntax/check: $(CHECK_DEPS)
+	@$(MKDIR_P) regexp/syntax
+	@$(CHECK)
+.PHONY: regexp/syntax/check
+
 rpc/jsonrpc.lo: $(go_rpc_jsonrpc_files) fmt.gox io.gox json.gox net.gox \
 		os.gox rpc.gox sync.gox
 	$(BUILDPACKAGE)
@@ -3005,8 +3088,6 @@
 	$(BUILDGOX)
 csv.gox: csv/csv.lo
 	$(BUILDGOX)
-ebnf.gox: ebnf/ebnf.lo
-	$(BUILDGOX)
 exec.gox: exec/exec.lo
 	$(BUILDGOX)
 expvar.gox: expvar/expvar.lo
@@ -3039,8 +3120,6 @@
 	$(BUILDGOX)
 net.gox: net/net.lo
 	$(BUILDGOX)
-netchan.gox: netchan/netchan.lo
-	$(BUILDGOX)
 os.gox: os/os.lo
 	$(BUILDGOX)
 patch.gox: patch/patch.lo
@@ -3081,8 +3160,6 @@
 	$(BUILDGOX)
 time.gox: time/time.lo
 	$(BUILDGOX)
-try.gox: try/try.lo
-	$(BUILDGOX)
 unicode.gox: unicode/unicode.lo
 	$(BUILDGOX)
 url.gox: url/url.lo
@@ -3118,10 +3195,10 @@
 	$(BUILDGOX)
 container/ring.gox: container/ring.lo
 	$(BUILDGOX)
-container/vector.gox: container/vector.lo
+
+crypto/aes.gox: crypto/aes.lo
 	$(BUILDGOX)
-
-crypto/aes.gox: crypto/aes.lo
+crypto/bcrypt.gox: crypto/bcrypt.lo
 	$(BUILDGOX)
 crypto/blowfish.gox: crypto/blowfish.lo
 	$(BUILDGOX)
@@ -3212,17 +3289,27 @@
 encoding/pem.gox: encoding/pem.lo
 	$(BUILDGOX)
 
+exp/ebnf.gox: exp/ebnf.lo
+	$(BUILDGOX)
 exp/gui.gox: exp/gui.lo
 	$(BUILDGOX)
 exp/norm.gox: exp/norm.lo
 	$(BUILDGOX)
-exp/regexp.gox: exp/regexp.lo
+exp/spdy.gox: exp/spdy.lo
+	$(BUILDGOX)
+exp/sql.gox: exp/sql.lo
+	$(BUILDGOX)
+exp/ssh.gox: exp/ssh.lo
+	$(BUILDGOX)
+exp/terminal.gox: exp/terminal.lo
+	$(BUILDGOX)
+exp/types.gox: exp/types.lo
 	$(BUILDGOX)
 
 exp/gui/x11.gox: exp/gui/x11.lo
 	$(BUILDGOX)
 
-exp/regexp/syntax.gox: exp/regexp/syntax.lo
+exp/sql/driver.gox: exp/sql/driver.lo
 	$(BUILDGOX)
 
 exp/template/html.gox: exp/template/html.lo
@@ -3242,10 +3329,6 @@
 	$(BUILDGOX)
 go/token.gox: go/token.lo
 	$(BUILDGOX)
-go/typechecker.gox: go/typechecker.lo
-	$(BUILDGOX)
-go/types.gox: go/types.lo
-	$(BUILDGOX)
 
 hash/adler32.gox: hash/adler32.lo
 	$(BUILDGOX)
@@ -3264,10 +3347,10 @@
 	$(BUILDGOX)
 http/pprof.gox: http/pprof.lo
 	$(BUILDGOX)
-http/spdy.gox: http/spdy.lo
+
+image/bmp.gox: image/bmp.lo
 	$(BUILDGOX)
-
-image/bmp.gox: image/bmp.lo
+image/color.gox: image/color.lo
 	$(BUILDGOX)
 image/draw.gox: image/draw.lo
 	$(BUILDGOX)
@@ -3296,6 +3379,10 @@
 net/textproto.gox: net/textproto.lo
 	$(BUILDGOX)
 
+old/netchan.gox: old/netchan.lo
+	$(BUILDGOX)
+old/regexp.gox: old/regexp.lo
+	$(BUILDGOX)
 old/template.gox: old/template.lo
 	$(BUILDGOX)
 
@@ -3309,6 +3396,9 @@
 path/filepath.gox: path/filepath.lo
 	$(BUILDGOX)
 
+regexp/syntax.gox: regexp/syntax.lo
+	$(BUILDGOX)
+
 rpc/jsonrpc.gox: rpc/jsonrpc.lo
 	$(BUILDGOX)
 
@@ -3344,7 +3434,6 @@
 	bytes/check \
 	cmath/check \
 	csv/check \
-	ebnf/check \
 	exec/check \
 	expvar/check \
 	flag/check \
@@ -3360,7 +3449,6 @@
 	mail/check \
 	mime/check \
 	net/check \
-	netchan/check \
 	os/check \
 	patch/check \
 	path/check \
@@ -3379,7 +3467,6 @@
 	tabwriter/check \
 	template/check \
 	time/check \
-	try/check \
 	unicode/check \
 	url/check \
 	utf16/check \
@@ -3396,8 +3483,8 @@
 	container/heap/check \
 	container/list/check \
 	container/ring/check \
-	container/vector/check \
 	crypto/aes/check \
+	crypto/bcrypt/check \
 	crypto/blowfish/check \
 	crypto/cast5/check \
 	crypto/cipher/check \
@@ -3437,9 +3524,12 @@
 	encoding/git85/check \
 	encoding/hex/check \
 	encoding/pem/check \
+	exp/ebnf/check \
 	exp/norm/check \
-	exp/regexp/check \
-	exp/regexp/syntax/check \
+	exp/spdy/check \
+	exp/sql/check \
+	exp/ssh/check \
+	exp/terminal/check \
 	exp/template/html/check \
 	go/ast/check \
 	$(go_build_check_omitted_since_it_calls_6g) \
@@ -3447,7 +3537,6 @@
 	go/printer/check \
 	go/scanner/check \
 	go/token/check \
-	go/typechecker/check \
 	$(go_types_check_omitted_since_it_calls_6g) \
 	hash/adler32/check \
 	hash/crc32/check \
@@ -3455,7 +3544,6 @@
 	hash/fnv/check \
 	http/cgi/check \
 	http/fcgi/check \
-	http/spdy/check \
 	image/draw/check \
 	image/jpeg/check \
 	image/png/check \
@@ -3465,11 +3553,14 @@
 	io/ioutil/check \
 	mime/multipart/check \
 	net/textproto/check \
+	old/netchan/check \
+	old/regexp/check \
 	old/template/check \
 	$(os_inotify_check) \
 	os/user/check \
 	os/signal/check \
 	path/filepath/check \
+	regexp/syntax/check \
 	rpc/jsonrpc/check \
 	sync/atomic/check \
 	template/parse/check \
diff -r c36211271569 libgo/go/syscall/exec_unix.go
--- a/libgo/go/syscall/exec_unix.go	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/go/syscall/exec_unix.go	Wed Oct 26 16:12:38 2011 -0700
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd linux openbsd
-
 // Fork, exec, wait, etc.
 
 package syscall
@@ -87,10 +85,10 @@
 // 2) Socket.  Does not block.  Use the ForkLock.
 // 3) Accept.  If using non-blocking mode, use the ForkLock.
 //             Otherwise, live with the race.
-// 4) Open.    Can block.  Use O_CLOEXEC if available (Linux).
+// 4) Open.    Can block.  Use O_CLOEXEC if available (GNU/Linux).
 //             Otherwise, live with the race.
 // 5) Dup.     Does not block.  Use the ForkLock.
-//             On Linux, could use fcntl F_DUPFD_CLOEXEC
+//             On GNU/Linux, could use fcntl F_DUPFD_CLOEXEC
 //             instead of the ForkLock, but only for dup(fd, -1).
 
 var ForkLock sync.RWMutex
@@ -254,8 +252,8 @@
 			continue
 		}
 		if fd[i] == int(i) {
-			// Dup2(i, i) won't clear close-on-exec flag on Linux,
-			// probably not elsewhere either.
+			// Dup2(i, i) won't clear close-on-exec flag on
+			// GNU/Linux, probably not elsewhere either.
 			_, err1 = raw_fcntl(fd[i], F_SETFD, 0)
 			if err1 != 0 {
 				goto childerror
diff -r c36211271569 libgo/go/syscall/libcall_linux.go
--- a/libgo/go/syscall/libcall_linux.go	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/go/syscall/libcall_linux.go	Wed Oct 26 16:12:38 2011 -0700
@@ -21,7 +21,7 @@
 }
 
 func Futimes(fd int, tv []Timeval) (errno int) {
-	// Believe it or not, this is the best we can do on Linux
+	// Believe it or not, this is the best we can do on GNU/Linux
 	// (and is what glibc does).
 	return Utimes("/proc/self/fd/"+itoa(fd), tv)
 }
diff -r c36211271569 libgo/go/syscall/libcall_posix.go
--- a/libgo/go/syscall/libcall_posix.go	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/go/syscall/libcall_posix.go	Wed Oct 26 16:12:38 2011 -0700
@@ -73,7 +73,7 @@
 		return nil, 0
 	}
 
-	// Sanity check group count.  Max is 1<<16 on Linux.
+	// Sanity check group count.  Max is 1<<16 on GNU/Linux.
 	if n < 0 || n > 1<<20 {
 		return nil, EINVAL
 	}
diff -r c36211271569 libgo/go/syscall/lsf_linux.go
--- a/libgo/go/syscall/lsf_linux.go	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/go/syscall/lsf_linux.go	Wed Oct 26 16:12:38 2011 -0700
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Linux socket filter
+// GNU/Linux socket filter
 
 package syscall
 
diff -r c36211271569 libgo/go/syscall/socket.go
--- a/libgo/go/syscall/socket.go	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/go/syscall/socket.go	Wed Oct 26 16:12:38 2011 -0700
@@ -296,14 +296,10 @@
 
 */
 
-/* FIXME: mksysinfo needs to support IPv6Mreq.
-
 func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (errno int) {
 	return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(mreq)), Socklen_t(unsafe.Sizeof(*mreq)))
 }
 
-*/
-
 func SetsockoptString(fd, level, opt int, s string) (errno int) {
 	return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(&[]byte(s)[0])), Socklen_t(len(s)))
 }
diff -r c36211271569 libgo/go/syscall/socket_irix.go
--- a/libgo/go/syscall/socket_irix.go	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/go/syscall/socket_irix.go	Wed Oct 26 16:12:38 2011 -0700
@@ -52,7 +52,7 @@
 	}
 
 	// Assume path ends at NUL.
-	// This is not technically the Linux semantics for
+	// This is not technically the GNU/Linux semantics for
 	// abstract Unix domain sockets--they are supposed
 	// to be uninterpreted fixed-size binary blobs--but
 	// everyone uses this convention.
diff -r c36211271569 libgo/go/syscall/socket_linux.go
--- a/libgo/go/syscall/socket_linux.go	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/go/syscall/socket_linux.go	Wed Oct 26 16:12:38 2011 -0700
@@ -1,4 +1,4 @@
-// socket_linux.go -- Socket handling specific to Linux.
+// socket_linux.go -- Socket handling specific to GNU/Linux.
 
 // Copyright 2010 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
@@ -98,7 +98,7 @@
 	}
 
 	// Assume path ends at NUL.
-	// This is not technically the Linux semantics for
+	// This is not technically the GNU/Linux semantics for
 	// abstract Unix domain sockets--they are supposed
 	// to be uninterpreted fixed-size binary blobs--but
 	// everyone uses this convention.
diff -r c36211271569 libgo/go/syscall/socket_solaris.go
--- a/libgo/go/syscall/socket_solaris.go	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/go/syscall/socket_solaris.go	Wed Oct 26 16:12:38 2011 -0700
@@ -53,7 +53,7 @@
 	}
 
 	// Assume path ends at NUL.
-	// This is not technically the Linux semantics for
+	// This is not technically the GNU/Linux semantics for
 	// abstract Unix domain sockets--they are supposed
 	// to be uninterpreted fixed-size binary blobs--but
 	// everyone uses this convention.
diff -r c36211271569 libgo/merge.sh
--- a/libgo/merge.sh	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/merge.sh	Wed Oct 26 16:12:38 2011 -0700
@@ -38,9 +38,9 @@
 hg clone -r ${old_rev} ${repository} ${OLDDIR}
 
 rm -rf ${NEWDIR}
-hg clone -u release ${repository} ${NEWDIR}
+hg clone -u weekly ${repository} ${NEWDIR}
 
-new_rev=`cd ${NEWDIR} && hg log -r release | sed 1q | sed -e 's/.*://'`
+new_rev=`cd ${NEWDIR} && hg log -r weekly | sed 1q | sed -e 's/.*://'`
 
 merge() {
   name=$1
diff -r c36211271569 libgo/mksysinfo.sh
--- a/libgo/mksysinfo.sh	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/mksysinfo.sh	Wed Oct 26 16:12:38 2011 -0700
@@ -463,7 +463,7 @@
       -e 's/msg_flags/Flags/' \
     >> ${OUT}
 
-# The ip_mreq struct
+# The ip_mreq struct.
 grep '^type _ip_mreq ' gen-sysinfo.go | \
     sed -e 's/_ip_mreq/IPMreq/' \
       -e 's/imr_multiaddr/Multiaddr/' \
@@ -476,6 +476,14 @@
   echo 'var SizeofIPMreq = int(unsafe.Sizeof(IPMreq{}))' >> ${OUT}
 fi
 
+# The ipv6_mreq struct.
+grep '^type _ipv6_mreq ' gen-sysinfo.go | \
+    sed -e 's/_ipv6_mreq/IPv6Mreq/' \
+      -e 's/ipv6mr_multiaddr/Multiaddr/' \
+      -e 's/ipv6mr_interface/Interface/' \
+      -e 's/_in6_addr/[16]byte/' \
+    >> ${OUT}
+
 # Try to guess the type to use for fd_set.
 fd_set=`grep '^type _fd_set ' gen-sysinfo.go || true`
 fds_bits_type="_C_long"
@@ -504,6 +512,10 @@
 grep '^const _TIOC' gen-sysinfo.go | \
     sed -e 's/^\(const \)_\(TIOC[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
 
+# The ioctl flags for terminal control
+grep '^const _TC[GS]ET' gen-sysinfo.go | \
+    sed -e 's/^\(const \)_\(TC[GS]ET[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+
 # ioctl constants.  Might fall back to 0 if TIOCNXCL is missing, too, but
 # needs handling in syscalls.exec.go.
 if ! grep '^const _TIOCSCTTY ' gen-sysinfo.go >/dev/null 2>&1; then
@@ -619,4 +631,33 @@
   echo 'var SizeofRtAttr = int(unsafe.Sizeof(RtAttr{}))' >> ${OUT}
 fi
 
+# The termios struct.
+grep '^type _termios ' gen-sysinfo.go | \
+    sed -e 's/_termios/Termios/' \
+      -e 's/c_iflag/Iflag/' \
+      -e 's/c_oflag/Oflag/' \
+      -e 's/c_cflag/Cflag/' \
+      -e 's/c_lflag/Lflag/' \
+      -e 's/c_line/Line/' \
+      -e 's/c_cc/Cc/' \
+      -e 's/c_ispeed/Ispeed/' \
+      -e 's/c_ospeed/Ospeed/' \
+    >> ${OUT}
+
+# The termios constants.  The ones starting with 'E' were picked up above.
+for n in IGNBRK BRKINT IGNPAR PARMRK INPCK ISTRIP INLCR IGNCR ICRNL IUCLC \
+    IXON IXANY IXOFF IMAXBEL IUTF8 OPOST OLCUC ONLCR OCRNL ONOCR ONLRET \
+    OFILL OFDEL NLDLY NL0 NL1 CRDLY CR0 CR1 CR2 CR3 TABDLY BSDLY VTDLY \
+    FFDLY CBAUD CBAUDEX CSIZE CSTOPB CREAD PARENB PARODD HUPCL CLOCAL \
+    LOBLK CIBAUD CMSPAR CRTSCTS ISIG ICANON XCASE DEFECHK FLUSHO NOFLSH \
+    TOSTOP PENDIN IEXTEN VINTR VQUIT VERASE VKILL VEOF VMIN VEOL VTIME VEOL2 \
+    VSWTCH VSTART VSTOP VSUSP VDSUSP VLNEXT VWERASE VREPRINT VDISCARD VSTATUS \
+    TCSANOW TCSADRAIN, TCSAFLUSH TCIFLUSH TCOFLUSH TCIOFLUSH TCOOFF TCOON \
+    TCIOFF TCION B0 B50 B75 B110 B134 B150 B200 B300 B600 B1200 B1800 B2400 \
+    B4800 B9600 B19200 B38400 B57600 B115200 B230400; do
+
+    grep "^const _$n " gen-sysinfo.go | \
+	sed -e 's/^\(const \)_\([^=]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+done
+
 exit $?
diff -r c36211271569 libgo/runtime/arch.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgo/runtime/arch.h	Wed Oct 26 16:12:38 2011 -0700
@@ -0,0 +1,8 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// FIXME: Ideally CacheLineSize would be dependent on the host architecture.
+enum {
+	CacheLineSize = 64
+};
diff -r c36211271569 libgo/runtime/cpuprof.c
--- a/libgo/runtime/cpuprof.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/cpuprof.c	Wed Oct 26 16:12:38 2011 -0700
@@ -49,6 +49,7 @@
 // in the situation when normally the goroutine "owns" handoff.
 
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 #include "array.h"
diff -r c36211271569 libgo/runtime/go-append.c
--- a/libgo/runtime/go-append.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/go-append.c	Wed Oct 26 16:12:38 2011 -0700
@@ -8,6 +8,7 @@
 #include "go-panic.h"
 #include "array.h"
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 /* We should be OK if we don't split the stack here, since the only
diff -r c36211271569 libgo/runtime/go-byte-array-to-string.c
--- a/libgo/runtime/go-byte-array-to-string.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/go-byte-array-to-string.c	Wed Oct 26 16:12:38 2011 -0700
@@ -6,6 +6,7 @@
 
 #include "go-string.h"
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 struct __go_string
diff -r c36211271569 libgo/runtime/go-go.c
--- a/libgo/runtime/go-go.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/go-go.c	Wed Oct 26 16:12:38 2011 -0700
@@ -17,6 +17,7 @@
 #include "go-panic.h"
 #include "go-alloc.h"
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 #ifdef USING_SPLIT_STACK
@@ -561,7 +562,7 @@
 /* Start the other threads after garbage collection.  */
 
 void
-runtime_starttheworld (void)
+runtime_starttheworld (bool extra __attribute__ ((unused)))
 {
   int i;
   pthread_t me;
diff -r c36211271569 libgo/runtime/go-int-array-to-string.c
--- a/libgo/runtime/go-int-array-to-string.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/go-int-array-to-string.c	Wed Oct 26 16:12:38 2011 -0700
@@ -7,6 +7,7 @@
 #include "go-assert.h"
 #include "go-string.h"
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 struct __go_string
diff -r c36211271569 libgo/runtime/go-int-to-string.c
--- a/libgo/runtime/go-int-to-string.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/go-int-to-string.c	Wed Oct 26 16:12:38 2011 -0700
@@ -6,6 +6,7 @@
 
 #include "go-string.h"
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 struct __go_string
diff -r c36211271569 libgo/runtime/go-main.c
--- a/libgo/runtime/go-main.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/go-main.c	Wed Oct 26 16:12:38 2011 -0700
@@ -19,6 +19,7 @@
 #include "go-string.h"
 
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 #undef int
diff -r c36211271569 libgo/runtime/go-make-slice.c
--- a/libgo/runtime/go-make-slice.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/go-make-slice.c	Wed Oct 26 16:12:38 2011 -0700
@@ -12,6 +12,7 @@
 #include "go-type.h"
 #include "array.h"
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 struct __go_open_array
diff -r c36211271569 libgo/runtime/go-new.c
--- a/libgo/runtime/go-new.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/go-new.c	Wed Oct 26 16:12:38 2011 -0700
@@ -6,6 +6,7 @@
 
 #include "go-alloc.h"
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 void *
diff -r c36211271569 libgo/runtime/go-note.c
--- a/libgo/runtime/go-note.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/go-note.c	Wed Oct 26 16:12:38 2011 -0700
@@ -12,7 +12,7 @@
 #include "runtime.h"
 
 /* We use a single global lock and condition variable.  It would be
-   better to use a futex on Linux.  */
+   better to use a futex on GNU/Linux.  */
 
 static pthread_mutex_t note_lock = PTHREAD_MUTEX_INITIALIZER;
 static pthread_cond_t note_cond = PTHREAD_COND_INITIALIZER;
diff -r c36211271569 libgo/runtime/go-panic.c
--- a/libgo/runtime/go-panic.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/go-panic.c	Wed Oct 26 16:12:38 2011 -0700
@@ -8,6 +8,7 @@
 #include <stdlib.h>
 
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 #include "go-alloc.h"
 #include "go-defer.h"
diff -r c36211271569 libgo/runtime/go-semacquire.c
--- a/libgo/runtime/go-semacquire.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/go-semacquire.c	Wed Oct 26 16:12:38 2011 -0700
@@ -13,9 +13,9 @@
 
 /* We use a single global lock and condition variable.  This is
    painful, since it will cause unnecessary contention, but is hard to
-   avoid in a portable manner.  On Linux we can use futexes, but they
-   are unfortunately not exposed by libc and are thus also hard to use
-   portably.  */
+   avoid in a portable manner.  On GNU/Linux we can use futexes, but
+   they are unfortunately not exposed by libc and are thus also hard
+   to use portably.  */
 
 static pthread_mutex_t sem_lock = PTHREAD_MUTEX_INITIALIZER;
 static pthread_cond_t sem_cond = PTHREAD_COND_INITIALIZER;
diff -r c36211271569 libgo/runtime/go-string-to-byte-array.c
--- a/libgo/runtime/go-string-to-byte-array.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/go-string-to-byte-array.c	Wed Oct 26 16:12:38 2011 -0700
@@ -7,6 +7,7 @@
 #include "go-string.h"
 #include "array.h"
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 struct __go_open_array
diff -r c36211271569 libgo/runtime/go-string-to-int-array.c
--- a/libgo/runtime/go-string-to-int-array.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/go-string-to-int-array.c	Wed Oct 26 16:12:38 2011 -0700
@@ -8,6 +8,7 @@
 #include "go-string.h"
 #include "array.h"
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 struct __go_open_array
diff -r c36211271569 libgo/runtime/go-strplus.c
--- a/libgo/runtime/go-strplus.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/go-strplus.c	Wed Oct 26 16:12:38 2011 -0700
@@ -6,6 +6,7 @@
 
 #include "go-string.h"
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 struct __go_string
diff -r c36211271569 libgo/runtime/go-strslice.c
--- a/libgo/runtime/go-strslice.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/go-strslice.c	Wed Oct 26 16:12:38 2011 -0700
@@ -7,6 +7,7 @@
 #include "go-string.h"
 #include "go-panic.h"
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 struct __go_string
diff -r c36211271569 libgo/runtime/goc2c.c
--- a/libgo/runtime/goc2c.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/goc2c.c	Wed Oct 26 16:12:38 2011 -0700
@@ -219,13 +219,14 @@
 }
 
 /*
- * Read and return a token.  Tokens are delimited by whitespace or by
- * [(),{}].  The latter are all returned as single characters.
+ * Read and return a token.  Tokens are string or character literals
+ * or else delimited by whitespace or by [(),{}].
+ * The latter are all returned as single characters.
  */
 static char *
 read_token(void)
 {
-	int c;
+	int c, q;
 	char *buf;
 	unsigned int alc, off;
 	const char* delims = "(),{}";
@@ -240,7 +241,26 @@
 	alc = 16;
 	buf = xmalloc(alc + 1);
 	off = 0;
-	if (strchr(delims, c) != NULL) {
+	if(c == '"' || c == '\'') {
+		q = c;
+		buf[off] = c;
+		++off;
+		while (1) {
+			if (off+2 >= alc) { // room for c and maybe next char
+				alc *= 2;
+				buf = xrealloc(buf, alc + 1);
+			}
+			c = getchar_no_eof();
+			buf[off] = c;
+			++off;
+			if(c == q)
+				break;
+			if(c == '\\') {
+				buf[off] = getchar_no_eof();
+				++off;
+			}
+		}
+	} else if (strchr(delims, c) != NULL) {
 		buf[off] = c;
 		++off;
 	} else {
diff -r c36211271569 libgo/runtime/malloc.goc
--- a/libgo/runtime/malloc.goc	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/malloc.goc	Wed Oct 26 16:12:38 2011 -0700
@@ -12,6 +12,7 @@
 #include <stdlib.h>
 #include "go-alloc.h"
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 #include "go-string.h"
 #include "interface.h"
@@ -96,11 +97,12 @@
 			m->mcache->next_sample -= size;
 		else {
 			// pick next profile time
+			// If you change this, also change allocmcache.
 			if(rate > 0x3fffffff)	// make 2*rate not overflow
 				rate = 0x3fffffff;
 			m->mcache->next_sample = runtime_fastrand1() % (2*rate);
 		profile:
-			runtime_setblockspecial(v);
+			runtime_setblockspecial(v, true);
 			runtime_MProf_Malloc(v, size);
 		}
 	}
@@ -224,6 +226,7 @@
 MCache*
 runtime_allocmcache(void)
 {
+	int32 rate;
 	MCache *c;
 
 	if(!__sync_bool_compare_and_swap(&m->mallocing, 0, 1))
@@ -239,6 +242,13 @@
 	mstats.mcache_sys = runtime_mheap.cachealloc.sys;
 	runtime_unlock(&runtime_mheap);
 
+	// Set first allocation sample size.
+	rate = runtime_MemProfileRate;
+	if(rate > 0x3fffffff)	// make 2*rate not overflow
+		rate = 0x3fffffff;
+	if(rate != 0)
+		c->next_sample = runtime_fastrand1() % (2*rate);
+
 	__sync_bool_compare_and_swap(&m->mallocing, 1, 0);
 	if(__sync_bool_compare_and_swap(&m->gcing, 1, 0))
 		__go_run_goroutine_gc(2);
@@ -280,6 +290,7 @@
 	byte *p;
 	uintptr arena_size, bitmap_size;
 	extern byte end[];
+	byte *want;
 
 	runtime_sizeof_C_MStats = sizeof(MStats);
 
@@ -341,9 +352,13 @@
 		// not as an absolute requirement.  If we ask for the end
 		// of the data segment but the operating system requires
 		// a little more space before we can start allocating, it will
-		// give out a slightly higher pointer.  That's fine.  
-		// Run with what we get back.
-		p = runtime_SysReserve(end, bitmap_size + arena_size);
+		// give out a slightly higher pointer.  Except QEMU, which
+		// is buggy, as usual: it won't adjust the pointer upward.
+		// So adjust it upward a little bit ourselves: 1/4 MB to get
+		// away from the running binary image and then round up
+		// to a MB boundary.
+		want = (byte*)(((uintptr)end + (1<<18) + (1<<20) - 1)&~((1<<20)-1));
+		p = runtime_SysReserve(want, bitmap_size + arena_size);
 		if(p == nil)
 			runtime_throw("runtime: cannot reserve arena virtual address space");
 	}
@@ -418,8 +433,9 @@
 	return runtime_mallocgc(n, 0, 1, 1);
 }
 
-func new(n uint32) (ret *uint8) {
-	ret = runtime_mal(n);
+func new(typ *Type) (ret *uint8) {
+	uint32 flag = typ->__code&GO_NO_POINTERS ? FlagNoPointers : 0;
+	ret = runtime_mallocgc(typ->__size, flag, 1, 1);
 }
 
 func Alloc(n uintptr) (p *byte) {
@@ -444,9 +460,8 @@
 	const FuncType *ft;
 
 	if(obj.__type_descriptor == nil) {
-		// runtime_printf("runtime.SetFinalizer: first argument is nil interface\n");
-	throw:
-		runtime_throw("runtime.SetFinalizer");
+		// runtime·printf("runtime.SetFinalizer: first argument is nil interface\n");
+		goto throw;
 	}
 	if(obj.__type_descriptor->__code != GO_PTR) {
 		// runtime_printf("runtime.SetFinalizer: first argument is %S, not pointer\n", *obj.type->string);
@@ -458,19 +473,21 @@
 	}
 	ft = nil;
 	if(finalizer.__type_descriptor != nil) {
-		if(finalizer.__type_descriptor->__code != GO_FUNC) {
-		badfunc:
-			// runtime_printf("runtime.SetFinalizer: second argument is %S, not func(%S)\n", *finalizer.type->string, *obj.type->string);
-			goto throw;
-		}
+		if(finalizer.__type_descriptor->__code != GO_FUNC)
+			goto badfunc;
 		ft = (const FuncType*)finalizer.__type_descriptor;
 		if(ft->__dotdotdot || ft->__in.__count != 1 || !__go_type_descriptors_equal(*(Type**)ft->__in.__values, obj.__type_descriptor))
 			goto badfunc;
+	}
 
-		if(runtime_getfinalizer(obj.__object, 0)) {
-			// runtime_printf("runtime.SetFinalizer: finalizer already set");
-			goto throw;
-		}
+	if(!runtime_addfinalizer(obj.__object, finalizer.__type_descriptor != nil ? *(void**)finalizer.__object : nil, ft)) {
+		runtime_printf("runtime.SetFinalizer: finalizer already set\n");
+		goto throw;
 	}
-	runtime_addfinalizer(obj.__object, finalizer.__type_descriptor != nil ? *(void**)finalizer.__object : nil, ft);
+	return;
+
+badfunc:
+	// runtime_printf("runtime.SetFinalizer: second argument is %S, not func(%S)\n", *finalizer.type->string, *obj.type->string);
+throw:
+	runtime_throw("runtime.SetFinalizer");
 }
diff -r c36211271569 libgo/runtime/malloc.h
--- a/libgo/runtime/malloc.h	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/malloc.h	Wed Oct 26 16:12:38 2011 -0700
@@ -120,6 +120,13 @@
 #else
 	MHeapMap_Bits = 20,
 #endif
+
+	// Max number of threads to run garbage collection.
+	// 2, 3, and 4 are all plausible maximums depending
+	// on the hardware details of the machine.  The second
+	// proc is the one that helps the most (after the first),
+	// so start with just 2 for now.
+	MaxGcproc = 2,
 };
 
 // A generic linked list of blocks.  (Typically the block is bigger than sizeof(MLink).)
@@ -192,7 +199,7 @@
 	uint64	nlookup;	// number of pointer lookups
 	uint64	nmalloc;	// number of mallocs
 	uint64	nfree;  // number of frees
-	
+
 	// Statistics about malloc heap.
 	// protected by mheap.Lock
 	uint64	heap_alloc;	// bytes allocated and still in use
@@ -210,7 +217,7 @@
 	uint64	mcache_inuse;	// MCache structures
 	uint64	mcache_sys;
 	uint64	buckhash_sys;	// profiling bucket hash table
-	
+
 	// Statistics about garbage collector.
 	// Protected by stopping the world during GC.
 	uint64	next_gc;	// next GC (in heap_alloc time)
@@ -219,7 +226,7 @@
 	uint32	numgc;
 	bool	enablegc;
 	bool	debuggc;
-	
+
 	// Statistics about allocation size classes.
 	struct {
 		uint32 size;
@@ -240,7 +247,7 @@
 //
 // class_to_size[i] = largest size in class i
 // class_to_allocnpages[i] = number of pages to allocate when
-// 	making new objects in class i
+//	making new objects in class i
 // class_to_transfercount[i] = number of objects to move when
 //	taking a bunch of objects out of the central lists
 //	and putting them in the thread free list.
@@ -279,7 +286,7 @@
 		int64 nmalloc;
 		int64 nfree;
 	} local_by_size[NumSizeClasses];
-	
+
 };
 
 void*	runtime_MCache_Alloc(MCache *c, int32 sizeclass, uintptr size, int32 zeroed);
@@ -352,14 +359,14 @@
 	byte *arena_start;
 	byte *arena_used;
 	byte *arena_end;
-	
+
 	// central free lists for small size classes.
 	// the union makes sure that the MCentrals are
-	// spaced 64 bytes apart, so that each MCentral.Lock
+	// spaced CacheLineSize bytes apart, so that each MCentral.Lock
 	// gets its own cache line.
 	union {
 		MCentral;
-		byte pad[64];
+		byte pad[CacheLineSize];
 	} central[NumSizeClasses];
 
 	FixAlloc spanalloc;	// allocator for Span*
@@ -387,7 +394,7 @@
 void	runtime_markspan(void *v, uintptr size, uintptr n, bool leftover);
 void	runtime_unmarkspan(void *v, uintptr size);
 bool	runtime_blockspecial(void*);
-void	runtime_setblockspecial(void*);
+void	runtime_setblockspecial(void*, bool);
 void	runtime_purgecachedstats(M*);
 
 enum
@@ -402,6 +409,8 @@
 void	runtime_MProf_Malloc(void*, uintptr);
 void	runtime_MProf_Free(void*, uintptr);
 void	runtime_MProf_Mark(void (*scan)(byte *, int64));
+int32	runtime_helpgc(bool*);
+void	runtime_gchelper(void);
 
 // Malloc profiling settings.
 // Must match definition in extern.go.
@@ -412,13 +421,6 @@
 };
 extern int32 runtime_malloc_profile;
 
-typedef struct Finalizer Finalizer;
-struct Finalizer
-{
-	Finalizer *next;	// for use by caller of getfinalizer
-	void (*fn)(void*);
-	void *arg;
-	const struct __go_func_type *ft;
-};
-
-Finalizer*	runtime_getfinalizer(void*, bool);
+struct __go_func_type;
+bool	runtime_getfinalizer(void *p, bool del, void (**fn)(void*), const struct __go_func_type **ft);
+void	runtime_walkfintab(void (*fn)(void*), void (*scan)(byte*, int64));
diff -r c36211271569 libgo/runtime/mcache.c
--- a/libgo/runtime/mcache.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/mcache.c	Wed Oct 26 16:12:38 2011 -0700
@@ -7,6 +7,7 @@
 // See malloc.h for an overview.
 
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 void*
diff -r c36211271569 libgo/runtime/mcentral.c
--- a/libgo/runtime/mcentral.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/mcentral.c	Wed Oct 26 16:12:38 2011 -0700
@@ -15,6 +15,7 @@
 // so that it is faster to move those lists between MCaches and MCentrals.
 
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 static bool MCentral_Grow(MCentral *c);
diff -r c36211271569 libgo/runtime/mem.c
--- a/libgo/runtime/mem.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/mem.c	Wed Oct 26 16:12:38 2011 -0700
@@ -2,6 +2,7 @@
 #include <unistd.h>
 
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 #ifndef MAP_ANON
diff -r c36211271569 libgo/runtime/mem_posix_memalign.c
--- a/libgo/runtime/mem_posix_memalign.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/mem_posix_memalign.c	Wed Oct 26 16:12:38 2011 -0700
@@ -1,6 +1,7 @@
 #include <errno.h>
 
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 void*
diff -r c36211271569 libgo/runtime/mfinal.c
--- a/libgo/runtime/mfinal.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/mfinal.c	Wed Oct 26 16:12:38 2011 -0700
@@ -3,18 +3,17 @@
 // license that can be found in the LICENSE file.
 
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
-// Lock to protect finalizer data structures.
-// Cannot reuse mheap.Lock because the finalizer
-// maintenance requires allocation.
-static Lock finlock;
+enum { debug = 0 };
 
-void
-runtime_initfintab()
+typedef struct Fin Fin;
+struct Fin
 {
-	runtime_initlock(&finlock);
-}
+	void (*fn)(void*);
+	const struct __go_func_type *ft;
+};
 
 // Finalizer hash table.  Direct hash, linear scan, at most 3/4 full.
 // Table size is power of 3 so that hash can be key % max.
@@ -26,25 +25,43 @@
 typedef struct Fintab Fintab;
 struct Fintab
 {
-	void **key;
-	Finalizer **val;
+	Lock;
+	void **fkey;
+	Fin *val;
 	int32 nkey;	// number of non-nil entries in key
 	int32 ndead;	// number of dead (-1) entries in key
 	int32 max;	// size of key, val allocations
 };
 
+#define TABSZ 17
+#define TAB(p) (&fintab[((uintptr)(p)>>3)%TABSZ])
+
+static struct {
+	Fintab;
+	uint8 pad[0 /* CacheLineSize - sizeof(Fintab) */];	
+} fintab[TABSZ];
+
+void
+runtime_initfintab()
+{
+	int32 i;
+
+	for(i=0; i<TABSZ; i++)
+		runtime_initlock(&fintab[i]);
+}
+
 static void
-addfintab(Fintab *t, void *k, Finalizer *v)
+addfintab(Fintab *t, void *k, void (*fn)(void*), const struct __go_func_type *ft)
 {
 	int32 i, j;
 
 	i = (uintptr)k % (uintptr)t->max;
 	for(j=0; j<t->max; j++) {
-		if(t->key[i] == nil) {
+		if(t->fkey[i] == nil) {
 			t->nkey++;
 			goto ret;
 		}
-		if(t->key[i] == (void*)-1) {
+		if(t->fkey[i] == (void*)-1) {
 			t->ndead--;
 			goto ret;
 		}
@@ -56,30 +73,32 @@
 	runtime_throw("finalizer table inconsistent");
 
 ret:
-	t->key[i] = k;
-	t->val[i] = v;
+	t->fkey[i] = k;
+	t->val[i].fn = fn;
+	t->val[i].ft = ft;
 }
 
-static Finalizer*
-lookfintab(Fintab *t, void *k, bool del)
+static bool
+lookfintab(Fintab *t, void *k, bool del, Fin *f)
 {
 	int32 i, j;
-	Finalizer *v;
 
 	if(t->max == 0)
-		return nil;
+		return false;
 	i = (uintptr)k % (uintptr)t->max;
 	for(j=0; j<t->max; j++) {
-		if(t->key[i] == nil)
-			return nil;
-		if(t->key[i] == k) {
-			v = t->val[i];
+		if(t->fkey[i] == nil)
+			return false;
+		if(t->fkey[i] == k) {
+			if(f)
+				*f = t->val[i];
 			if(del) {
-				t->key[i] = (void*)-1;
-				t->val[i] = nil;
+				t->fkey[i] = (void*)-1;
+				t->val[i].fn = nil;
+				t->val[i].ft = nil;
 				t->ndead++;
 			}
-			return v;
+			return true;
 		}
 		if(++i == t->max)
 			i = 0;
@@ -87,108 +106,123 @@
 
 	// cannot happen - table is known to be non-full
 	runtime_throw("finalizer table inconsistent");
-	return nil;
+	return false;
 }
 
-static Fintab fintab;
+static void
+resizefintab(Fintab *tab)
+{
+	Fintab newtab;
+	void *k;
+	int32 i;
 
-// add finalizer; caller is responsible for making sure not already in table
-void
+	runtime_memclr((byte*)&newtab, sizeof newtab);
+	newtab.max = tab->max;
+	if(newtab.max == 0)
+		newtab.max = 3*3*3;
+	else if(tab->ndead < tab->nkey/2) {
+		// grow table if not many dead values.
+		// otherwise just rehash into table of same size.
+		newtab.max *= 3;
+	}
+	
+	newtab.fkey = runtime_mallocgc(newtab.max*sizeof newtab.fkey[0], FlagNoPointers, 0, 1);
+	newtab.val = runtime_mallocgc(newtab.max*sizeof newtab.val[0], 0, 0, 1);
+	
+	for(i=0; i<tab->max; i++) {
+		k = tab->fkey[i];
+		if(k != nil && k != (void*)-1)
+			addfintab(&newtab, k, tab->val[i].fn, tab->val[i].ft);
+	}
+	
+	runtime_free(tab->fkey);
+	runtime_free(tab->val);
+	
+	tab->fkey = newtab.fkey;
+	tab->val = newtab.val;
+	tab->nkey = newtab.nkey;
+	tab->ndead = newtab.ndead;
+	tab->max = newtab.max;
+}
+
+bool
 runtime_addfinalizer(void *p, void (*f)(void*), const struct __go_func_type *ft)
 {
-	Fintab newtab;
-	int32 i;
+	Fintab *tab;
 	byte *base;
-	Finalizer *e;
+	bool ret = false;
 	
-	e = nil;
-	if(f != nil) {
-		e = runtime_mal(sizeof *e);
-		e->fn = f;
-		e->ft = ft;
+	if(debug) {
+		if(!runtime_mlookup(p, &base, nil, nil) || p != base)
+			runtime_throw("addfinalizer on invalid pointer");
 	}
-
+	
 	if(!__sync_bool_compare_and_swap(&m->holds_finlock, 0, 1))
 		runtime_throw("finalizer deadlock");
 
-	runtime_lock(&finlock);
-	if(!runtime_mlookup(p, &base, nil, nil) || p != base) {
-		runtime_unlock(&finlock);
-		__sync_bool_compare_and_swap(&m->holds_finlock, 1, 0);
-		runtime_throw("addfinalizer on invalid pointer");
-	}
+	tab = TAB(p);
+	runtime_lock(tab);
 	if(f == nil) {
-		lookfintab(&fintab, p, 1);
+		if(lookfintab(tab, p, true, nil))
+			runtime_setblockspecial(p, false);
+		ret = true;
 		goto unlock;
 	}
 
-	if(lookfintab(&fintab, p, 0)) {
-		runtime_unlock(&finlock);
-		__sync_bool_compare_and_swap(&m->holds_finlock, 1, 0);
-		runtime_throw("double finalizer");
+	if(lookfintab(tab, p, false, nil)) {
+		ret = false;
+		goto unlock;
 	}
-	runtime_setblockspecial(p);
 
-	if(fintab.nkey >= fintab.max/2+fintab.max/4) {
+	if(tab->nkey >= tab->max/2+tab->max/4) {
 		// keep table at most 3/4 full:
 		// allocate new table and rehash.
-
-		runtime_memclr((byte*)&newtab, sizeof newtab);
-		newtab.max = fintab.max;
-		if(newtab.max == 0)
-			newtab.max = 3*3*3;
-		else if(fintab.ndead < fintab.nkey/2) {
-			// grow table if not many dead values.
-			// otherwise just rehash into table of same size.
-			newtab.max *= 3;
-		}
-
-		newtab.key = runtime_mallocgc(newtab.max*sizeof newtab.key[0], FlagNoPointers, 0, 1);
-		newtab.val = runtime_mallocgc(newtab.max*sizeof newtab.val[0], 0, 0, 1);
-
-		for(i=0; i<fintab.max; i++) {
-			void *k;
-
-			k = fintab.key[i];
-			if(k != nil && k != (void*)-1)
-				addfintab(&newtab, k, fintab.val[i]);
-		}
-		runtime_free(fintab.key);
-		runtime_free(fintab.val);
-		fintab = newtab;
+		resizefintab(tab);
 	}
 
-	addfintab(&fintab, p, e);
+	addfintab(tab, p, f, ft);
+	runtime_setblockspecial(p, true);
+	ret = true;
+
  unlock:
-	runtime_unlock(&finlock);
+	runtime_unlock(tab);
 
 	__sync_bool_compare_and_swap(&m->holds_finlock, 1, 0);
 
 	if(__sync_bool_compare_and_swap(&m->gcing_for_finlock, 1, 0)) {
 		__go_run_goroutine_gc(200);
 	}
+
+	return ret;
 }
 
 // get finalizer; if del, delete finalizer.
-// caller is responsible for updating RefHasFinalizer bit.
-Finalizer*
-runtime_getfinalizer(void *p, bool del)
+// caller is responsible for updating RefHasFinalizer (special) bit.
+bool
+runtime_getfinalizer(void *p, bool del, void (**fn)(void*), const struct __go_func_type **ft)
 {
-	Finalizer *f;
+	Fintab *tab;
+	bool res;
+	Fin f;
 	
 	if(!__sync_bool_compare_and_swap(&m->holds_finlock, 0, 1))
 		runtime_throw("finalizer deadlock");
 
-	runtime_lock(&finlock);
-	f = lookfintab(&fintab, p, del);
-	runtime_unlock(&finlock);
+	tab = TAB(p);
+	runtime_lock(tab);
+	res = lookfintab(tab, p, del, &f);
+	runtime_unlock(tab);
 
 	__sync_bool_compare_and_swap(&m->holds_finlock, 1, 0);
 	if(__sync_bool_compare_and_swap(&m->gcing_for_finlock, 1, 0)) {
 		__go_run_goroutine_gc(201);
 	}
 
-	return f;
+	if(res==false)
+		return false;
+	*fn = f.fn;
+	*ft = f.ft;
+	return true;
 }
 
 void
@@ -196,18 +230,22 @@
 {
 	void **key;
 	void **ekey;
+	int32 i;
 
 	if(!__sync_bool_compare_and_swap(&m->holds_finlock, 0, 1))
 		runtime_throw("finalizer deadlock");
 
-	scan((byte*)&fintab, sizeof fintab);
-	runtime_lock(&finlock);
-	key = fintab.key;
-	ekey = key + fintab.max;
-	for(; key < ekey; key++)
-		if(*key != nil && *key != ((void*)-1))
-			fn(*key);
-	runtime_unlock(&finlock);
+	for(i=0; i<TABSZ; i++) {
+		runtime_lock(&fintab[i]);
+		key = fintab[i].fkey;
+		ekey = key + fintab[i].max;
+		for(; key < ekey; key++)
+			if(*key != nil && *key != ((void*)-1))
+				fn(*key);
+		scan((byte*)&fintab[i].fkey, sizeof(void*));
+		scan((byte*)&fintab[i].val, sizeof(void*));
+		runtime_unlock(&fintab[i]);
+	}
 
 	__sync_bool_compare_and_swap(&m->holds_finlock, 1, 0);
 	if(__sync_bool_compare_and_swap(&m->gcing_for_finlock, 1, 0)) {
diff -r c36211271569 libgo/runtime/mfixalloc.c
--- a/libgo/runtime/mfixalloc.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/mfixalloc.c	Wed Oct 26 16:12:38 2011 -0700
@@ -7,6 +7,7 @@
 // See malloc.h for overview.
 
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 // Initialize f to allocate objects of the given size,
diff -r c36211271569 libgo/runtime/mgc0.c
--- a/libgo/runtime/mgc0.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/mgc0.c	Wed Oct 26 16:12:38 2011 -0700
@@ -5,13 +5,14 @@
 // Garbage collector.
 
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 enum {
 	Debug = 0,
-	UseCas = 1,
 	PtrSize = sizeof(void*),
-	
+	DebugMark = 0,  // run second pass to check mark
+
 	// Four bits per word (see #defines below).
 	wordsPerBitmapWord = sizeof(void*)*8/4,
 	bitShift = sizeof(void*)*8/4,
@@ -50,28 +51,72 @@
 
 #define bitMask (bitBlockBoundary | bitAllocated | bitMarked | bitSpecial)
 
+// TODO: Make these per-M.
 static uint64 nlookup;
 static uint64 nsizelookup;
 static uint64 naddrlookup;
+static uint64 nhandoff;
+
 static int32 gctrace;
 
 typedef struct Workbuf Workbuf;
 struct Workbuf
 {
 	Workbuf *next;
-	uintptr nw;
-	byte *w[2048-2];
+	uintptr nobj;
+	byte *obj[512-2];
+};
+
+typedef struct Finalizer Finalizer;
+struct Finalizer
+{
+	void (*fn)(void*);
+	void *arg;
+	const struct __go_func_type *ft;
+};
+
+typedef struct FinBlock FinBlock;
+struct FinBlock
+{
+	FinBlock *alllink;
+	FinBlock *next;
+	int32 cnt;
+	int32 cap;
+	Finalizer fin[1];
 };
 
 static bool finstarted;
 static pthread_mutex_t finqlock = PTHREAD_MUTEX_INITIALIZER;
 static pthread_cond_t finqcond = PTHREAD_COND_INITIALIZER;
-static Finalizer *finq;
+static FinBlock *finq; // list of finalizers that are to be executed
+static FinBlock *finc; // cache of free blocks
+static FinBlock *allfin; // list of all blocks
+static Lock finlock;
 static int32 fingwait;
 
 static void runfinq(void*);
 static Workbuf* getempty(Workbuf*);
 static Workbuf* getfull(Workbuf*);
+static void	putempty(Workbuf*);
+static Workbuf* handoff(Workbuf*);
+
+static struct {
+	Lock fmu;
+	Workbuf	*full;
+	Lock emu;
+	Workbuf	*empty;
+	uint32	nproc;
+	volatile uint32	nwait;
+	volatile uint32	ndone;
+	Note	alldone;
+	Lock	markgate;
+	Lock	sweepgate;
+	MSpan	*spans;
+
+	Lock;
+	byte	*chunk;
+	uintptr	nchunk;
+} work;
 
 // scanblock scans a block of n bytes starting at pointer b for references
 // to other objects, scanning any it finds recursively until there are no
@@ -82,13 +127,14 @@
 static void
 scanblock(byte *b, int64 n)
 {
-	byte *obj, *arena_start, *p;
+	byte *obj, *arena_start, *arena_used, *p;
 	void **vp;
-	uintptr size, *bitp, bits, shift, i, j, x, xbits, off;
+	uintptr size, *bitp, bits, shift, i, j, x, xbits, off, nobj, nproc;
 	MSpan *s;
 	PageID k;
-	void **bw, **w, **ew;
+	void **wp;
 	Workbuf *wbuf;
+	bool keepworking;
 
 	if((int64)(uintptr)n != n || n < 0) {
 		// runtime_printf("scanblock %p %lld\n", b, (long long)n);
@@ -97,11 +143,19 @@
 
 	// Memory arena parameters.
 	arena_start = runtime_mheap.arena_start;
-	
+	arena_used = runtime_mheap.arena_used;
+	nproc = work.nproc;
+
 	wbuf = nil;  // current work buffer
-	ew = nil;  // end of work buffer
-	bw = nil;  // beginning of work buffer
-	w = nil;  // current pointer into work buffer
+	wp = nil;  // storage for next queued pointer (write pointer)
+	nobj = 0;  // number of queued objects
+
+	// Scanblock helpers pass b==nil.
+	// The main proc needs to return to make more
+	// calls to scanblock.  But if work.nproc==1 then
+	// might as well process blocks as soon as we
+	// have them.
+	keepworking = b == nil || work.nproc == 1;
 
 	// Align b to a word boundary.
 	off = (uintptr)b & (PtrSize-1);
@@ -117,17 +171,17 @@
 			runtime_printf("scanblock %p %lld\n", b, (long long) n);
 
 		vp = (void**)b;
-		n /= PtrSize;
+		n >>= (2+PtrSize/8);  /* n /= PtrSize (4 or 8) */
 		for(i=0; i<(uintptr)n; i++) {
 			obj = (byte*)vp[i];
-			
+
 			// Words outside the arena cannot be pointers.
-			if((byte*)obj < arena_start || (byte*)obj >= runtime_mheap.arena_used)
+			if((byte*)obj < arena_start || (byte*)obj >= arena_used)
 				continue;
-			
+
 			// obj may be a pointer to a live object.
 			// Try to find the beginning of the object.
-			
+
 			// Round down to word boundary.
 			obj = (void*)((uintptr)obj & ~((uintptr)PtrSize-1));
 
@@ -185,47 +239,72 @@
 		found:
 			// Now we have bits, bitp, and shift correct for
 			// obj pointing at the base of the object.
-			// If not allocated or already marked, done.
-			if((bits & bitAllocated) == 0 || (bits & bitMarked) != 0)
+			// Only care about allocated and not marked.
+			if((bits & (bitAllocated|bitMarked)) != bitAllocated)
 				continue;
-			*bitp |= bitMarked<<shift;
+			if(nproc == 1)
+				*bitp |= bitMarked<<shift;
+			else {
+				for(;;) {
+					x = *bitp;
+					if(x & (bitMarked<<shift))
+						goto continue_obj;
+					if(runtime_casp((void**)bitp, (void*)x, (void*)(x|(bitMarked<<shift))))
+						break;
+				}
+			}
 
 			// If object has no pointers, don't need to scan further.
 			if((bits & bitNoPointers) != 0)
 				continue;
 
+			// If another proc wants a pointer, give it some.
+			if(nobj > 4 && work.nwait > 0 && work.full == nil) {
+				wbuf->nobj = nobj;
+				wbuf = handoff(wbuf);
+				nobj = wbuf->nobj;
+				wp = (void**)(wbuf->obj + nobj);
+			}
+
 			// If buffer is full, get a new one.
-			if(w >= ew) {
+			if(wbuf == nil || nobj >= nelem(wbuf->obj)) {
+				if(wbuf != nil)
+					wbuf->nobj = nobj;
 				wbuf = getempty(wbuf);
-				bw = (void**)wbuf->w;
-				w = bw;
-				ew = bw + nelem(wbuf->w);
+				wp = (void**)(wbuf->obj);
+				nobj = 0;
 			}
-			*w++ = obj;
+			*wp++ = obj;
+			nobj++;
+		continue_obj:;
 		}
-		
+
 		// Done scanning [b, b+n).  Prepare for the next iteration of
 		// the loop by setting b and n to the parameters for the next block.
 
-		// Fetch b from the work buffers.
-		if(w <= bw) {
+		// Fetch b from the work buffer.
+		if(nobj == 0) {
+			if(!keepworking) {
+				putempty(wbuf);
+				return;
+			}
 			// Emptied our buffer: refill.
 			wbuf = getfull(wbuf);
 			if(wbuf == nil)
-				break;
-			bw = (void**)wbuf->w;
-			ew = (void**)(wbuf->w + nelem(wbuf->w));
-			w = bw+wbuf->nw;
+				return;
+			nobj = wbuf->nobj;
+			wp = (void**)(wbuf->obj + wbuf->nobj);
 		}
-		b = *--w;
-	
+		b = *--wp;
+		nobj--;
+
 		// Figure out n = size of b.  Start by loading bits for b.
 		off = (uintptr*)b - (uintptr*)arena_start;
 		bitp = (uintptr*)arena_start - off/wordsPerBitmapWord - 1;
 		shift = off % wordsPerBitmapWord;
 		xbits = *bitp;
 		bits = xbits >> shift;
-		
+
 		// Might be small; look for nearby block boundary.
 		// A block boundary is marked by either bitBlockBoundary
 		// or bitAllocated being set (see notes near their definition).
@@ -244,12 +323,12 @@
 		// apply a mask to keep only the bits corresponding
 		// to shift+j < bitShift aka j < bitShift-shift.
 		bits &= (boundary<<(bitShift-shift)) - boundary;
-		
+
 		// A block boundary j words before b is indicated by
 		//	xbits>>(shift-j) & boundary
 		// (assuming shift >= j).  There is no cleverness here
 		// avoid the test, because when j gets too large the shift
-		// turns negative, which is undefined in C.		
+		// turns negative, which is undefined in C.
 
 		for(j=1; j<bitShift; j++) {
 			if(((bits>>j)&boundary) != 0 || (shift>=j && ((xbits>>(shift-j))&boundary) != 0)) {
@@ -257,7 +336,7 @@
 				goto scan;
 			}
 		}
-		
+
 		// Fall back to asking span about size class.
 		// (Manually inlined copy of MHeap_Lookup.)
 		nlookup++;
@@ -274,29 +353,123 @@
 	}
 }
 
-static struct {
-	Workbuf	*full;
-	Workbuf	*empty;
-	byte	*chunk;
-	uintptr	nchunk;
-} work;
+// debug_scanblock is the debug copy of scanblock.
+// it is simpler, slower, single-threaded, recursive,
+// and uses bitSpecial as the mark bit.
+static void
+debug_scanblock(byte *b, int64 n)
+{
+	byte *obj, *p;
+	void **vp;
+	uintptr size, *bitp, bits, shift, i, xbits, off;
+	MSpan *s;
+
+	if(!DebugMark)
+		runtime_throw("debug_scanblock without DebugMark");
+
+	if((int64)(uintptr)n != n || n < 0) {
+		//runtime_printf("debug_scanblock %p %D\n", b, n);
+		runtime_throw("debug_scanblock");
+	}
+
+	// Align b to a word boundary.
+	off = (uintptr)b & (PtrSize-1);
+	if(off != 0) {
+		b += PtrSize - off;
+		n -= PtrSize - off;
+	}
+
+	vp = (void**)b;
+	n /= PtrSize;
+	for(i=0; i<(uintptr)n; i++) {
+		obj = (byte*)vp[i];
+
+		// Words outside the arena cannot be pointers.
+		if((byte*)obj < runtime_mheap.arena_start || (byte*)obj >= runtime_mheap.arena_used)
+			continue;
+
+		// Round down to word boundary.
+		obj = (void*)((uintptr)obj & ~((uintptr)PtrSize-1));
+
+		// Consult span table to find beginning.
+		s = runtime_MHeap_LookupMaybe(&runtime_mheap, obj);
+		if(s == nil)
+			continue;
+
+
+		p =  (byte*)((uintptr)s->start<<PageShift);
+		if(s->sizeclass == 0) {
+			obj = p;
+			size = (uintptr)s->npages<<PageShift;
+		} else {
+			if((byte*)obj >= (byte*)s->limit)
+				continue;
+			size = runtime_class_to_size[s->sizeclass];
+			int32 i = ((byte*)obj - p)/size;
+			obj = p+i*size;
+		}
+
+		// Now that we know the object header, reload bits.
+		off = (uintptr*)obj - (uintptr*)runtime_mheap.arena_start;
+		bitp = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
+		shift = off % wordsPerBitmapWord;
+		xbits = *bitp;
+		bits = xbits >> shift;
+
+		// Now we have bits, bitp, and shift correct for
+		// obj pointing at the base of the object.
+		// If not allocated or already marked, done.
+		if((bits & bitAllocated) == 0 || (bits & bitSpecial) != 0)  // NOTE: bitSpecial not bitMarked
+			continue;
+		*bitp |= bitSpecial<<shift;
+		if(!(bits & bitMarked))
+			runtime_printf("found unmarked block %p in %p\n", obj, vp+i);
+
+		// If object has no pointers, don't need to scan further.
+		if((bits & bitNoPointers) != 0)
+			continue;
+
+		debug_scanblock(obj, size);
+	}
+}
 
 // Get an empty work buffer off the work.empty list,
 // allocating new buffers as needed.
 static Workbuf*
 getempty(Workbuf *b)
 {
-	if(b != nil) {
-		b->nw = nelem(b->w);
-		b->next = work.full;
-		work.full = b;
+	if(work.nproc == 1) {
+		// Put b on full list.
+		if(b != nil) {
+			b->next = work.full;
+			work.full = b;
+		}
+		// Grab from empty list if possible.
+		b = work.empty;
+		if(b != nil) {
+			work.empty = b->next;
+			goto haveb;
+		}
+	} else {
+		// Put b on full list.
+		if(b != nil) {
+			runtime_lock(&work.fmu);
+			b->next = work.full;
+			work.full = b;
+			runtime_unlock(&work.fmu);
+		}
+		// Grab from empty list if possible.
+		runtime_lock(&work.emu);
+		b = work.empty;
+		if(b != nil)
+			work.empty = b->next;
+		runtime_unlock(&work.emu);
+		if(b != nil)
+			goto haveb;
 	}
-	b = work.empty;
-	if(b != nil) {
-		work.empty = b->next;
-		return b;
-	}
-	
+
+	// Need to allocate.
+	runtime_lock(&work);
 	if(work.nchunk < sizeof *b) {
 		work.nchunk = 1<<20;
 		work.chunk = runtime_SysAlloc(work.nchunk);
@@ -304,25 +477,121 @@
 	b = (Workbuf*)work.chunk;
 	work.chunk += sizeof *b;
 	work.nchunk -= sizeof *b;
+	runtime_unlock(&work);
+
+haveb:
+	b->nobj = 0;
 	return b;
 }
 
+static void
+putempty(Workbuf *b)
+{
+	if(b == nil)
+		return;
+
+	if(work.nproc == 1) {
+		b->next = work.empty;
+		work.empty = b;
+		return;
+	}
+
+	runtime_lock(&work.emu);
+	b->next = work.empty;
+	work.empty = b;
+	runtime_unlock(&work.emu);
+}
+
 // Get a full work buffer off the work.full list, or return nil.
 static Workbuf*
 getfull(Workbuf *b)
 {
-	if(b != nil) {
-		b->nw = 0;
-		b->next = work.empty;
-		work.empty = b;
+	int32 i;
+	Workbuf *b1;
+
+	if(work.nproc == 1) {
+		// Put b on empty list.
+		if(b != nil) {
+			b->next = work.empty;
+			work.empty = b;
+		}
+		// Grab from full list if possible.
+		// Since work.nproc==1, no one else is
+		// going to give us work.
+		b = work.full;
+		if(b != nil)
+			work.full = b->next;
+		return b;
 	}
-	b = work.full;
-	if(b != nil)
-		work.full = b->next;
-	return b;
+
+	putempty(b);
+
+	// Grab buffer from full list if possible.
+	for(;;) {
+		b1 = work.full;
+		if(b1 == nil)
+			break;
+		runtime_lock(&work.fmu);
+		if(work.full != nil) {
+			b1 = work.full;
+			work.full = b1->next;
+			runtime_unlock(&work.fmu);
+			return b1;
+		}
+		runtime_unlock(&work.fmu);
+	}
+
+	runtime_xadd(&work.nwait, +1);
+	for(i=0;; i++) {
+		b1 = work.full;
+		if(b1 != nil) {
+			runtime_lock(&work.fmu);
+			if(work.full != nil) {
+				runtime_xadd(&work.nwait, -1);
+				b1 = work.full;
+				work.full = b1->next;
+				runtime_unlock(&work.fmu);
+				return b1;
+			}
+			runtime_unlock(&work.fmu);
+			continue;
+		}
+		if(work.nwait == work.nproc)
+			return nil;
+		if(i < 10)
+			runtime_procyield(20);
+		else if(i < 20)
+			runtime_osyield();
+		else
+			runtime_usleep(100);
+	}
 }
 
-// Scanstack calls scanblock on each of gp's stack segments.
+static Workbuf*
+handoff(Workbuf *b)
+{
+	int32 n;
+	Workbuf *b1;
+
+	// Make new buffer with half of b's pointers.
+	b1 = getempty(nil);
+	n = b->nobj/2;
+	b->nobj -= n;
+	b1->nobj = n;
+	runtime_memmove(b1->obj, b->obj+b->nobj, n*sizeof b1->obj[0]);
+	nhandoff += n;
+
+	// Put b on full list - let first half of b get stolen.
+	runtime_lock(&work.fmu);
+	b->next = work.full;
+	work.full = b;
+	runtime_unlock(&work.fmu);
+
+	return b1;
+}
+
+// Markfin calls scanblock on the blocks that have finalizers:
+// the things pointed at cannot be freed until the finalizers have run.
 static void
 markfin(void *v)
 {
@@ -355,11 +624,22 @@
 	roots = r;
 }
 
-// Mark 
 static void
-mark(void)
+debug_markfin(void *v)
+{
+	uintptr size;
+
+	if(!runtime_mlookup(v, (byte**)&v, &size, nil))
+		runtime_throw("debug_mark - finalizer inconsistency");
+	debug_scanblock(v, size);
+}
+
+// Mark
+static void
+mark(void (*scan)(byte*, int64))
 {
 	struct root_list *pl;
+	FinBlock *fb;
 
 	for(pl = roots; pl != nil; pl = pl->next) {
 		struct root* pr = &pl->roots[0];
@@ -372,18 +652,63 @@
 		}
 	}
 
-	scanblock((byte*)&m0, sizeof m0);
-	scanblock((byte*)&finq, sizeof finq);
-	runtime_MProf_Mark(scanblock);
+	scan((byte*)&m0, sizeof m0);
+	scan((byte*)&finq, sizeof finq);
+	runtime_MProf_Mark(scan);
 
 	// mark stacks
-	__go_scanstacks(scanblock);
+	__go_scanstacks(scan);
 
 	// mark things pointed at by objects with finalizers
-	runtime_walkfintab(markfin, scanblock);
+	if(scan == debug_scanblock)
+		runtime_walkfintab(debug_markfin, scan);
+	else
+		runtime_walkfintab(markfin, scan);
+
+	for(fb=allfin; fb; fb=fb->alllink)
+		scanblock((byte*)fb->fin, fb->cnt*sizeof(fb->fin[0]));
+
+	// in multiproc mode, join in the queued work.
+	scan(nil, 0);
 }
 
-// Sweep frees or calls finalizers for blocks not marked in the mark phase.
+static bool
+handlespecial(byte *p, uintptr size)
+{
+	void (*fn)(void*);
+	const struct __go_func_type *ft;
+	FinBlock *block;
+	Finalizer *f;
+	
+	if(!runtime_getfinalizer(p, true, &fn, &ft)) {
+		runtime_setblockspecial(p, false);
+		runtime_MProf_Free(p, size);
+		return false;
+	}
+
+	runtime_lock(&finlock);
+	if(finq == nil || finq->cnt == finq->cap) {
+		if(finc == nil) {
+			finc = runtime_SysAlloc(PageSize);
+			finc->cap = (PageSize - sizeof(FinBlock)) / sizeof(Finalizer) + 1;
+			finc->alllink = allfin;
+			allfin = finc;
+		}
+		block = finc;
+		finc = block->next;
+		block->next = finq;
+		finq = block;
+	}
+	f = &finq->fin[finq->cnt];
+	finq->cnt++;
+	f->fn = fn;
+	f->ft = ft;
+	f->arg = p;
+	runtime_unlock(&finlock); 
+	return true;
+}
+
+// Sweep frees or collects finalizers for blocks not marked in the mark phase.
 // It clears the mark bits in preparation for the next GC round.
 static void
 sweep(void)
@@ -393,9 +718,17 @@
 	uintptr size;
 	byte *p;
 	MCache *c;
-	Finalizer *f;
+	byte *arena_start;
 
-	for(s = runtime_mheap.allspans; s != nil; s = s->allnext) {
+	arena_start = runtime_mheap.arena_start;
+
+	for(;;) {
+		s = work.spans;
+		if(s == nil)
+			break;
+		if(!runtime_casp(&work.spans, s, s->allnext))
+			continue;
+
 		if(s->state != MSpanInUse)
 			continue;
 
@@ -410,13 +743,15 @@
 			npages = runtime_class_to_allocnpages[cl];
 			n = (npages << PageShift) / size;
 		}
-	
-		// sweep through n objects of given size starting at p.
+
+		// Sweep through n objects of given size starting at p.
+		// This thread owns the span now, so it can manipulate
+		// the block bitmap without atomic operations.
 		for(; n > 0; n--, p += size) {
 			uintptr off, *bitp, shift, bits;
 
-			off = (uintptr*)p - (uintptr*)runtime_mheap.arena_start;
-			bitp = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
+			off = (uintptr*)p - (uintptr*)arena_start;
+			bitp = (uintptr*)arena_start - off/wordsPerBitmapWord - 1;
 			shift = off % wordsPerBitmapWord;
 			bits = *bitp>>shift;
 
@@ -424,20 +759,21 @@
 				continue;
 
 			if((bits & bitMarked) != 0) {
+				if(DebugMark) {
+					if(!(bits & bitSpecial))
+						runtime_printf("found spurious mark on %p\n", p);
+					*bitp &= ~(bitSpecial<<shift);
+				}
 				*bitp &= ~(bitMarked<<shift);
 				continue;
 			}
 
-			if((bits & bitSpecial) != 0) {
-				// Special means it has a finalizer or is being profiled.
-				f = runtime_getfinalizer(p, 1);
-				if(f != nil) {
-					f->arg = p;
-					f->next = finq;
-					finq = f;
+			// Special means it has a finalizer or is being profiled.
+			// In DebugMark mode, the bit has been coopted so
+			// we have to assume all blocks are special.
+			if(DebugMark || (bits & bitSpecial) != 0) {
+				if(handlespecial(p, size))
 					continue;
-				}
-				runtime_MProf_Free(p, size);
 			}
 
 			// Mark freed; restore block boundary bit.
@@ -464,6 +800,23 @@
 
 static pthread_mutex_t gcsema = PTHREAD_MUTEX_INITIALIZER;
 
+void
+runtime_gchelper(void)
+{
+	// Wait until main proc is ready for mark help.
+	runtime_lock(&work.markgate);
+	runtime_unlock(&work.markgate);
+	scanblock(nil, 0);
+
+	// Wait until main proc is ready for sweep help.
+	runtime_lock(&work.sweepgate);
+	runtime_unlock(&work.sweepgate);
+	sweep();
+
+	if(runtime_xadd(&work.ndone, +1) == work.nproc-1)
+		runtime_notewakeup(&work.alldone);
+}
+
 // Initialized from $GOGC.  GOGC=off means no gc.
 //
 // Next gc is after we've allocated an extra amount of
@@ -481,7 +834,7 @@
 	int64 t0, t1, t2, t3;
 	uint64 heap0, heap1, obj0, obj1;
 	char *p;
-	Finalizer *fp;
+	bool extra;
 
 	// The gc is turned off (via enablegc) until
 	// the bootstrap has completed.
@@ -502,10 +855,16 @@
 			gcpercent = -1;
 		else
 			gcpercent = runtime_atoi(p);
-		
+
 		p = runtime_getenv("GOGCTRACE");
 		if(p != nil)
 			gctrace = runtime_atoi(p);
+
+		runtime_initlock(&work.fmu);
+		runtime_initlock(&work.emu);
+		runtime_initlock(&work.markgate);
+		runtime_initlock(&work.sweepgate);
+		runtime_initlock(&work.Lock);
 	}
 	if(gcpercent < 0)
 		return;
@@ -522,20 +881,42 @@
 	nlookup = 0;
 	nsizelookup = 0;
 	naddrlookup = 0;
+	nhandoff = 0;
 
 	m->gcing = 1;
 	runtime_stoptheworld();
-	if(runtime_mheap.Lock.key != 0)
-		runtime_throw("runtime_mheap locked during gc");
 
 	__go_cachestats();
 	heap0 = mstats.heap_alloc;
 	obj0 = mstats.nmalloc - mstats.nfree;
 
-	mark();
+	runtime_lock(&work.markgate);
+	runtime_lock(&work.sweepgate);
+
+	extra = false;
+	work.nproc = 1;
+#if 0
+	if(runtime_gomaxprocs > 1 && runtime_ncpu > 1) {
+		runtime_noteclear(&work.alldone);
+		work.nproc += runtime_helpgc(&extra);
+	}
+#endif
+	work.nwait = 0;
+	work.ndone = 0;
+
+	runtime_unlock(&work.markgate);  // let the helpers in
+	mark(scanblock);
+	if(DebugMark)
+		mark(debug_scanblock);
 	t1 = runtime_nanotime();
+
+	work.spans = runtime_mheap.allspans;
+	runtime_unlock(&work.sweepgate);  // let the helpers in
 	sweep();
+	if(work.nproc > 1)
+		runtime_notesleep(&work.alldone);
 	t2 = runtime_nanotime();
+
 	__go_stealcache();
 	__go_cachestats();
 
@@ -553,21 +934,28 @@
 	mstats.numgc++;
 	if(mstats.debuggc)
 		runtime_printf("pause %llu\n", (unsigned long long)t3-t0);
-	
+
 	if(gctrace) {
-		runtime_printf("gc%d: %llu+%llu+%llu ms %llu -> %llu MB %llu -> %llu (%llu-%llu) objects %llu pointer lookups (%llu size, %llu addr)\n",
+		runtime_printf("gc%d: %llu+%llu+%llu ms %llu -> %llu MB %llu -> %llu (%llu-%llu) objects %llu pointer lookups (%llu size, %llu addr) %llu handoff\n",
 			mstats.numgc, (unsigned long long)(t1-t0)/1000000, (unsigned long long)(t2-t1)/1000000, (unsigned long long)(t3-t2)/1000000,
 			(unsigned long long)heap0>>20, (unsigned long long)heap1>>20, (unsigned long long)obj0, (unsigned long long)obj1,
 			(unsigned long long)mstats.nmalloc, (unsigned long long)mstats.nfree,
-			(unsigned long long)nlookup, (unsigned long long)nsizelookup, (unsigned long long)naddrlookup);
+			(unsigned long long)nlookup, (unsigned long long)nsizelookup, (unsigned long long)naddrlookup, (unsigned long long) nhandoff);
 	}
 
 	pthread_mutex_unlock(&gcsema);
-	runtime_starttheworld();
+
+	// If we could have used another helper proc, start one now,
+	// in the hope that it will be available next time.
+	// It would have been even better to start it before the collection,
+	// but doing so requires allocating memory, so it's tricky to
+	// coordinate.  This lazy approach works out in practice:
+	// we don't mind if the first couple gc rounds don't have quite
+	// the maximum number of procs.
+	runtime_starttheworld(extra);
 
 	// finqlock is still held.
-	fp = finq;
-	if(fp != nil) {
+	if(finq != nil) {
 		// kick off or wake up goroutine to run queued finalizers
 		if(!finstarted) {
 			__go_go(runfinq, nil);
@@ -601,37 +989,44 @@
 	__go_cachestats();
 	m->gcing = 0;
 	pthread_mutex_unlock(&gcsema);
-	runtime_starttheworld();
+	runtime_starttheworld(false);
 }
 
 static void
 runfinq(void* dummy)
 {
-	Finalizer *f, *next;
+	Finalizer *f;
+	FinBlock *fb, *next;
+	uint32 i;
 
 	USED(dummy);
 
 	for(;;) {
 		pthread_mutex_lock(&finqlock);
-		f = finq;
+		fb = finq;
 		finq = nil;
-		if(f == nil) {
+		if(fb == nil) {
 			fingwait = 1;
 			pthread_cond_wait(&finqcond, &finqlock);
 			pthread_mutex_unlock(&finqlock);
 			continue;
 		}
 		pthread_mutex_unlock(&finqlock);
-		for(; f; f=next) {
-			void *params[1];
+		for(; fb; fb=next) {
+			next = fb->next;
+			for(i=0; i<(uint32)fb->cnt; i++) {
+				void *params[1];
 
-			next = f->next;
-			params[0] = &f->arg;
-			reflect_call(f->ft, (void*)f->fn, 0, 0, params, nil);
-			f->fn = nil;
-			f->arg = nil;
-			f->next = nil;
-			runtime_free(f);
+				f = &fb->fin[i];
+				params[0] = &f->arg;
+				runtime_setblockspecial(f->arg, false);
+				reflect_call(f->ft, (void*)f->fn, 0, 0, params, nil);
+				f->fn = nil;
+				f->arg = nil;
+			}
+			fb->cnt = 0;
+			fb->next = finc;
+			finc = fb;
 		}
 		runtime_gc(1);	// trigger another gc to clean up the finalized objects, if possible
 	}
@@ -783,6 +1178,9 @@
 {
 	uintptr *b, off, shift;
 
+	if(DebugMark)
+		return true;
+
 	off = (uintptr*)v - (uintptr*)runtime_mheap.arena_start;
 	b = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
 	shift = off % wordsPerBitmapWord;
@@ -791,17 +1189,23 @@
 }
 
 void
-runtime_setblockspecial(void *v)
+runtime_setblockspecial(void *v, bool s)
 {
 	uintptr *b, off, shift, bits, obits;
 
+	if(DebugMark)
+		return;
+
 	off = (uintptr*)v - (uintptr*)runtime_mheap.arena_start;
 	b = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
 	shift = off % wordsPerBitmapWord;
 
 	for(;;) {
 		obits = *b;
-		bits = obits | (bitSpecial<<shift);
+		if(s)
+			bits = obits | (bitSpecial<<shift);
+		else
+			bits = obits & ~(bitSpecial<<shift);
 		if(runtime_singleproc) {
 			*b = bits;
 			break;
@@ -812,7 +1216,7 @@
 		}
 	}
 }
- 
+
 void
 runtime_MHeap_MapBits(MHeap *h)
 {
@@ -823,7 +1227,7 @@
 		bitmapChunk = 8192
 	};
 	uintptr n;
-	
+
 	n = (h->arena_used - h->arena_start) / wordsPerBitmapWord;
 	n = (n+bitmapChunk-1) & ~(bitmapChunk-1);
 	if(h->bitmap_mapped >= n)
diff -r c36211271569 libgo/runtime/mheap.c
--- a/libgo/runtime/mheap.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/mheap.c	Wed Oct 26 16:12:38 2011 -0700
@@ -13,6 +13,7 @@
 // and heapmap(i) == span for all s->start <= i < s->start+s->npages.
 
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 static MSpan *MHeap_AllocLocked(MHeap*, uintptr, int32);
@@ -102,6 +103,7 @@
 		runtime_throw("MHeap_AllocLocked - bad npages");
 	runtime_MSpanList_Remove(s);
 	s->state = MSpanInUse;
+	mstats.heap_idle -= s->npages<<PageShift;
 
 	if(s->npages > npage) {
 		// Trim extra and put it back in the heap.
@@ -277,6 +279,7 @@
 		// runtime_printf("MHeap_FreeLocked - span %p ptr %p state %d ref %d\n", s, s->start<<PageShift, s->state, s->ref);
 		runtime_throw("MHeap_FreeLocked - invalid free");
 	}
+	mstats.heap_idle += s->npages<<PageShift;
 	s->state = MSpanFree;
 	runtime_MSpanList_Remove(s);
 	sp = (uintptr*)(s->start<<PageShift);
diff -r c36211271569 libgo/runtime/mprof.goc
--- a/libgo/runtime/mprof.goc	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/mprof.goc	Wed Oct 26 16:12:38 2011 -0700
@@ -7,6 +7,7 @@
 
 package runtime
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 #include "defs.h"
 #include "go-type.h"
diff -r c36211271569 libgo/runtime/msize.c
--- a/libgo/runtime/msize.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/msize.c	Wed Oct 26 16:12:38 2011 -0700
@@ -26,6 +26,7 @@
 // TODO(rsc): Compute max waste for any given size.
 
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 int32 runtime_class_to_size[NumSizeClasses];
diff -r c36211271569 libgo/runtime/proc.c
--- a/libgo/runtime/proc.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/proc.c	Wed Oct 26 16:12:38 2011 -0700
@@ -3,6 +3,7 @@
 // license that can be found in the LICENSE file.
 
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"	/* so that acid generated from proc.c includes malloc data structures */
 
 typedef struct Sched Sched;
diff -r c36211271569 libgo/runtime/runtime.h
--- a/libgo/runtime/runtime.h	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/runtime.h	Wed Oct 26 16:12:38 2011 -0700
@@ -136,7 +136,7 @@
 int64	runtime_nanotime(void);
 
 void	runtime_stoptheworld(void);
-void	runtime_starttheworld(void);
+void	runtime_starttheworld(bool);
 void	__go_go(void (*pfn)(void*), void*);
 void	__go_gc_goroutine_init(void*);
 void	__go_enable_gc(void);
@@ -184,18 +184,21 @@
 MCache*	runtime_allocmcache(void);
 void	free(void *v);
 struct __go_func_type;
-void	runtime_addfinalizer(void*, void(*fn)(void*), const struct __go_func_type *);
-void	runtime_walkfintab(void (*fn)(void*), void (*scan)(byte *, int64));
+bool	runtime_addfinalizer(void*, void(*fn)(void*), const struct __go_func_type *);
 #define runtime_mmap mmap
 #define runtime_munmap(p, s) munmap((p), (s))
 #define runtime_cas(pval, old, new) __sync_bool_compare_and_swap (pval, old, new)
 #define runtime_casp(pval, old, new) __sync_bool_compare_and_swap (pval, old, new)
+#define runtime_xadd(p, v) __sync_add_and_fetch (p, v)
 
 void	runtime_sigprof(uint8 *pc, uint8 *sp, uint8 *lr);
 void	runtime_cpuprofinit(void);
 void	runtime_resetcpuprofiler(int32);
 void	runtime_setcpuprofilerate(void(*)(uintptr*, int32), int32);
 uint32	runtime_fastrand1(void);
+void	runtime_procyield(uint32);
+void	runtime_osyield(void);
+void	runtime_usleep(uint32);
 
 struct __go_func_type;
 void reflect_call(const struct __go_func_type *, const void *, _Bool, _Bool,
diff -r c36211271569 libgo/runtime/sigqueue.goc
--- a/libgo/runtime/sigqueue.goc	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/sigqueue.goc	Wed Oct 26 16:12:38 2011 -0700
@@ -39,6 +39,7 @@
 package runtime
 #include "config.h"
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 #include "defs.h"
 
diff -r c36211271569 libgo/runtime/thread.c
--- a/libgo/runtime/thread.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/thread.c	Wed Oct 26 16:12:38 2011 -0700
@@ -14,19 +14,6 @@
 		runtime_throw("sem_init failed");
 }
 
-static uint32
-runtime_xadd(uint32 volatile *val, int32 delta)
-{
-	uint32 oval, nval;
-
-	for(;;){
-		oval = *val;
-		nval = oval + delta;
-		if(runtime_cas(val, oval, nval))
-			return nval;
-	}
-}
-
 // noinline so that runtime_lock doesn't have to split the stack.
 static void runtime_lock_full(Lock *l) __attribute__ ((noinline));
 
diff -r c36211271569 libgo/runtime/yield.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgo/runtime/yield.c	Wed Oct 26 16:12:38 2011 -0700
@@ -0,0 +1,54 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#define _GNU_SOURCE
+
+#include "config.h"
+
+#include <stddef.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <pthread.h>
+#include <unistd.h>
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#include "runtime.h"
+
+/* Spin wait.  */
+
+void
+runtime_procyield (uint32 cnt)
+{
+  volatile uint32 i;
+
+  for (i = 0; i < cnt; ++i)
+    {
+#if defined (__i386__) || defined (__x86_64__)
+      __builtin_ia32_pause ();
+#endif
+    }
+}
+
+/* Ask the OS to reschedule this thread.  */
+
+void
+runtime_osyield (void)
+{
+  pthread_yield ();
+}
+
+/* Sleep for some number of microseconds.  */
+
+void
+runtime_usleep (uint32 us)
+{
+  struct timeval tv;
+
+  tv.tv_sec = us / 1000000;
+  tv.tv_usec = us % 1000000;
+  select (0, NULL, NULL, NULL, &tv);
+}
diff -r c36211271569 libgo/testsuite/gotest
--- a/libgo/testsuite/gotest	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/testsuite/gotest	Wed Oct 26 16:12:38 2011 -0700
@@ -331,6 +331,10 @@
 	pattern='Benchmark([^a-z].*)?'
 	benchmarks=$($NM -p -v _gotest_.o $xofile | egrep ' T .*\.'$pattern'$' | grep -v '\..*\..*\.' | sed 's/.* //' | sed 's/.*\.\(.*\.\)/\1/')
 
+	# examples are named ExampleFoo
+	pattern='Example([^a-z].*)?'
+	examples=$($NM -p -v _gotest_.o $xofile | egrep ' T .*\.'$pattern'$' | grep -v '\..*\..*\.' | sed 's/.* //' | sed 's/.*\.\(.*\.\)/\1/')
+
 	# package spec
 	echo 'package main'
 	echo
@@ -353,6 +357,7 @@
 		echo '	{"'$i'", '$j'},'
 	done
 	echo '}'
+
 	# benchmark array
 	# The comment makes the multiline declaration
 	# gofmt-safe even when there are no benchmarks.
@@ -363,6 +368,17 @@
 		echo '	{"'$i'", '$j'},'
 	done
 	echo '}'
+
+	# examples array
+	echo 'var examples = []testing.InternalExample{ //'
+	# This doesn't work because we don't pick up the output.
+	#for i in $examples
+	#do
+	#	j=$(localname $i)
+	#	echo '	{"'$i'", '$j', ""},'
+	#done
+	echo '}'
+
 	# body
 	echo \
 '
@@ -381,7 +397,7 @@
 }
 
 func main() {
-	testing.Main(matchString, tests, benchmarks)
+	testing.Main(matchString, tests, benchmarks, examples)
 }'
 }>_testmain.go
 

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2011-11-29 23:03 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-10-27 17:24 Go patch committed: Update Go library Uros Bizjak
2011-11-01  9:57 ` Uros Bizjak
  -- strict thread matches above, loose matches on Subject: below --
2011-11-30  4:05 Ian Lance Taylor
2011-10-27  3:07 Ian Lance Taylor
2011-10-27 14:46 ` Rainer Orth
2011-10-27 17:36   ` Ian Lance Taylor
2011-10-27 17:50     ` Rainer Orth
2011-10-31 23:06   ` Ian Lance Taylor
2011-10-31 17:57 ` Rainer Orth
2011-11-01  4:55   ` Ian Lance Taylor
2011-11-01  5:21   ` Ian Lance Taylor
     [not found] ` <4EB15B7E.4050006@ubuntu.com>
2011-11-02 16:21   ` Ian Lance Taylor
2011-11-02 17:11 ` Rainer Orth
2011-11-02 18:01   ` Ian Lance Taylor
2011-11-02 18:04     ` David Daney
2011-11-02 18:23       ` Ian Lance Taylor
2011-11-02 20:23         ` Joseph S. Myers
2011-11-02 20:24       ` Joseph S. Myers
2011-11-02 18:17     ` Rainer Orth

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).