[Pkg-golang-commits] [SCM] Packaging for Google Go branch, debian-sid, updated. debian/2%1.0.1-1-41-g75cafdb

Michael Stapelberg michael at stapelberg.de
Fri Apr 5 23:21:17 UTC 2013


The following commit has been merged in the debian-sid branch:
commit 6e7a55a2c0ab461fd1c8e68c3c7366b0afa4d4d4
Author: Michael Stapelberg <michael at stapelberg.de>
Date:   Fri Apr 5 18:22:38 2013 +0200

    Imported Upstream version 1.1~hg20130405

diff --git a/AUTHORS b/AUTHORS
index 78d149f..b7acdc6 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -18,6 +18,7 @@ Alex Brainman <alex.brainman at gmail.com>
 Alexander Orlov <alexander.orlov at loxal.net>
 Alexander Reece <awreece at gmail.com>
 Alexander Surma <surma at surmair.de>
+Alexei Sholik <alcosholik at gmail.com>
 Alexey Borzenkov <snaury at gmail.com>
 Amir Mohammad Saied <amir at gluegadget.com>
 Amrut Joshi <amrut.joshi at gmail.com>
@@ -30,6 +31,7 @@ Andrew Radev <andrey.radev at gmail.com>
 Andrew Skiba <skibaa at gmail.com>
 Andrew Wilkins <axwalk at gmail.com>
 Andrey Mirtchovski <mirtchovski at gmail.com>
+Andriy Lytvynov <lytvynov.a.v at gmail.com>
 Andy Davis <andy at bigandian.com>
 Anh Hai Trinh <anh.hai.trinh at gmail.com>
 Anschel Schaffer-Cohen <anschelsc at gmail.com>
@@ -87,6 +89,7 @@ Devon H. O'Dell <devon.odell at gmail.com>
 Dmitry Chestnykh <dchest at gmail.com>
 Dominik Honnef <dominik.honnef at gmail.com>
 Donovan Hide <donovanhide at gmail.com>
+Duncan Holm <mail at frou.org>
 Dustin Shields-Cloues <dcloues at gmail.com>
 Eden Li <eden.li at gmail.com>
 Egon Elbre <egonelbre at gmail.com>
@@ -240,6 +243,7 @@ Robert Daniel Kortschak <dan.kortschak at adelaide.edu.au>
 Robert Dinu <r at oktett.se>
 Robert Figueiredo <robfig at gmail.com>
 Robert Hencke <robert.hencke at gmail.com>
+Robert Obryk <robryk at gmail.com>
 Robin Eklind <r.eklind.87 at gmail.com>
 Rodrigo Moraes de Oliveira <rodrigo.moraes at gmail.com>
 Rodrigo Rafael Monti Kochenburger <divoxx at gmail.com>
@@ -298,3 +302,4 @@ Yusuke Kagiwada <block.rxckin.beats at gmail.com>
 Yuusei Kuwana <kuwana at kumama.org>
 Yuval Pavel Zholkover <paulzhol at gmail.com>
 Ziad Hatahet <hatahet at gmail.com>
+Zorion Arrizabalaga <zorionk at gmail.com>
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index 6afe1f0..7b8779b 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -46,6 +46,7 @@ Alexander Orlov <alexander.orlov at loxal.net>
 Alexander Reece <awreece at gmail.com>
 Alexander Surma <surma at surmair.de>
 Alexandru Moșoi <brtzsnr at gmail.com>
+Alexei Sholik <alcosholik at gmail.com>
 Alexey Borzenkov <snaury at gmail.com>
 Amir Mohammad Saied <amir at gluegadget.com>
 Amrut Joshi <amrut.joshi at gmail.com>
@@ -61,6 +62,7 @@ Andrew Radev <andrey.radev at gmail.com>
 Andrew Skiba <skibaa at gmail.com>
 Andrew Wilkins <axwalk at gmail.com>
 Andrey Mirtchovski <mirtchovski at gmail.com>
+Andriy Lytvynov <lytvynov.a.v at gmail.com>
 Andy Davis <andy at bigandian.com>
 Anh Hai Trinh <anh.hai.trinh at gmail.com>
 Anschel Schaffer-Cohen <anschelsc at gmail.com>
@@ -143,6 +145,7 @@ Dmitriy Vyukov <dvyukov at google.com>
 Dmitry Chestnykh <dchest at gmail.com>
 Dominik Honnef <dominik.honnef at gmail.com>
 Donovan Hide <donovanhide at gmail.com>
+Duncan Holm <mail at frou.org>
 Dustin Shields-Cloues <dcloues at gmail.com>
 Eden Li <eden.li at gmail.com>
 Egon Elbre <egonelbre at gmail.com>
@@ -197,6 +200,7 @@ James Gray <james at james4k.com>
 James Meneghello <rawrz0r at gmail.com>
 James P. Cooper <jamespcooper at gmail.com>
 James Toy <nil at opensesame.st>
+James Tucker <raggi at google.com>
 James Whitehead <jnwhiteh at gmail.com>
 Jamie Gennis <jgennis at google.com> <jgennis at gmail.com>
 Jan H. Hosang <jan.hosang at gmail.com>
@@ -349,6 +353,7 @@ Robert Dinu <r at oktett.se>
 Robert Figueiredo <robfig at gmail.com>
 Robert Griesemer <gri at golang.org>
 Robert Hencke <robert.hencke at gmail.com>
+Robert Obryk <robryk at gmail.com>
 Robin Eklind <r.eklind.87 at gmail.com>
 Rodrigo Moraes de Oliveira <rodrigo.moraes at gmail.com>
 Rodrigo Rafael Monti Kochenburger <divoxx at gmail.com>
@@ -421,3 +426,4 @@ Yuusei Kuwana <kuwana at kumama.org>
 Yuval Pavel Zholkover <paulzhol at gmail.com>
 Yves Junqueira <yves.junqueira at gmail.com>
 Ziad Hatahet <hatahet at gmail.com>
+Zorion Arrizabalaga <zorionk at gmail.com>
diff --git a/api/next.txt b/api/next.txt
index b45c225..2aaca2f 100644
--- a/api/next.txt
+++ b/api/next.txt
@@ -28,6 +28,7 @@ pkg bytes, func TrimPrefix([]uint8, []uint8) []uint8
 pkg bytes, func TrimSuffix([]uint8, []uint8) []uint8
 pkg bytes, method (*Buffer) Grow(int)
 pkg bytes, method (*Reader) WriteTo(io.Writer) (int64, error)
+pkg compress/gzip, method (*Writer) Flush() error
 pkg crypto/hmac, func Equal([]uint8, []uint8) bool
 pkg crypto/tls, const TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16
 pkg crypto/tls, const TLS_RSA_WITH_AES_256_CBC_SHA uint16
@@ -61,6 +62,8 @@ pkg crypto/x509, type PEMCipher int
 pkg crypto/x509, type SystemRootsError struct
 pkg crypto/x509, type VerifyOptions struct, KeyUsages []ExtKeyUsage
 pkg crypto/x509, var IncorrectPasswordError error
+pkg database/sql, method (*DB) Ping() error
+pkg database/sql, method (*DB) SetMaxIdleConns(int)
 pkg database/sql/driver, type Queryer interface { Query }
 pkg database/sql/driver, type Queryer interface, Query(string, []Value) (Rows, error)
 pkg debug/elf, method (*File) DynString(DynTag) ([]string, error)
@@ -89,6 +92,7 @@ pkg encoding/json, method (Number) String() string
 pkg encoding/json, type Number string
 pkg encoding/xml, func EscapeText(io.Writer, []uint8) error
 pkg encoding/xml, method (*Encoder) Indent(string, string)
+pkg encoding/xml, type Decoder struct, DefaultSpace string
 pkg go/ast, func NewCommentMap(*token.FileSet, Node, []*CommentGroup) CommentMap
 pkg go/ast, method (CommentMap) Comments() []*CommentGroup
 pkg go/ast, method (CommentMap) Filter(Node) CommentMap
@@ -96,14 +100,20 @@ pkg go/ast, method (CommentMap) String() string
 pkg go/ast, method (CommentMap) Update(Node, Node) Node
 pkg go/ast, type ChanType struct, Arrow token.Pos
 pkg go/ast, type CommentMap map[Node][]*CommentGroup
-pkg go/build, type Context struct, InstallTag string
+pkg go/build, type Context struct, InstallSuffix string
+pkg go/build, type Context struct, ReleaseTags []string
 pkg go/build, type Package struct, IgnoredGoFiles []string
 pkg go/build, type Package struct, SwigCXXFiles []string
 pkg go/build, type Package struct, SwigFiles []string
 pkg go/doc, type Example struct, EmptyOutput bool
 pkg go/doc, type Example struct, Order int
 pkg go/doc, type Example struct, Play *ast.File
-pkg go/doc, type Package struct, Notes map[string][]string
+pkg go/doc, type Note struct
+pkg go/doc, type Note struct, Body string
+pkg go/doc, type Note struct, End token.Pos
+pkg go/doc, type Note struct, Pos token.Pos
+pkg go/doc, type Note struct, UID string
+pkg go/doc, type Package struct, Notes map[string][]*Note
 pkg go/doc, var IllegalPrefixes []string
 pkg go/format, func Node(io.Writer, *token.FileSet, interface{}) error
 pkg go/format, func Source([]uint8) ([]uint8, error)
@@ -339,28 +349,24 @@ pkg math/big, method (*Int) UnmarshalJSON([]uint8) error
 pkg math/big, method (*Rat) Float64() (float64, bool)
 pkg math/big, method (*Rat) SetFloat64(float64) *Rat
 pkg mime/multipart, method (*Writer) SetBoundary(string) error
-pkg net, func Deadline(time.Time) DialOption
-pkg net, func DialOpt(string, ...DialOption) (Conn, error)
 pkg net, func ListenUnixgram(string, *UnixAddr) (*UnixConn, error)
-pkg net, func LocalAddress(Addr) DialOption
 pkg net, func LookupNS(string) ([]*NS, error)
-pkg net, func Network(string) DialOption
-pkg net, func Timeout(time.Duration) DialOption
+pkg net, method (*Dialer) Dial(string, string) (Conn, error)
 pkg net, method (*IPConn) ReadMsgIP([]uint8, []uint8) (int, int, int, *IPAddr, error)
 pkg net, method (*IPConn) WriteMsgIP([]uint8, []uint8, *IPAddr) (int, int, error)
 pkg net, method (*UDPConn) ReadMsgUDP([]uint8, []uint8) (int, int, int, *UDPAddr, error)
 pkg net, method (*UDPConn) WriteMsgUDP([]uint8, []uint8, *UDPAddr) (int, int, error)
 pkg net, method (*UnixConn) CloseRead() error
 pkg net, method (*UnixConn) CloseWrite() error
-pkg net, type DialOption interface, unexported methods
+pkg net, type Dialer struct
+pkg net, type Dialer struct, Deadline time.Time
+pkg net, type Dialer struct, LocalAddr Addr
+pkg net, type Dialer struct, Timeout time.Duration
 pkg net, type IPAddr struct, Zone string
-pkg net, type IPNet struct, Zone string
 pkg net, type NS struct
 pkg net, type NS struct, Host string
 pkg net, type TCPAddr struct, Zone string
 pkg net, type UDPAddr struct, Zone string
-pkg net, var TCP DialOption
-pkg net, var UDP DialOption
 pkg net/http, func ParseTime(string) (time.Time, error)
 pkg net/http, method (*Request) PostFormValue(string) string
 pkg net/http, method (*ServeMux) Handler(*Request) (Handler, string)
@@ -385,6 +391,7 @@ pkg net/smtp, method (*Client) Hello(string) error
 pkg net/textproto, func TrimBytes([]uint8) []uint8
 pkg net/textproto, func TrimString(string) string
 pkg os, method (FileMode) IsRegular() bool
+pkg os/signal, func Stop(chan<- os.Signal)
 pkg reflect, const SelectDefault SelectDir
 pkg reflect, const SelectRecv SelectDir
 pkg reflect, const SelectSend SelectDir
diff --git a/doc/articles/godoc_documenting_go_code.html b/doc/articles/godoc_documenting_go_code.html
index 18a3ee9..96ae745 100644
--- a/doc/articles/godoc_documenting_go_code.html
+++ b/doc/articles/godoc_documenting_go_code.html
@@ -91,10 +91,9 @@ known issue from the <a href="/pkg/bytes/#pkg-bugs"><code>bytes</code></a> packa
 </pre>
 
 <p>
-Godoc treats executable commands somewhat differently. Instead of inspecting the
-command source code, it looks for a Go source file belonging to the special
-package "documentation". The comment on the "package documentation" clause is
-used as the command's documentation. For example, see the
+Godoc treats executable commands in the same way. It looks for a comment on
+package main, which is sometimes put in a separate file called <code>doc.go</code>.
+For example, see the
 <a href="/cmd/godoc/">godoc documentation</a> and its corresponding
 <a href="/src/cmd/godoc/doc.go">doc.go</a> file.
 </p>
diff --git a/doc/articles/race_detector.html b/doc/articles/race_detector.html
index 400d96b..30458ef 100644
--- a/doc/articles/race_detector.html
+++ b/doc/articles/race_detector.html
@@ -6,7 +6,9 @@
 <h2 id="Introduction">Introduction</h2>
 
 <p>
-Data races are one of the most common and hardest to debug types of bugs in concurrent systems.  A data race occurs when two goroutines access the same variable concurrently and at least one of the accesses is a write.  See the <a href="/ref/mem/">The Go Memory Model</a> for details.
+Data races are among the most common and hardest to debug types of bugs in concurrent systems.
+A data race occurs when two goroutines access the same variable concurrently and at least one of the accesses is a write.
+See the <a href="/ref/mem/">The Go Memory Model</a> for details.
 </p>
 
 <p>
@@ -32,7 +34,8 @@ func main() {
 <h2 id="Usage">Usage</h2>
 
 <p>
-Fortunately, Go includes a built-in data race detector.  To use it, add the <code>-race</code> flag to the go command:
+To help diangose such bugs, Go includes a built-in data race detector.
+To use it, add the <code>-race</code> flag to the go command:
 </p>
 
 <pre>
@@ -45,7 +48,9 @@ $ go install -race mypkg // to install the package
 <h2 id="Report_Format">Report Format</h2>
 
 <p>
-When the race detector finds a data race in the program, it prints a report.  The report contains stack traces for conflicting accesses, as well as stacks where the involved goroutines were created.  For example:
+When the race detector finds a data race in the program, it prints a report.
+The report contains stack traces for conflicting accesses, as well as stacks where the involved goroutines were created.
+Here is an example:
 </p>
 
 <pre>
@@ -86,7 +91,8 @@ Goroutine 184 (running) created at:
 <h2 id="Options">Options</h2>
 
 <p>
-The <code>GORACE</code> environment variable sets race detector options.  The format is:
+The <code>GORACE</code> environment variable sets race detector options.
+The format is:
 </p>
 
 <pre>
@@ -100,7 +106,8 @@ The options are:
 <ul>
 <li>
 <code>log_path</code> (default <code>stderr</code>): The race detector writes
-its report to a file named log_path.pid.  The special names <code>stdout</code>
+its report to a file named <code>log_path.<em>pid</em></code>.
+The special names <code>stdout</code>
 and <code>stderr</code> cause reports to be written to standard output and
 standard error, respectively.
 </li>
@@ -117,8 +124,8 @@ from all reported file paths, to make reports more concise.
 
 <li>
 <code>history_size</code> (default <code>1</code>): The per-goroutine memory
-access history is <code>32K * 2**history_size elements</code>. Increasing this
-value can avoid a "failed to restore the stack" error in reports, but at the
+access history is <code>32K * 2**history_size elements</code>.
+Increasing this value can avoid a "failed to restore the stack" error in reports, at the
 cost of increased memory usage.
 </li>
 </ul>
@@ -134,9 +141,10 @@ $ GORACE="log_path=/tmp/race/report strip_path_prefix=/my/go/sources/" go test -
 <h2 id="Excluding_Tests">Excluding Tests</h2>
 
 <p>
-When you build with <code>-race</code> flag, go command defines additional
+When you build with <code>-race</code> flag, the <code>go</code> command defines additional
 <a href="/pkg/go/build/#Build_Constraints">build tag</a> <code>race</code>.
-You can use it to exclude some code/tests under the race detector. For example:
+You can use the tag to exclude some code and tests when running the race detector.
+Some examples:
 </p>
 
 <pre>
@@ -165,7 +173,8 @@ func TestBaz(t *testing.T) {
 <p>
 To start, run your tests using the race detector (<code>go test -race</code>).
 The race detector only finds races that happen at runtime, so it can't find
-races in code paths that are not executed. If your tests have incomplete coverage,
+races in code paths that are not executed.
+If your tests have incomplete coverage,
 you may find more races by running a binary built with <code>-race</code> under a realistic
 workload.
 </p>
@@ -194,9 +203,9 @@ func main() {
 
 <p>
 The variable <code>i</code> in the function literal is the same variable used by the loop, so
-the read in the goroutine races with the loop increment. (This program typically
-prints 55555, not 01234.) The program can be fixed by making a copy of the
-variable:
+the read in the goroutine races with the loop increment.
+(This program typically prints 55555, not 01234.)
+The program can be fixed by making a copy of the variable:
 </p>
 
 <pre>
@@ -246,7 +255,7 @@ func ParallelWrite(data []byte) chan error {
 </pre>
 
 <p>
-The fix is to introduce new variables in the goroutines (note <code>:=</code>):
+The fix is to introduce new variables in the goroutines (note the use of <code>:=</code>):
 </p>
 
 <pre>
@@ -260,8 +269,8 @@ The fix is to introduce new variables in the goroutines (note <code>:=</code>):
 <h3 id="Unprotected_global_variable">Unprotected global variable</h3>
 
 <p>
-If the following code is called from several goroutines, it leads to bad races on the <code>service</code> map.
-Concurrent reads and writes of a map are not safe:
+If the following code is called from several goroutines, it leads to races on the <code>service</code> map.
+Concurrent reads and writes of the same map are not safe:
 </p>
 
 <pre>
@@ -302,7 +311,8 @@ func LookupService(name string) net.Addr {
 <h3 id="Primitive_unprotected_variable">Primitive unprotected variable</h3>
 
 <p>
-Data races can happen on variables of primitive types as well (<code>bool</code>, <code>int</code>, <code>int64</code>, etc.), like in the following example:
+Data races can happen on variables of primitive types as well (<code>bool</code>, <code>int</code>, <code>int64</code>, etc.),
+as in this example:
 </p>
 
 <pre>
@@ -327,12 +337,16 @@ func (w *Watchdog) Start() {
 </pre>
 
 <p>
-Even such “innocent” data races can lead to hard to debug problems caused by (1) non-atomicity of the memory accesses, (2) interference with compiler optimizations and (3) processor memory access reordering issues.
+Even such "innocent" data races can lead to hard-to-debug problems caused by
+non-atomicity of the memory accesses,
+interference with compiler optimizations,
+or reordering issues accessing processor memory .
 </p>
 
 <p>
 A typical fix for this race is to use a channel or a mutex.
-To preserve the lock-free behavior, one can also use the <a href="/pkg/sync/atomic/"><code>sync/atomic</code></a> package.
+To preserve the lock-free behavior, one can also use the
+<a href="/pkg/sync/atomic/"><code>sync/atomic</code></a> package.
 </p>
 
 <pre>
diff --git a/doc/code.html b/doc/code.html
index 82b2118..2d63d4d 100644
--- a/doc/code.html
+++ b/doc/code.html
@@ -6,344 +6,381 @@
 
 <p>
 This document demonstrates the development of a simple Go package and
-introduces the <a href="/cmd/go/">go command</a>, the standard way to fetch,
+introduces the <a href="/cmd/go/">go tool</a>, the standard way to fetch,
 build, and install Go packages and commands.
 </p>
 
 <p>
-This content is also available as a <a href="http://www.youtube.com/watch?v=XCsL89YtqCs">screencast</a>.
+The <code>go</code> tool requires you to organize your code in a specific
+way. Please read this document carefully.
+It explains the simplest way to get up and running with your Go installation.
+</p>
+
+<p>
+A similar explanation is available as a
+<a href="http://www.youtube.com/watch?v=XCsL89YtqCs">screencast</a>.
 </p>
 
 
-<h2 id="GOPATH">Code organization</h2>
+<h2 id="Organization">Code organization</h2>
 
-<h3><code>GOPATH</code> and workspaces</h3>
+<h3 id="Workspaces">Workspaces</h3>
 
 <p>
-One of Go's design goals is to make writing software easier.  To that end, the
-<code>go</code> command doesn't use Makefiles or other configuration files to
-guide program construction. Instead, it uses the source code to find
-dependencies and determine build conditions. This means your source code and
-build scripts are always in sync; they are one and the same.
+The <code>go</code> tool is designed to work with open source code maintained
+in public repositories. Although you don't need to publish your code, the model
+for how the environment is set up works the same whether you do or not.
 </p>
 
 <p>
-The one thing you must do is set a <code>GOPATH</code> environment variable.
-<code>GOPATH</code> tells the <code>go</code> command (and other related tools)
-where to find and install the Go packages on your system.
+Go code must be kept inside a <i>workspace</i>.
+A workspace is a directory hierarchy with three directories at its root:
 </p>
 
+<ul>
+<li><code>src</code> contains Go source files organized into packages (one package per directory),
+<li><code>pkg</code> contains package objects, and
+<li><code>bin</code> contains executable commands.
+</ul>
+
 <p>
-<code>GOPATH</code> is a list of paths. It shares the syntax of your system's
-<code>PATH</code> environment variable. A typical <code>GOPATH</code> on
-a Unix system might look like this:
+The <code>go</code> tool builds source packages and installs the resulting
+binaries to the <code>pkg</code> and <code>bin</code> directories.
 </p>
 
-<pre>
-GOPATH=/home/user/ext:/home/user/mygo
-</pre>
-
 <p>
-(On a Windows system use semicolons as the path separator instead of colons.)
+The <code>src</code> subdirectory typically contains multiple version control
+repositories (such as for Git or Mercurial) that track the development of one
+or more source packages.
 </p>
 
 <p>
-Each path in the list (in this case <code>/home/user/ext</code> or
-<code>/home/user/mygo</code>) specifies the location of a <i>workspace</i>.
-A workspace contains Go source files and their associated package objects, and
-command executables. It has a prescribed structure of three subdirectories:
+To give you an idea of how a workspace looks in practice, here's an example:
 </p>
 
-<ul>
-<li><code>src</code> contains Go source files,
-<li><code>pkg</code> contains compiled package objects, and
-<li><code>bin</code> contains executable commands.
-</ul>
+<pre>
+bin/
+    streak                         # command executable
+    todo                           # command executable
+pkg/
+    linux_amd64/
+        code.google.com/p/goauth2/
+            oauth.a                # package object
+        github.com/nf/todo/
+            task.a                 # package object
+src/
+    code.google.com/p/goauth2/
+        .hg/                       # mercurial repository metadata
+        oauth/
+            oauth.go               # package source
+            oauth_test.go          # test source
+    github.com/nf/
+        streak/
+	    .git/                  # git repository metadata
+            oauth.go               # command source
+            streak.go              # command source
+        todo/
+	    .git/                  # git repository metadata
+            task/
+                task.go            # package source
+            todo.go                # command source
+</pre>
 
 <p>
-Subdirectories of the <code>src</code> directory hold independent packages, and
-all source files (<code>.go</code>, <code>.c</code>, <code>.h</code>, and
-<code>.s</code>) in each subdirectory are elements of that subdirectory's
-package.
+This workspace contains three repositories (<code>goauth2</code>,
+<code>streak</code>, and <code>todo</code>) comprising two commands
+(<code>streak</code> and <code>todo</code>) and two libraries
+(<code>oauth</code> and <code>task</code>).
 </p>
 
 <p>
-When building a program that imports the package "<code>widget</code>" the
-<code>go</code> command looks for <code>src/pkg/widget</code> inside the Go root,
-and then—if the package source isn't found there—it searches
-for <code>src/widget</code> inside each workspace in order.
+Commands and libraries are built from different kinds of source packages.
+We will discuss the distinction <a href="#PackageNames">later</a>.
 </p>
 
+
+<h3 id="GOPATH">The <code>GOPATH</code> environment variable</h3>
+
 <p>
-Multiple workspaces can offer some flexibility and convenience, but for now
-we'll concern ourselves with only a single workspace.
+The <code>GOPATH</code> environment variable specifies the location of your
+workspace. It is likely the only environment variable you'll need to set
+when developing Go code.
 </p>
 
 <p>
-Let's work through a simple example. First, create a <code>$HOME/mygo</code>
-directory and its <code>src</code> subdirectory:
+To get started, create a workspace directory and set <code>GOPATH</code>
+accordingly. Your workspace can be located wherever you like, but we'll use
+<code>$HOME/go</code> in this document. Note that this must <b>not</b> be the
+same path as your Go installation.
 </p>
 
 <pre>
-$ mkdir -p $HOME/mygo/src # create a place to put source code
+$ <b>mkdir $HOME/go</b>
+$ <b>export GOPATH=$HOME/go</b>
 </pre>
 
 <p>
-Next, set it as the <code>GOPATH</code>. You should also add the
-<code>bin</code> subdirectory to your <code>PATH</code> environment variable so
-that you can run the commands therein without specifying their full path.
-To do this, add the following lines to <code>$HOME/.profile</code> (or
-equivalent):
+For convenience, add the workspace's <code>bin</code> subdirectory
+to your <code>PATH</code>:
 </p>
 
 <pre>
-export GOPATH=$HOME/mygo
-export PATH=$PATH:$HOME/mygo/bin
+$ <b>export PATH=$PATH:$GOPATH/bin</b>
 </pre>
 
 
-<h3>Import paths</h3>
+<h3 id="PackagePaths">Package paths</h3>
 
 <p>
-The standard packages are given short import paths such as <code>"fmt"</code>
-and <code>"net/http"</code> for convenience. 
-For your own projects, it is important to choose a base import path that is
-unlikely to collide with future additions to the standard library or other
-external libraries.
+The packages from the standard library are given short paths such as
+<code>"fmt"</code> and <code>"net/http"</code>.
+For your own packages, you must choose a base path that is unlikely to
+collide with future additions to the standard library or other external
+libraries.
 </p>
 
 <p>
-The best way to choose an import path is to use the location of your version
-control repository.
-For instance, if your source repository is at <code>example.com</code> 
-or <code>code.google.com/p/example</code>, you should begin your package
-paths with that URL, as in "<code>example.com/foo/bar</code>" or
-"<code>code.google.com/p/example/foo/bar</code>".
-Using this convention, the <code>go</code> command can automatically check out and
-build the source code by its import path alone.
+If you keep your code in a source repository somewhere, then you should use the
+root of that source repository as your base path.
+For instance, if you have a <a href="https://github.com/">GitHub</a> account at
+<code>github.com/user</code>, that should be your base path.
 </p>
 
 <p>
-If you don't intend to install your code in this way, you should at
-least use a unique prefix like "<code>widgets/</code>", as in
-"<code>widgets/foo/bar</code>". A good rule is to use a prefix such as your
-company or project name, since it is unlikely to be used by another group.
+Note that you don't need to publish your code to a remote repository before you
+can build it. It's just a good habit to organize your code as if you will
+publish it someday. In practice you can choose any arbitrary path name,
+as long as it is unique to the standard library and greater Go ecosystem.
 </p>
 
 <p>
-We'll use <code>example/</code> as our base import path:
+We'll use <code>github.com/user</code> as our base path. Create a directory
+inside your workspace in which to keep source code:
 </p>
 
 <pre>
-$ mkdir -p $GOPATH/src/example
+$ <b>mkdir -p $GOPATH/src/github.com/user</b>
 </pre>
 
 
-<h3>Package names</h3>
+<h3 id="Command">Your first program</h3>
 
 <p>
-The first statement in a Go source file should be
+To compile and run a simple program, first choose a package path (we'll use
+<code>github.com/user/hello</code>) and create a corresponding package directory
+inside your workspace:
 </p>
 
 <pre>
-package <i>name</i>
+$ <b>mkdir $GOPATH/src/github.com/user/hello</b>
 </pre>
 
 <p>
-where <code><i>name</i></code> is the package's default name for imports.
-(All files in a package must use the same <code><i>name</i></code>.)
+Next, create a file named <code>hello.go</code> inside that directory,
+containing the following Go code.
 </p>
 
-<p>
-Go's convention is that the package name is the last element of the
-import path: the package imported as "<code>crypto/rot13</code>"
-should be named <code>rot13</code>.
-There is no requirement that package names be unique
-across all packages linked into a single binary,
-only that the import paths (their full file names) be unique.
-</p>
+<pre>
+package main
 
-<p>
-Create a new package under <code>example</code> called <code>newmath</code>:
-</p>
+import "fmt"
 
-<pre>
-$ cd $GOPATH/src/example
-$ mkdir newmath
+func main() {
+	fmt.Printf("Hello, world.\n")
+}
 </pre>
 
 <p>
-Then create a file named <code>$GOPATH/src/example/newmath/sqrt.go</code>
-containing the following Go code:
+Now you can build and install that program with the <code>go</code> tool:
 </p>
 
 <pre>
-// Package newmath is a trivial example package.
-package newmath
-
-// Sqrt returns an approximation to the square root of x.
-func Sqrt(x float64) float64 {
-        // This is a terrible implementation.
-        // Real code should import "math" and use math.Sqrt.
-        z := 0.0
-        for i := 0; i < 1000; i++ {
-                z -= (z*z - x) / (2 * x)
-        }
-        return z
-}
+$ <b>go install github.com/user/hello</b>
 </pre>
 
 <p>
-This package is imported by the path name of the directory it's in, starting
-after the <code>src</code> component:
+Note that you can run this command from anywhere on your system. The
+<code>go</code> tool finds the source code by looking for the
+<code>github.com/user/hello</code> package inside the workspace specified by
+<code>GOPATH</code>.
+</p>
+
+<p>
+You can also omit the package path if you run <code>go install</code> from the
+package directory:
 </p>
 
 <pre>
-import "example/newmath"
+$ <b>cd $GOPATH/src/github.com/user/hello</b>
+$ <b>go install</b>
 </pre>
 
 <p>
-See <a href="/doc/effective_go.html#names">Effective Go</a> to learn more about
-Go's naming conventions.
+This command builds the <code>hello</code> command, producing an executable
+binary. It then installs that binary to the workspace's <code>bin</code>
+directory as <code>hello</code> (or, under Windows, <code>hello.exe</code>).
+In our example, that will be <code>$GOPATH/bin/hello</code>, which is
+<code>$HOME/go/bin/hello</code>.
 </p>
 
-
-<h2>Building and installing</h2>
+<p>
+The <code>go</code> tool will only print output when an error occurs, so if
+these commands produce no output they have executed successfully.
+</p>
 
 <p>
-The <code>go</code> command comprises several subcommands, the most central being
-<code>install</code>. Running <code>go install <i>importpath</i></code> builds
-and installs a package and its dependencies.
+You can now run the program by typing its full path at the command line:
 </p>
 
+<pre>
+$ <b>$GOPATH/bin/hello</b>
+Hello, world.
+</pre>
+
 <p>
-To "install a package" means to write the package object or executable command
-to the <code>pkg</code> or <code>bin</code> subdirectory of the workspace in
-which the source resides.
+Or, as you have added <code>$GOPATH/bin</code> to your <code>PATH</code>,
+just type the binary name:
 </p>
 
-<h3>Building a package</h3>
+<pre>
+$ <b>hello</b>
+Hello, world.
+</pre>
 
 <p>
-To build and install the <code>newmath</code> package, type
+If you're using a source control system, now would be a good time to initialize
+a repository, add the files, and commit your first change. Again, this step is
+optional: you do not need to use source control to write Go code.
 </p>
 
 <pre>
-$ go install example/newmath
+$ <b>cd $GOPATH/src/github.com/user/hello</b>
+$ <b>git init</b>
+Initialized empty Git repository in /home/user/go/src/github.com/user/hello/.git/
+$ <b>git add hello.go</b>
+$ <b>git commit -m "initial commit"</b>
+[master (root-commit) 0b4507d] initial commit
+ 1 file changed, 1 insertion(+)
+  create mode 100644 hello.go
 </pre>
 
 <p>
-This command will produce no output if the package and its dependencies
-are built and installed correctly.
+Pushing the code to a remote repository is left as an exercise for the reader.
+</p>
+
+
+<h3 id="Library">Your first library</h3>
+
+<p>
+Let's write a library and use it from the <code>hello</code> program.
 </p>
 
 <p>
-As a convenience, the <code>go</code> command will assume the current directory
-if no import path is specified on the command line. This sequence of commands
-has the same effect as the one above:
+Again, the first step is to choose a package path (we'll use
+<code>github.com/user/newmath</code>) and create the package directory:
 </p>
 
 <pre>
-$ cd $GOPATH/src/example/newmath
-$ go install
+$ <b>mkdir $GOPATH/src/github.com/user/newmath</b>
 </pre>
 
 <p>
-The resulting workspace directory tree (assuming we're running Linux on a 64-bit
-system) looks like this:
+Next, create a file named <code>sqrt.go</code> in that directory with the
+following contents.
 </p>
 
 <pre>
-pkg/
-    linux_amd64/
-        example/
-            newmath.a  # package object
-src/
-    example/
-        newmath/
-            sqrt.go    # package source
-</pre>
-
+// Package newmath is a trivial example package.
+package newmath
 
-<h3>Building a command</h3>
+// Sqrt returns an approximation to the square root of x.
+func Sqrt(x float64) float64 {
+	z := 0.0
+	for i := 0; i < 1000; i++ {
+		z -= (z*z - x) / (2 * x)
+	}
+	return z
+}
+</pre>
 
 <p>
-The <code>go</code> command treats code belonging to <code>package main</code> as
-an executable command and installs the package binary to the
-<code>GOPATH</code>'s <code>bin</code> subdirectory.
+Now, test that the package compiles with <code>go build</code>:
 </p>
 
+<pre>
+$ <b>go build github.com/user/newmath</b>
+</pre>
+
 <p>
-Add a command named <code>hello</code> to the source tree.
-First create the <code>example/hello</code> directory:
+Or, if you are working in the package's source directory, just:
 </p>
 
 <pre>
-$ cd $GOPATH/src/example
-$ mkdir hello
+$ <b>go build</b>
 </pre>
 
 <p>
-Then create the file <code>$GOPATH/src/example/hello/hello.go</code>
-containing the following Go code.
+This won't produce an output file. To do that, you must use <code>go
+install</code>, which places the package object inside the <code>pkg</code>
+directory of the workspace.
+</p>
+
+<p>
+After confirming that the <code>newmath</code> package builds,
+modify your original <code>hello.go</code> (which is in
+<code>$GOPATH/src/github.com/user/hello</code>) to use it:
 </p>
 
 <pre>
-// Hello is a trivial example of a main package.
 package main
 
 import (
-        "example/newmath"
-        "fmt"
+	"fmt"
+
+	<b>"github.com/user/newmath"</b>
 )
 
 func main() {
-        fmt.Printf("Hello, world.  Sqrt(2) = %v\n", newmath.Sqrt(2))
+	fmt.Printf("Hello, world.  <b>Sqrt(2) = %v\n", newmath.Sqrt(2)</b>)
 }
 </pre>
 
 <p>
-Next, run <code>go install</code>, which builds and installs the binary to
-<code>$GOPATH/bin</code> (or <code>$GOBIN</code>, if set; to simplify
-presentation, this document assumes <code>GOBIN</code> is unset):
+Whenever the <code>go</code> tool installs a package or binary, it also
+installs whatever dependencies it has. So when you install the <code>hello</code>
+program
 </p>
 
 <pre>
-$ go install example/hello
+$ <b>go install github.com/user/hello</b>
 </pre>
 
 <p>
-To run the program, invoke it by name as you would any other command:
+the <code>newmath</code> package will be installed as well, automatically.
 </p>
 
-<pre>
-$ $GOPATH/bin/hello
-Hello, world.  Sqrt(2) = 1.414213562373095
-</pre>
-
 <p>
-If you added <code>$HOME/mygo/bin</code> to your <code>PATH</code>, you may omit
-the path to the executable:
+Running the new version of the program, you should see some numerical output:
 </p>
 
 <pre>
-$ hello
+$ <b>hello</b>
 Hello, world.  Sqrt(2) = 1.414213562373095
 </pre>
 
 <p>
-The workspace directory tree now looks like this:
+After the steps above, your workspace should look like this:
 </p>
 
 <pre>
 bin/
     hello              # command executable
 pkg/
-    linux_amd64/ 
-        example/
+    linux_amd64/       # this will reflect your OS and architecture
+        github.com/user/
             newmath.a  # package object
 src/
-    example/
+    github.com/user/
         hello/
             hello.go   # command source
         newmath/
@@ -351,13 +388,55 @@ src/
 </pre>
 
 <p>
-The <code>go</code> command also provides a <code>build</code> command, which is
-like <code>install</code> except it builds all objects in a temporary directory
-and does not install them under <code>pkg</code> or <code>bin</code>.
-When building a command an executable named after the last element of the
-import path is written to the current directory. When building a package, 
-<code>go build</code> serves merely to test that the package and its
-dependencies can be built. (The resulting package object is thrown away.)
+Note that <code>go install</code> placed the <code>newmath.a</code> object in a
+directory inside <code>pkg/linux_amd64</code> that mirrors its source
+directory.
+This is so that future invocations of the <code>go</code> tool can find the
+package object and avoid recompiling the package unnecessarily.
+The <code>linux_amd64</code> part is there to aid in cross-compilation,
+and will reflect the operating system and architecture of your system.
+</p>
+
+<p>
+Go command executables are statically linked; the package objects need not
+be present to run Go programs.
+</p>
+
+
+<h3 id="PackageNames">Package names</h3>
+
+<p>
+The first statement in a Go source file must be
+</p>
+
+<pre>
+package <i>name</i>
+</pre>
+
+<p>
+where <code><i>name</i></code> is the package's default name for imports.
+(All files in a package must use the same <code><i>name</i></code>.)
+</p>
+
+<p>
+Go's convention is that the package name is the last element of the
+import path: the package imported as "<code>crypto/rot13</code>"
+should be named <code>rot13</code>.
+</p>
+
+<p>
+Executable commands must always use <code>package main</code>.
+</p>
+
+<p>
+There is no requirement that package names be unique
+across all packages linked into a single binary,
+only that the import paths (their full file names) be unique.
+</p>
+
+<p>
+See <a href="/doc/effective_go.html#names">Effective Go</a> to learn more about
+Go's naming conventions.
 </p>
 
 
@@ -379,8 +458,8 @@ if the function calls a failure function such as <code>t.Error</code> or
 
 <p>
 Add a test to the <code>newmath</code> package by creating the file
-<code>$GOPATH/src/example/newmath/sqrt_test.go</code> containing the following
-Go code.
+<code>$GOPATH/src/github.com/user/newmath/sqrt_test.go</code> containing the
+following Go code.
 </p>
 
 <pre>
@@ -397,12 +476,22 @@ func TestSqrt(t *testing.T) {
 </pre>
 
 <p>
-Now run the test with <code>go test</code>:
+Then run the test with <code>go test</code>:
+</p>
+
+<pre>
+$ <b>go test github.com/user/newmath</b>
+ok  	github.com/user/newmath 0.165s
+</pre>
+
+<p>
+As always, if you are running the <code>go</code> tool from the package
+directory, you can omit the package path:
 </p>
 
 <pre>
-$ go test example/newmath
-ok  	example/newmath 0.165s
+$ <b>go test</b>
+ok  	github.com/user/newmath 0.165s
 </pre>
 
 <p>
@@ -415,7 +504,7 @@ Run <code><a href="/cmd/go/#hdr-Test_packages">go help test</a></code> and see t
 
 <p>
 An import path can describe how to obtain the package source code using a
-revision control system such as Git or Mercurial. The <code>go</code> command uses
+revision control system such as Git or Mercurial. The <code>go</code> tool uses
 this property to automatically fetch packages from remote repositories.
 For instance, the examples described in this document are also kept in a
 Mercurial repository hosted at Google Code,
@@ -425,8 +514,8 @@ If you include the repository URL in the package's import path,
 </p>
 
 <pre>
-$ go get code.google.com/p/go.example/hello
-$ $GOPATH/bin/hello
+$ <b>go get code.google.com/p/go.example/hello</b>
+$ <b>$GOPATH/bin/hello</b>
 Hello, world.  Sqrt(2) = 1.414213562373095
 </pre>
 
@@ -446,10 +535,10 @@ tree should now now look like this:
 bin/
     hello                 # command executable
 pkg/
-    linux_amd64/ 
+    linux_amd64/
         code.google.com/p/go.example/
             newmath.a     # package object
-        example/
+        github.com/user/
             newmath.a     # package object
 src/
     code.google.com/p/go.example/
@@ -458,7 +547,7 @@ src/
         newmath/
             sqrt.go       # package source
             sqrt_test.go  # test source
-    example/
+    github.com/user/
         hello/
             hello.go      # command source
         newmath/
@@ -480,12 +569,13 @@ import "code.google.com/p/go.example/newmath"
 <p>
 This convention is the easiest way to make your Go packages available for
 others to use.
-The <a href="http://code.google.com/p/go-wiki/wiki/Projects">Go Community Wiki</a>
-has a list of external Go projects including programs and libraries.
+The <a href="http://code.google.com/p/go-wiki/wiki/Projects">Go Wiki</a>
+and <a href="http://godoc.org/">godoc.org</a>
+provide lists of external Go projects.
 </p>
 
 <p>
-For more information on using remote repositories with the <code>go</code> command, see
+For more information on using remote repositories with the <code>go</code> tool, see
 <code><a href="/cmd/go/#hdr-Remote_import_path_syntax">go help remote</a></code>.
 </p>
 
diff --git a/doc/codewalk/markov.xml b/doc/codewalk/markov.xml
index 7f12818..76c448a 100644
--- a/doc/codewalk/markov.xml
+++ b/doc/codewalk/markov.xml
@@ -181,7 +181,7 @@ p == Prefix{"am", "not"}</pre>
 	one index to the left (if you consider zero as the leftmost index).
 	<pre>
 p := Prefix{"I", "am"}
-copy(p, p[:1])
+copy(p, p[1:])
 // p == Prefix{"am", "am"}</pre>
 	We then assign the provided <code>word</code> to the last index
 	of the slice:
diff --git a/doc/effective_go.html b/doc/effective_go.html
index decca34..a1e13c0 100644
--- a/doc/effective_go.html
+++ b/doc/effective_go.html
@@ -2466,7 +2466,7 @@ only to have them be needed again later.
 The blank identifier provides a workaround.
 </p>
 <p>
-This half-written program is has two unused imports
+This half-written program has two unused imports
 (<code>fmt</code> and <code>io</code>)
 and an unused variable (<code>fd</code>),
 so it will not compile, but it would be nice to see if the
diff --git a/doc/go1.1.html b/doc/go1.1.html
index f1d490f..fac9229 100644
--- a/doc/go1.1.html
+++ b/doc/go1.1.html
@@ -6,9 +6,41 @@
 
 <h2 id="introduction">Introduction to Go 1.1</h2>
 
-TODO
- - overview
- - link back to Go 1 and also Go 1 Compatibility docs.
+<p>
+The release of <a href="/doc/go1.html">Go version 1</a> (Go 1 or Go 1.0 for short)
+in March of 2012 introduced a new period
+of stability in the Go language and libraries.
+That stability has helped nourish a growing community of Go users
+and systems around the world.
+Several "point" releases since
+then—1.0.1, 1.0.2, and 1.0.3—have been issued.
+These point releases fixed known bugs but made
+no non-critical changes to the implementation.
+</p>
+
+<p>
+This new release, Go 1.1, keeps the <a href="/doc/go1compat.html">promise
+of compatibility</a> but adds a couple of significant
+(backwards-compatible, of course) language changes, has a long list
+of (again, compatible) library changes, and
+includes major work on the implementation of the compilers,
+libraries, and run-time.
+The focus is on performance.
+Benchmarking is an inexact science at best, but we see significant,
+sometimes dramatic speedups for many of our test programs.
+We trust that many of our users' programs will also see improvements
+just by updating their Go installation and recompiling.
+</p>
+
+<p>
+This document summarizes the changes between Go 1 and Go 1.1.
+Very little if any code will need modification to run with Go 1.1,
+although a couple of rare error cases surface with this release
+and need to be addressed if they arise.
+Details appear below; see the discussion of
+<a href="#int">64-bit ints</a> and <a href="#unicode_literals">Unicode literals</a>
+in particular.
+</p>
 
 <h2 id="language">Changes to the language</h2>
 
@@ -62,7 +94,7 @@ a function literal closing over <code>w</code>:
 
 <pre>
 func (p []byte) (n int, err error) {
-	return w.Write(n, err)
+	return w.Write(p)
 }
 </pre>
 
@@ -75,7 +107,7 @@ is equivalent to a function with an extra first argument, a receiver of type
 
 <pre>
 func (w *bufio.Writer, p []byte) (n int, err error) {
-	return w.Write(n, err)
+	return w.Write(p)
 }
 </pre>
 
@@ -120,6 +152,17 @@ Such code can be identified by <code>go vet</code>.
 
 <h2 id="impl">Changes to the implementations and tools</h2>
 
+<h3 id="gccgo">Status of gccgo</h3>
+
+<p>
+The GCC release schedule does not coincide with the Go release schedule, so some skew is inevitable in
+<code>gccgo</code>'s releases.
+The 4.8.0 version of GCC shipped in March, 2013 and includes a nearly-Go 1.1 version of <code>gccgo</code>.
+Its library is a little behind the release, but the biggest difference is that method values are not implemented.
+Sometime around May 2013, we expect 4.8.1 of GCC to ship with a <code>gccgo</code>
+providing a complete Go 1.1 implementaiton.
+</p>
+
 <h3 id="gc_flag">Command-line flag parsing</h3>
 
 <p>
@@ -169,6 +212,24 @@ would instead say:
 i := int(int32(x))
 </pre>
 
+<h3 id="heap">Heap size on 64-bit architectures</h3>
+
+<p>
+On 64-bit architectures only, the maximum heap size has been enlarged substantially,
+from a few gigabytes to several tens of gigabytes.
+(The exact details depend on the system and may change.)
+</p>
+
+<p>
+On 32-bit architectures, the heap size has not changed.
+</p>
+
+<p>
+<em>Updating</em>:
+This change should have no effect on existing programs beyond allowing them
+to run with larger heaps.
+</p>
+
 <h3 id="unicode">Unicode</h3>
 
 <p>
@@ -224,6 +285,19 @@ Programs that depend on the old behavior should be modified to avoid the issue.
 The byte-order-mark change is strictly backward-compatible.
 </p>
 
+<h3 id="race">Race detector</h3>
+
+<p>
+A major addition to the tools is a <em>race detector</em>, a way to find
+bugs in programs caused by problems like concurrent changes to the same variable.
+This new facility is built into the <code>go</code> tool.
+For now, it is only available on Linux, Mac OS X, and Windows systems with
+64-bit x86 processors.
+To enable it, set the <code>-race</code> flag when building or testing your program 
+(for instance, <code>go test -race</code>).
+The race detector is documented in <a href="/doc/articles/race_detector.html">a separate article</a>.
+</p>
+
 <h3 id="gc_asm">The gc assemblers</h3>
 
 <p>
@@ -277,7 +351,7 @@ when <code>$GOPATH</code> and <code>$GOROOT</code> are set to the same value.
 
 <pre>
 $ GOPATH=$GOROOT go get code.google.com/p/foo/quxx
-warning: GOPATH set to GOROOT (/home/User/go) has no effect
+warning: GOPATH set to GOROOT (/home/you/go) has no effect
 package code.google.com/p/foo/quxx: cannot download, $GOPATH must not be set to $GOROOT. For more details see: go help gopath
 </pre>
 
@@ -320,17 +394,69 @@ To update pre-Go 1 code to Go 1.1, use a Go 1.0 tool chain
 to convert the code to Go 1.0 first.
 </p>
 
+<h3 id="gorun">Changes to the go run command</h3>
+
+<p>
+The <code>go run</code> command now runs all files in the current working
+directory if no file arguments are listed. Also, the <code>go run</code>
+command now returns an error if test files are provided on the command line. In
+this sense, "<code>go run</code>" replaces "<code>go run *.go</code>".
+</p>
+
+<h3 id="platforms">Additional platforms</h3>
+
+<p>
+The Go 1.1 tool chain adds experimental support for <code>freebsd/arm</code>,
+<code>netbsd/386</code>, <code>netbsd/amd64</code>, <code>netbsd/arm</code>, 
+<code>openbsd/386</code> and <code>openbsd/amd64</code> platforms.
+</p>
+
+<p>
+An ARMv6 or later processor is required for <code>freebsd/arm</code> or
+<code>netbsd/arm</code>.
+</p>
+
+<p>
+Go 1.1 adds experimental support for <code>cgo</code> on <code>linux/arm</code>.
+</p>
+
+<h3 id="crosscompile">Cross compilation</h3>
+
+<p>
+When cross-compiling, the <code>go</code> tool will disable <code>cgo</code>
+support by default.
+</p>
+
+<p>
+To explicitly enable <code>cgo</code>, set <code>CGO_ENABLED=1</code>.
+</p>
+
 <h2 id="performance">Performance</h2>
 
 <p>
-TODO introduction
+The performance of code compiled with the Go 1.1 gc tool suite should be noticeably
+better for most Go programs.
+Typical improvements relative to Go 1.0 seem to be about 30%-40%, sometimes
+much more, but occasionally less or even non-existent.
+There are too many small performance-driven tweaks through the tools and libraries
+to list them all here, but the following major changes are worth noting:
 </p>
 
 <ul>
-<li>TODO better code generation (inlining, ...?)</li>
-<li>TODO parallel gc</li>
-<li>TODO more precise gc</li>
-<li>TODO networking is more efficient (known to runtime)</li>
+<li>The gc compilers generate better code in many cases, most noticeably for
+floating point on the 32-bit Intel architecture.</li>
+<li>The gc compilers do more in-lining, including for some operations
+in the run-time such as <a href="/pkg/builtin/#append"><code>append</code></a>
+and interface conversions.</li>
+<li>There is a new implementation of Go maps with significant reduction in
+memory footprint and CPU time.</li>
+<li>The garbage collector has been made more parallel, which can reduce
+latencies for programs running on multiple CPUs.</li>
+<li>The garbage collector is also more precise, which costs a small amount of
+CPU time but can reduce the size of the heap significantly, especially
+on 32-bit architectures.</li>
+<li>Due to tighter coupling of the run-time and network libraries, fewer
+context switches are required on network operations.</li>
 </ul>
 
 <h2 id="library">Changes to the standard library</h2>
@@ -405,6 +531,26 @@ and
 methods.
 </p>
 
+<p>
+The data structures
+<a href="/pkg/net/#IPAddr"><code>IPAddr</code></a>,
+<a href="/pkg/net/#TCPAddr"><code>TCPAddr</code></a>, and
+<a href="/pkg/net/#UDPAddr"><code>UDPAddr</code></a>
+add a new string field called <code>Zone</code>.
+Code using untagged composite literals (e.g. <code>net.TCPAddr{ip, port}</code>)
+instead of tagged literals (<code>net.TCPAddr{IP: ip, Port: port}</code>)
+will break due to the new field.
+The Go 1 compatibility rules allow this change: client code must use tagged literals to avoid such breakages.
+</p>
+
+<p>
+<em>Updating</em>:
+To correct breakage caused by the new struct field,
+<code>go fix</code> will rewrite code to add tags for these types.
+More generally, <code>go vet</code> will identify composite literals that
+should be revised to use field tags.
+</p>
+
 <h3 id="reflect">reflect</h3>
 
 <p>
@@ -448,7 +594,7 @@ and
 <a href="/pkg/reflect/#SliceOf"><code>SliceOf</code></a>
 construct new
 <a href="/pkg/reflect/#Type"><code>Types</code></a>
-from existing types, for example to construct a the type <code>[]T</code> given
+from existing types, for example to construct the type <code>[]T</code> given
 only <code>T</code>.
 </p>
 
@@ -554,6 +700,14 @@ so it implements the
 </li>
 
 <li>
+The <a href="/pkg/compress/gzip/"><code>compress/gzip</code></a> package has
+a new <a href="/pkg/compress/gzip/#Writer.Flush"><code>Flush</code></a>
+method for its
+<a href="/pkg/compress/gzip/#Writer"><code>Writer</code></a>
+type that flushes its underlying <code>flate.Writer</code>.
+</li>
+
+<li>
 The <a href="/pkg/crypto/hmac/"><code>crypto/hmac</code></a> package has a new function,
 <a href="/pkg/crypto/hmac/#Equal"><code>Equal</code></a>, to compare two MACs.
 </li>
@@ -567,7 +721,7 @@ and a new function
 </li>
 
 <li>
-The <a href="/pkg/database/sql/"><code>database/sql/</code></a> package
+The <a href="/pkg/database/sql/"><code>database/sql</code></a> package
 has a new 
 <a href="/pkg/database/sql/#DB.Ping"><code>Ping</code></a>
 method for its
@@ -588,7 +742,7 @@ may implement to improve performance.
 The <a href="/pkg/encoding/json/"><code>encoding/json</code></a> package's
 <a href="/pkg/encoding/json/#Decoder"><code>Decoder</code></a>
 has a new method
-<a href="/pkg/encoding/json/#Decoder.Reader"><code>Reader</code></a>
+<a href="/pkg/encoding/json/#Decoder.Buffered"><code>Buffered</code></a>
 to provide access to the remaining data in its buffer,
 as well as a new method
 <a href="/pkg/encoding/json/#Decoder.UseNumber"><code>UseNumber</code></a>
@@ -598,7 +752,7 @@ a string, rather than a float64.
 </li>
 
 <li>
-The <a href="/pkg/encoding/xml/"><code>endoding/xml</code></a> package
+The <a href="/pkg/encoding/xml/"><code>encoding/xml</code></a> package
 has a new function,
 <a href="/pkg/encoding/xml/#EscapeText"><code>EscapeText</code></a>,
 which writes escaped XML output,
@@ -635,12 +789,17 @@ to format arbitrary Go source code.
 
 <li>
 The undocumented and only partially implemented "noescape" feature of the
-<a href="/pkg/html/template/">html/template</a>
+<a href="/pkg/html/template/"><code>html/template</code></a>
 package has been removed; programs that depend on it will break.
 </li>
 
 <li>
-The <a href="/pkg/io/">io</a> package now exports the
+The <a href="/pkg/image/jpeg/"><code>image/jpeg</code></a> package now
+reads progressive JPEG files and handles a few more subsampling configurations.
+</li>
+
+<li>
+The <a href="/pkg/io/"><code>io</code></a> package now exports the
 <a href="/pkg/io/#ByteWriter"><code>io.ByteWriter</code></a> interface to capture the common
 functionality of writing a byte at a time.
 </li>
@@ -683,29 +842,99 @@ to define the boundary separator used to package the output.
 <li>
 The
 <a href="/pkg/net/"><code>net</code></a> package's
-<a href="/pkg/net/#ListenUnixgram"><code>net/ListenUnixgram</code></a>
+<a href="/pkg/net/#ListenUnixgram"><code>ListenUnixgram</code></a>
 function has changed return types: it now returns a
-<a href="/pkg/net/#UnixConn"><code>net/UnixConn</code></a>
+<a href="/pkg/net/#UnixConn"><code>UnixConn</code></a>
 rather than a
-<a href="/pkg/net/#UDPConn"><code>net/UDPConn</code></a>, which was
+<a href="/pkg/net/#UDPConn"><code>UDPConn</code></a>, which was
 clearly a mistake in Go 1.0.
 Since this API change fixes a bug, it is permitted by the Go 1 compatibility rules.
 </li>
 
 <li>
-The new <a href="/pkg/net/http/cookiejar/">net/http/cookiejar</a> package provides the basics for managing HTTP cookies.
+The <a href="/pkg/net/"><code>net</code></a> package includes a new type,
+<a href="/pkg/net/#Dialer"><code>Dialer</code></a>, to supply options to
+<a href="/pkg/net/#Dialer.Dial"><code>Dial</code></a>.
 </li>
 
-<li> TODO: 
-<code>net/http</code>: ParseTime, CloseNotifier, Request.PostFormValue, ServeMux.Handler, Transport.CancelRequest
+<li>
+The <a href="/pkg/net/"><code>net</code></a> package adds support for
+link-local IPv6 addresses with zone qualifiers, such as <code>fe80::1%lo0</code>.
+The address structures <a href="/pkg/net/#IPAddr"><code>IPAddr</code></a>,
+<a href="/pkg/net/#UDPAddr"><code>UDPAddr</code></a>, and
+<a href="/pkg/net/#TCPAddr"><code>TCPAddr</code></a>
+record the zone in a new field, and functions that expect string forms of these addresses, such as
+<a href="/pkg/net/#Dial"><code>Dial</code></a>,
+<a href="/pkg/net/#ResolveIPAddr"><code>ResolveIPAddr</code></a>,
+<a href="/pkg/net/#ResolveUDPAddr"><code>ResolveUDPAddr</code></a>, and
+<a href="/pkg/net/#ResolveTCPAddr"><code>ResolveTCPAddr</code></a>,
+now accept the zone-qualified form.
 </li>
 
-<li> TODO: 
-<code>net/mail</code>: ParseAddress, ParseAddressList
+<li>
+The <a href="/pkg/net/"><code>net</code></a> package adds
+<a href="/pkg/net/#LookupNS"><code>LookupNS</code></a> to its suite of resolving functions.
+<code>LookupNS</code> returns the <a href="/pkg/net/#NS">NS records</a> for a host name.
 </li>
 
-<li> TODO: 
-<code>net/smtp</code>: Client.Hello
+<li>
+The <a href="/pkg/net/"><code>net</code></a> package adds protocol-specific 
+packet reading and writing methods to
+<a href="/pkg/net/#IPConn"><code>IPConn</code></a>
+(<a href="/pkg/net/#IPConn.ReadMsgIP"><code>ReadMsgIP</code></a>
+and <a href="/pkg/net/#IPConn.WriteMsgIP"><code>WriteMsgIP</code></a>) and 
+<a href="/pkg/net/#UDPConn"><code>UDPConn</code></a>
+(<a href="/pkg/net/#UDPConn.ReadMsgUDP"><code>ReadMsgUDP</code></a> and
+<a href="/pkg/net/#UDPConn.WriteMsgUDP"><code>WriteMsgUDP</code></a>).
+These are specialized versions of <a href="/pkg/net/#PacketConn"><code>PacketConn</code></a>'s
+<code>ReadFrom</code> and <code>WriteTo</code> methods that provide access to out-of-band data associated
+with the packets.
+ </li>
+ 
+ <li>
+The <a href="/pkg/net/"><code>net</code></a> package adds methods to
+<a href="/pkg/net/#UnixConn"><code>UnixConn</code></a> to allow closing half of the connection 
+(<a href="/pkg/net/#UnixConn.CloseRead"><code>CloseRead</code></a> and
+<a href="/pkg/net/#UnixConn.CloseWrite"><code>CloseWrite</code></a>),
+matching the existing methods of <a href="/pkg/net/#TCPConn"><code>TCPConn</code></a>.
+</li>
+ 
+<li>
+The <a href="/pkg/net/http/"><code>net/http</code></a> package includes several new additions.
+<a href="/pkg/net/http/#ParseTime"><code>ParseTime</code></a> parses a time string, trying
+several common HTTP time formats.
+The <a href="/pkg/net/http/#Request.PostFormValue">PostFormValue</a> method of
+<a href="/pkg/net/http/#Request"><code>Request</code></a> is like
+<a href="/pkg/net/http/#Request.FormValue"><code>FormValue</code></a> but ignores URL parameters.
+The <a href="/pkg/net/http/#CloseNotifier"><code>CloseNotifier</code></a> interface provides a mechanism
+for a server handler to discover when a client has disconnected.
+The <code>ServeMux</code> type now has a
+<a href="/pkg/net/http/#ServeMux.Handler"><code>Handler</code></a> method to access a path's
+<code>Handler</code> without executing it.
+The <code>Transport</code> can now cancel an in-flight request with
+<a href="/pkg/net/http/#Transport.CancelRequest"><code>CancelRequest</code></a>.
+Finally, the Transport is now more aggressive at closing TCP connections when
+a <a href="/pkg/net/http/#Response"><code>Response.Body</code></a> is closed before
+being fully consumed.
+</li>
+
+<li>
+The new <a href="/pkg/net/http/cookiejar/"><code>net/http/cookiejar</code></a> package provides the basics for managing HTTP cookies.
+</li>
+
+<li>
+The <a href="/pkg/net/mail/"><code>net/mail</code></a> package has two new functions,
+<a href="/pkg/net/mail/#ParseAddress"><code>ParseAddress</code></a> and
+<a href="/pkg/net/mail/#ParseAddressList"><code>ParseAddressList</code></a>,
+to parse RFC 5322-formatted mail addresses into
+<a href="/pkg/net/mail/#Address"><code>Address</code></a> structures.
+</li>
+
+<li>
+The <a href="/pkg/net/smtp/"><code>net/smtp</code></a> package's
+<a href="/pkg/net/smtp/#Client"><code>Client</code></a> type has a new method,
+<a href="/pkg/net/smtp/#Client.Hello"><code>Hello</code></a>,
+which transmits a <code>HELO</code> or <code>EHLO</code> message to the server.
 </li>
 
 <li>
@@ -716,17 +945,14 @@ has two new functions,
 which do ASCII-only trimming of leading and trailing spaces.
 </li>
 
-<li> TODO:
-<code>net</code>: DialOption, DialOpt, ListenUnixgram, LookupNS, IPConn.ReadMsgIP, IPConn.WriteMsgIP, UDPConn.ReadMsgUDP, UDPConn.WriteMsgUDP, UnixConn.CloseRead, UnixConn.CloseWrite
-</li>
-
 <li>
-The new method <a href="/pkg/os/#FileMode.IsRegular"><code>os.FileMode.IsRegular</code> </a> makes it easy to ask if a file is a plain file.
+The new method <a href="/pkg/os/#FileMode.IsRegular"><code>os.FileMode.IsRegular</code></a> makes it easy to ask if a file is a plain file.
 </li>
 
 <li>
-The <a href="/pkg/image/jpeg/"><code>image/jpeg</code></a> package now
-reads progressive JPEG files and handles a few more subsampling configurations.
+The <a href="/pkg/os/signal/"><code>os/signal</code></a> package has a new function,
+<a href="/pkg/os/signal/#Stop"><code>Stop</code></a>, which stops the package delivering
+any further signals to the channel.
 </li>
 
 <li>
@@ -764,7 +990,7 @@ The <a href="/pkg/strings/"><code>strings</code></a> package has two new functio
 <a href="/pkg/strings/#TrimPrefix"><code>TrimPrefix</code></a>
 and
 <a href="/pkg/strings/#TrimSuffix"><code>TrimSuffix</code></a>
-with self-evident properties, and the the new method
+with self-evident properties, and the new method
 <a href="/pkg/strings/#Reader.WriteTo"><code>Reader.WriteTo</code></a> so the
 <a href="/pkg/strings/#Reader"><code>Reader</code></a>
 type now implements the
@@ -777,8 +1003,11 @@ The <a href="/pkg/syscall/"><code>syscall</code></a> package has received many u
 
 <li>
 The <a href="/pkg/testing/"><code>testing</code></a> package now automates the generation of allocation
-statistics in benchmarks using the new
-<a href="/pkg/testing/#AllocsPerRun"><code>AllocsPerRun</code></a> function and the
+statistics in tests and benchmarks using the new
+<a href="/pkg/testing/#AllocsPerRun"><code>AllocsPerRun</code></a> function. And the
+<a href="/pkg/testing/#B.ReportAllocs"><code>ReportAllocs</code></a>
+method on <a href="/pkg/testing/#B"><code>testing.B</code></a> will enable printing of
+memory allocation statistics for the calling benchmark. It also introduces the
 <a href="/pkg/testing/#BenchmarkResult.AllocsPerOp"><code>AllocsPerOp</code></a> method of
 <a href="/pkg/testing/#BenchmarkResult"><code>BenchmarkResult</code></a>.
 There is also a new
@@ -796,7 +1025,6 @@ In the <a href="/pkg/text/template/"><code>text/template</code></a>
 and
 <a href="/pkg/html/template/"><code>html/template</code></a> packages,
 templates can now use parentheses to group the elements of pipelines, simplifying the construction of complex pipelines.
-TODO: Link to example.
 Also, as part of the new parser, the
 <a href="/pkg/text/template/parse/#Node"><code>Node</code></a> interface got two new methods to provide
 better error reporting.
@@ -810,12 +1038,12 @@ packages and there are safeguards to guarantee that.
 </li>
 
 <li>
-In the <a href="/pkg/unicode/utf8/"><code>unicode/utf8</code></a> package,
-the new function <a href="/pkg/unicode/utf8/#ValidRune"><code>ValidRune</code></a> reports whether the rune is a valid Unicode code point.
-To be valid, a rune must be in range and not be a surrogate half.
+The implementation of the <a href="/pkg/unicode/"><code>unicode</code></a> package has been updated to Unicode version 6.2.0.
 </li>
 
 <li>
-The implementation of the <a href="/pkg/unicode/"><code>unicode</code></a> package has been updated to Unicode version 6.2.0.
+In the <a href="/pkg/unicode/utf8/"><code>unicode/utf8</code></a> package,
+the new function <a href="/pkg/unicode/utf8/#ValidRune"><code>ValidRune</code></a> reports whether the rune is a valid Unicode code point.
+To be valid, a rune must be in range and not be a surrogate half.
 </li>
 </ul>
diff --git a/doc/go_faq.html b/doc/go_faq.html
index 3e742d9..63ad66c 100644
--- a/doc/go_faq.html
+++ b/doc/go_faq.html
@@ -157,6 +157,12 @@ and so on.  These cannot be addressed well by libraries or tools; a new
 language was called for.
 </p>
 
+<p>
+The article <a href="http://talks.golang.org/2012/splash.article">Go at Google</a>
+discusses the background and motivation behind the design of the Go language,
+as well as providing more detail about many of the answers presented in this FAQ.
+</p>
+
 <h3 id="ancestors">
 What are Go's ancestors?</h3>
 <p>
@@ -216,6 +222,13 @@ document server running in a production configuration on
 <a href="https://developers.google.com/appengine/">Google App Engine</a>.
 </p>
 
+<p>
+Other examples include the <a href="https://code.google.com/p/vitess/">Vitess</a>
+system for large-scale SQL installations and Google's download server, <code>dl.google.com</code>,
+which delivers Chrome binaries and other large installables such as <code>apt-get</code>
+packages.
+</p>
+
 <h3 id="Do_Go_programs_link_with_Cpp_programs">
 Do Go programs link with C/C++ programs?</h3>
 
@@ -394,6 +407,8 @@ for concurrency comes from Hoare's Communicating Sequential Processes, or CSP.
 Occam and Erlang are two well known languages that stem from CSP.
 Go's concurrency primitives derive from a different part of the family tree
 whose main contribution is the powerful notion of channels as first class objects.
+Experience with several earlier languages has shown that the CSP model
+fits well into a procedural language framework.
 </p>
 
 <h3 id="goroutines">
@@ -874,11 +889,11 @@ There's a lot of history on that topic.  Early on, maps and channels
 were syntactically pointers and it was impossible to declare or use a
 non-pointer instance.  Also, we struggled with how arrays should work.
 Eventually we decided that the strict separation of pointers and
-values made the language harder to use.  Introducing reference types,
-including slices to handle the reference form of arrays, resolved
-these issues.  Reference types add some regrettable complexity to the
-language but they have a large effect on usability: Go became a more
-productive, comfortable language when they were introduced.
+values made the language harder to use.  Changing these
+types to act as references to the associated, shared data structures resolved
+these issues. This change added some regrettable complexity to the
+language but had a large effect on usability: Go became a more
+productive, comfortable language when it was introduced.
 </p>
 
 <h2 id="Writing_Code">Writing Code</h2>
@@ -1080,7 +1095,7 @@ There are several considerations.
 First, and most important, does the method need to modify the
 receiver?
 If it does, the receiver <em>must</em> be a pointer.
-(Slices and maps are reference types, so their story is a little
+(Slices and maps act as references, so their story is a little
 more subtle, but for instance to change the length of a slice
 in a method the receiver must still be a pointer.)
 In the examples above, if <code>pointerMethod</code> modifies
@@ -1131,7 +1146,7 @@ of Effective Go</a> for more details.
 </p>
 
 <h3 id="q_int_sizes">
-Why is <code>int</code> 32 bits on 64 bit machines?</h3>
+What is the size of an <code>int</code> on a 64 bit machine?</h3>
 
 <p>
 The sizes of <code>int</code> and <code>uint</code> are implementation-specific
@@ -1148,12 +1163,6 @@ floating-point numbers.
 The default size of a floating-point constant is <code>float64</code>.
 </p>
 
-<p>
-At the moment, all implementations use 32-bit ints, an essentially arbitrary decision.
-However, we expect that <code>int</code> will be increased to 64 bits on 64-bit
-architectures in a future release of Go.
-</p>
-
 <h3 id="stack_or_heap">
 How do I know whether a variable is allocated on the heap or the stack?</h3>
 
@@ -1237,6 +1246,9 @@ run-time support to utilize more than one OS thread.
 <p>
 Programs that perform parallel computation should benefit from an increase in
 <code>GOMAXPROCS</code>.
+However, be aware that
+<a href="http://blog.golang.org/2013/01/concurrency-is-not-parallelism.html">concurrency
+is not parallelism</a>.
 </p>
 
 <h3 id="Why_GOMAXPROCS">
@@ -1270,6 +1282,11 @@ should recognize such cases and optimize its use of OS threads. For now,
 <code>GOMAXPROCS</code> should be set on a per-application basis.
 </p>
 
+<p>
+For more detail on this topic see the talk entitled,
+<a href="http://blog.golang.org/2013/01/concurrency-is-not-parallelism.html">Concurrency
+is not Parallelism</a>.
+
 <h2 id="Functions_methods">Functions and Methods</h2>
 
 <h3 id="different_method_sets">
@@ -1503,9 +1520,11 @@ We considered writing <code>gc</code>, the original Go compiler, in Go itself bu
 elected not to do so because of the difficulties of bootstrapping and
 especially of open source distribution—you'd need a Go compiler to
 set up a Go environment. <code>Gccgo</code>, which came later, makes it possible to
-consider writing a compiler in Go, which might well happen. (Go would be a
+consider writing a compiler in Go, which might well happen.
+(Go would be a
 fine language in which to implement a compiler; a native lexer and
-parser are already available in the <a href="/pkg/go/"><code>go</code></a> package.)
+parser are already available in the <a href="/pkg/go/"><code>go</code></a> package
+and a type checker is in the works.)
 </p>
 
 <p>
diff --git a/doc/go_spec.html b/doc/go_spec.html
index 881d166..214d1c0 100644
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1,6 +1,6 @@
 <!--{
 	"Title": "The Go Programming Language Specification",
-	"Subtitle": "Version of March 22, 2013",
+	"Subtitle": "Version of April 3, 2013",
 	"Path": "/ref/spec"
 }-->
 
@@ -837,9 +837,9 @@ multi-dimensional types.
 <h3 id="Slice_types">Slice types</h3>
 
 <p>
-A slice is a reference to a contiguous segment of an array and
-contains a numbered sequence of elements from that array.  A slice
-type denotes the set of all slices of arrays of its element type.
+A slice is a descriptor for a contiguous segment of an array and
+provides access to a numbered sequence of elements from that array.
+A slice type denotes the set of all slices of arrays of its element type.
 The value of an uninitialized slice is <code>nil</code>.
 </p>
 
@@ -5197,8 +5197,6 @@ of the memory.
 <h3 id="Making_slices_maps_and_channels">Making slices, maps and channels</h3>
 
 <p>
-Slices, maps and channels are reference types that do not require the
-extra indirection of an allocation with <code>new</code>.
 The built-in function <code>make</code> takes a type <code>T</code>,
 which must be a slice, map or channel type,
 optionally followed by a type-specific list of expressions.
diff --git a/doc/godocs.js b/doc/godocs.js
index 5d12da1..6875f74 100644
--- a/doc/godocs.js
+++ b/doc/godocs.js
@@ -179,6 +179,13 @@ function fixFocus() {
   }).resize();
 }
 
+function toggleHash() {
+    var hash = $(window.location.hash);
+    if (hash.is('.toggle')) {
+      hash.addClass('toggleVisible').removeClass('toggle');
+    }
+}
+
 $(document).ready(function() {
   bindSearchEvents();
   generateTOC();
@@ -190,6 +197,7 @@ $(document).ready(function() {
   bindToggleLinks(".indexLink", "");
   setupDropdownPlayground();
   fixFocus();
+  toggleHash();
 });
 
 })();
diff --git a/doc/install.html b/doc/install.html
index 03b13c0..f2e21b4 100644
--- a/doc/install.html
+++ b/doc/install.html
@@ -3,25 +3,34 @@
 	"Path":  "/doc/install"
 }-->
 
-<h2 id="introduction">Introduction</h2>
+<h2 id="download">Download the Go distribution</h2>
 
 <p>
-Go is an open source project with a BSD-style license.
-There are two official Go compiler toolchains: the <code>gc</code> Go compiler
-and the <code>gccgo</code> compiler that is part of the GNU C Compiler (GCC).
+<a href="http://code.google.com/p/go/downloads" id="start" class="download" target="_blank">
+<span class="big">Download Go</span>
+<span class="desc">Click here to visit the downloads page</span>
+</a>
 </p>
 
 <p>
-The <code>gc</code> compiler is the more mature and well-tested of the two.
-This page is about installing a binary distribution of the <code>gc</code>
-compiler.
+Click the link above to visit the
+<a href="http://code.google.com/p/go/downloads">Go project's downloads page</a>
+and select the binary distribution that matches your operating system and
+processor architecture.
 </p>
 
 <p>
-For information about installing the <code>gc</code> compiler from source, see
-<a href="/doc/install/source">Installing Go from source</a>.
-For information about installing <code>gccgo</code>, see
-<a href="/doc/install/gccgo">Setting up and using gccgo</a>.
+Official binary distributions are available for the FreeBSD, Linux, Mac OS X
+(Snow Leopard, Lion, and Mountain Lion), NetBSD, and Windows operating systems
+and the 32-bit (<code>386</code>) and 64-bit (<code>amd64</code>) x86 processor
+architectures.
+</p>
+
+<p>
+If a binary distribution is not available for your combination of operating
+system and architecture you may want to try
+<a href="/doc/install/source">installing from source</a> or
+<a href="/doc/install/gccgo">installing gccgo instead of gc</a>.
 </p>
 
 <h2 id="requirements">System requirements</h2>
@@ -56,29 +65,6 @@ installed Xcode 4.3+, you can install it from the Components tab of the
 Downloads preferences panel.
 </p>
 
-<h2 id="download">Download the Go tools</h2>
-
-<p>
-Visit the
-<a href="http://code.google.com/p/go/downloads">Go project's downloads page</a>
-and select the binary distribution that matches
-your operating system and processor architecture.
-</p>
-
-<p>
-Official binary distributions are available
-for the FreeBSD, Linux, Mac OS X (Snow Leopard/Lion), NetBSD, and Windows operating systems
-and the 32-bit (<code>386</code>) and 64-bit (<code>amd64</code>)
-x86 processor architectures.
-</p>
-
-<p>
-If a binary distribution is not available for your
-OS/arch combination you may want to try
-<a href="/doc/install/source">installing from source</a> or
-<a href="/doc/install/gccgo">installing gccgo instead of gc</a>.
-</p>
-
 <h2 id="install">Install the Go tools</h2>
 
 <p>
diff --git a/doc/style.css b/doc/style.css
index 3d881b0..5c8e17a 100644
--- a/doc/style.css
+++ b/doc/style.css
@@ -12,7 +12,7 @@ pre {
 	line-height: 18px;
 }
 pre .comment {
-	color: #375EAB;
+	color: #006600;
 }
 pre .highlight,
 pre .highlight-comment,
@@ -198,6 +198,9 @@ div#blog .read a {
 	border: 1px solid #375EAB;
 	background: #E0EBF5;
 }
+.download {
+	width: 150px;
+}
 
 div#menu {
 	float: right;
diff --git a/include/libc.h b/include/libc.h
index fab1532..e10dde3 100644
--- a/include/libc.h
+++ b/include/libc.h
@@ -291,6 +291,7 @@ extern	char*	getgoroot(void);
 extern	char*	getgoversion(void);
 extern	char*	getgoarm(void);
 extern	char*	getgo386(void);
+extern	char*	getgoextlinkenabled(void);
 
 extern	char*	mktempdir(void);
 extern	void	removeall(char*);
diff --git a/include/plan9/libc.h b/include/plan9/libc.h
index e6f9839..dcecc7c 100644
--- a/include/plan9/libc.h
+++ b/include/plan9/libc.h
@@ -18,6 +18,7 @@ char*	getgoroot(void);
 char*	getgoversion(void);
 char*	getgoarm(void);
 char*	getgo386(void);
+char*	getgoextlinkenabled(void);
 
 void	flagcount(char*, char*, int*);
 void	flagint32(char*, char*, int32*);
diff --git a/lib/codereview/codereview.py b/lib/codereview/codereview.py
index 11766fc..f839263 100644
--- a/lib/codereview/codereview.py
+++ b/lib/codereview/codereview.py
@@ -1762,7 +1762,8 @@ def gofmt(ui, repo, *pats, **opts):
 	files = ChangedExistingFiles(ui, repo, pats, opts)
 	files = gofmt_required(files)
 	if not files:
-		return "no modified go files"
+		ui.status("no modified go files\n")
+		return
 	cwd = os.getcwd()
 	files = [RelativePath(repo.root + '/' + f, cwd) for f in files]
 	try:
diff --git a/lib/godoc/package.html b/lib/godoc/package.html
index 33c2c27..aefbef9 100644
--- a/lib/godoc/package.html
+++ b/lib/godoc/package.html
@@ -40,7 +40,7 @@
 				{{comment_html .Doc}}
 			</div>
 		</div>
-		{{example_html "" $.Examples $.FSet}}
+		{{example_html $ ""}}
 
 		<div id="pkg-index" class="toggleVisible">
 		<div class="collapsed">
@@ -60,18 +60,18 @@
 			{{end}}
 			{{range .Funcs}}
 				{{$name_html := html .Name}}
-				<dd><a href="#{{$name_html}}">{{node_html .Decl $.FSet}}</a></dd>
+				<dd><a href="#{{$name_html}}">{{node_html $ .Decl false}}</a></dd>
 			{{end}}
 			{{range .Types}}
 				{{$tname_html := html .Name}}
 				<dd><a href="#{{$tname_html}}">type {{$tname_html}}</a></dd>
 				{{range .Funcs}}
 					{{$name_html := html .Name}}
-					<dd>    <a href="#{{$name_html}}">{{node_html .Decl $.FSet}}</a></dd>
+					<dd>    <a href="#{{$name_html}}">{{node_html $ .Decl false}}</a></dd>
 				{{end}}
 				{{range .Methods}}
 					{{$name_html := html .Name}}
-					<dd>    <a href="#{{$tname_html}}.{{$name_html}}">{{node_html .Decl $.FSet}}</a></dd>
+					<dd>    <a href="#{{$tname_html}}.{{$name_html}}">{{node_html $ .Decl false}}</a></dd>
 				{{end}}
 			{{end}}
 			{{if $.Notes}}
@@ -109,59 +109,59 @@
 		{{with .Consts}}
 			<h2 id="pkg-constants">Constants</h2>
 			{{range .}}
-				<pre>{{node_html .Decl $.FSet}}</pre>
+				<pre>{{node_html $ .Decl true}}</pre>
 				{{comment_html .Doc}}
 			{{end}}
 		{{end}}
 		{{with .Vars}}
 			<h2 id="pkg-variables">Variables</h2>
 			{{range .}}
-				<pre>{{node_html .Decl $.FSet}}</pre>
+				<pre>{{node_html $ .Decl true}}</pre>
 				{{comment_html .Doc}}
 			{{end}}
 		{{end}}
 		{{range .Funcs}}
 			{{/* Name is a string - no need for FSet */}}
 			{{$name_html := html .Name}}
-			<h2 id="{{$name_html}}">func <a href="{{posLink_url .Decl $.FSet}}">{{$name_html}}</a></h2>
-			<pre>{{node_html .Decl $.FSet}}</pre>
+			<h2 id="{{$name_html}}">func <a href="{{posLink_url $ .Decl}}">{{$name_html}}</a></h2>
+			<pre>{{node_html $ .Decl true}}</pre>
 			{{comment_html .Doc}}
-			{{example_html .Name $.Examples $.FSet}}
+			{{example_html $ .Name}}
 		{{end}}
 		{{range .Types}}
 			{{$tname := .Name}}
 			{{$tname_html := html .Name}}
-			<h2 id="{{$tname_html}}">type <a href="{{posLink_url .Decl $.FSet}}">{{$tname_html}}</a></h2>
-			<pre>{{node_html .Decl $.FSet}}</pre>
+			<h2 id="{{$tname_html}}">type <a href="{{posLink_url $ .Decl}}">{{$tname_html}}</a></h2>
+			<pre>{{node_html $ .Decl true}}</pre>
 			{{comment_html .Doc}}
 
 			{{range .Consts}}
-				<pre>{{node_html .Decl $.FSet}}</pre>
+				<pre>{{node_html $ .Decl true}}</pre>
 				{{comment_html .Doc}}
 			{{end}}
 
 			{{range .Vars}}
-				<pre>{{node_html .Decl $.FSet}}</pre>
+				<pre>{{node_html $ .Decl true}}</pre>
 				{{comment_html .Doc}}
 			{{end}}
 
-			{{example_html $tname $.Examples $.FSet}}
+			{{example_html $ $tname}}
 
 			{{range .Funcs}}
 				{{$name_html := html .Name}}
-				<h3 id="{{$name_html}}">func <a href="{{posLink_url .Decl $.FSet}}">{{$name_html}}</a></h3>
-				<pre>{{node_html .Decl $.FSet}}</pre>
+				<h3 id="{{$name_html}}">func <a href="{{posLink_url $ .Decl}}">{{$name_html}}</a></h3>
+				<pre>{{node_html $ .Decl true}}</pre>
 				{{comment_html .Doc}}
-				{{example_html .Name $.Examples $.FSet}}
+				{{example_html $ .Name}}
 			{{end}}
 
 			{{range .Methods}}
 				{{$name_html := html .Name}}
-				<h3 id="{{$tname_html}}.{{$name_html}}">func ({{html .Recv}}) <a href="{{posLink_url .Decl $.FSet}}">{{$name_html}}</a></h3>
-				<pre>{{node_html .Decl $.FSet}}</pre>
+				<h3 id="{{$tname_html}}.{{$name_html}}">func ({{html .Recv}}) <a href="{{posLink_url $ .Decl}}">{{$name_html}}</a></h3>
+				<pre>{{node_html $ .Decl true}}</pre>
 				{{comment_html .Doc}}
 				{{$name := printf "%s_%s" $tname .Name}}
-				{{example_html $name $.Examples $.FSet}}
+				{{example_html $ $name}}
 			{{end}}
 		{{end}}
 	{{end}}
@@ -169,9 +169,9 @@
 	{{with $.Notes}}
 		{{range $marker, $content := .}}
 			<h2 id="pkg-note-{{$marker}}">{{noteTitle $marker | html}}s</h2>
-			<ul>
+			<ul style="list-style: none; padding: 0;">
 			{{range .}}
-			<li>{{html .Body}}</li>
+			<li><a href="{{posLink_url $ .}}">&#x261e;</a> {{html .Body}}</li>
 			{{end}}
 			</ul>
 		{{end}}
@@ -179,7 +179,7 @@
 {{end}}
 
 {{with .PAst}}
-	<pre>{{node_html . $.FSet}}</pre>
+	<pre>{{node_html $ . false}}</pre>
 {{end}}
 
 {{with .Dirs}}
diff --git a/lib/godoc/package.txt b/lib/godoc/package.txt
index bc11fc3..d191621 100644
--- a/lib/godoc/package.txt
+++ b/lib/godoc/package.txt
@@ -1,4 +1,4 @@
-{{with .PAst}}{{node . $.FSet}}{{end}}{{/*
+{{with .PAst}}{{node $ .}}{{end}}{{/*
 
 ---------------------------------------
 
@@ -11,55 +11,54 @@ package {{.Name}}
     import "{{.ImportPath}}"
 
 {{comment_text .Doc "    " "\t"}}
-{{example_text "" $.Examples $.FSet "    "}}{{/*
+{{example_text $ "" "    "}}{{/*
 
 ---------------------------------------
 
 */}}{{with .Consts}}
 CONSTANTS
 
-{{range .}}{{node .Decl $.FSet}}
-{{comment_text .Doc "    " "\t"}}{{end}}
-{{end}}{{/*
+{{range .}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}
+{{end}}{{end}}{{/*
 
 ---------------------------------------
 
 */}}{{with .Vars}}
 VARIABLES
 
-{{range .}}{{node .Decl $.FSet}}
-{{comment_text .Doc "    " "\t"}}{{end}}
-{{end}}{{/*
+{{range .}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}
+{{end}}{{end}}{{/*
 
 ---------------------------------------
 
 */}}{{with .Funcs}}
 FUNCTIONS
 
-{{range .}}{{node .Decl $.FSet}}
+{{range .}}{{node $ .Decl}}
 {{comment_text .Doc "    " "\t"}}
-{{example_text .Name $.Examples $.FSet "    "}}
-{{end}}{{end}}{{/*
+{{example_text $ .Name "    "}}{{end}}{{end}}{{/*
 
 ---------------------------------------
 
 */}}{{with .Types}}
 TYPES
 
-{{range .}}{{$tname := .Name}}{{node .Decl $.FSet}}
+{{range .}}{{$tname := .Name}}{{node $ .Decl}}
 {{comment_text .Doc "    " "\t"}}
-{{range .Consts}}{{node .Decl $.FSet}}
+{{range .Consts}}{{node $ .Decl}}
 {{comment_text .Doc "    " "\t"}}
-{{end}}{{range .Vars}}{{node .Decl $.FSet}}
+{{end}}{{range .Vars}}{{node $ .Decl}}
 {{comment_text .Doc "    " "\t"}}
-{{end}}{{example_text .Name $.Examples $.FSet "    "}}
-{{range .Funcs}}{{node .Decl $.FSet}}
+{{end}}{{example_text $ .Name "    "}}
+{{range .Funcs}}{{node $ .Decl}}
 {{comment_text .Doc "    " "\t"}}
-{{example_text .Name $.Examples $.FSet "    "}}
-{{end}}{{range .Methods}}{{node .Decl $.FSet}}
+{{example_text $ .Name "    "}}
+{{end}}{{range .Methods}}{{node $ .Decl}}
 {{comment_text .Doc "    " "\t"}}
-{{$name := printf "%s_%s" $tname .Name}}{{example_text $name $.Examples $.FSet "    "}}
-{{end}}{{end}}{{end}}{{end}}{{/*
+{{$name := printf "%s_%s" $tname .Name}}{{example_text $ $name "    "}}{{end}}
+{{end}}{{end}}{{end}}{{/*
 
 ---------------------------------------
 
diff --git a/lib/time/update.bash b/lib/time/update.bash
index ef7fdc7..c2377e1 100755
--- a/lib/time/update.bash
+++ b/lib/time/update.bash
@@ -7,8 +7,8 @@
 # downloaded from the ICANN/IANA distribution.
 
 # Versions to use.
-CODE=2011i
-DATA=2011n
+CODE=2013b
+DATA=2013b
 
 set -e
 rm -rf work
diff --git a/lib/time/zoneinfo.zip b/lib/time/zoneinfo.zip
index b542132..c10a425 100644
Binary files a/lib/time/zoneinfo.zip and b/lib/time/zoneinfo.zip differ
diff --git a/misc/cgo/gmp/gmp.go b/misc/cgo/gmp/gmp.go
index 3bcf991..7b7a9b3 100644
--- a/misc/cgo/gmp/gmp.go
+++ b/misc/cgo/gmp/gmp.go
@@ -33,7 +33,7 @@ field; unrepresentable fields are replaced with opaque byte arrays.  A
 C union translates into a struct containing the first union member and
 perhaps additional padding.  C arrays become Go arrays.  C pointers
 become Go pointers.  C function pointers become Go's uintptr.
-C void pointer's become Go's unsafe.Pointer.
+C void pointers become Go's unsafe.Pointer.
 
 For example, mpz_t is defined in <gmp.h> as:
 
diff --git a/misc/cgo/test/callback.go b/misc/cgo/test/callback.go
index 4f5d3f8..b6e2e3c 100644
--- a/misc/cgo/test/callback.go
+++ b/misc/cgo/test/callback.go
@@ -12,7 +12,9 @@ import "C"
 
 import (
 	"./backdoor"
+	"path"
 	"runtime"
+	"strings"
 	"testing"
 	"unsafe"
 )
@@ -136,3 +138,44 @@ func testBlocking(t *testing.T) {
 		}
 	})
 }
+
+// Test that the stack can be unwound through a call out and call back
+// into Go.
+func testCallbackCallers(t *testing.T) {
+	pc := make([]uintptr, 100)
+	n := 0
+	name := []string{
+		"test.goCallback",
+		"runtime.cgocallbackg",
+		"runtime.cgocallback_gofunc",
+		"return",
+		"runtime.cgocall",
+		"test._Cfunc_callback",
+		"test.nestedCall",
+		"test.testCallbackCallers",
+		"test.TestCallbackCallers",
+		"testing.tRunner",
+		"runtime.goexit",
+	}
+	nestedCall(func() {
+		n = runtime.Callers(2, pc)
+	})
+	if n != len(name) {
+		t.Errorf("expected %d frames, got %d", len(name), n)
+	}
+	for i := 0; i < n; i++ {
+		f := runtime.FuncForPC(pc[i])
+		if f == nil {
+			t.Fatalf("expected non-nil Func for pc %p", pc[i])
+		}
+		fname := f.Name()
+		// Remove the prepended pathname from automatically
+		// generated cgo function names.
+		if strings.HasPrefix(fname, "_") {
+			fname = path.Base(f.Name()[1:])
+		}
+		if fname != name[i] {
+			t.Errorf("expected function name %s, got %s", name[i], fname)
+		}
+	}
+}
diff --git a/misc/cgo/test/cgo_test.go b/misc/cgo/test/cgo_test.go
index 536fa50..1901d5d 100644
--- a/misc/cgo/test/cgo_test.go
+++ b/misc/cgo/test/cgo_test.go
@@ -36,5 +36,6 @@ func TestBoolAlign(t *testing.T)           { testBoolAlign(t) }
 func Test3729(t *testing.T)                { test3729(t) }
 func Test3775(t *testing.T)                { test3775(t) }
 func TestCthread(t *testing.T)             { testCthread(t) }
+func TestCallbackCallers(t *testing.T)     { testCallbackCallers(t) }
 
 func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
diff --git a/misc/cgo/testtls/tls.go b/misc/cgo/testtls/tls.go
new file mode 100644
index 0000000..a9546a6
--- /dev/null
+++ b/misc/cgo/testtls/tls.go
@@ -0,0 +1,28 @@
+// Copyright 2013 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.
+
+package cgotlstest
+
+// #include <pthread.h>
+// extern void setTLS(int);
+// extern int getTLS();
+import "C"
+
+import (
+	"runtime"
+	"testing"
+)
+
+func testTLS(t *testing.T) {
+	var keyVal C.int = 1234
+
+	runtime.LockOSThread()
+	defer runtime.UnlockOSThread()
+	C.setTLS(C.int(keyVal))
+	storedVal := C.getTLS()
+
+	if storedVal != keyVal {
+		t.Fatalf("stored %d want %d", storedVal, keyVal)
+	}
+}
diff --git a/misc/cgo/testtls/tls_test.go b/misc/cgo/testtls/tls_test.go
new file mode 100644
index 0000000..3076c2d
--- /dev/null
+++ b/misc/cgo/testtls/tls_test.go
@@ -0,0 +1,13 @@
+// Copyright 2013 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.
+
+// +build !windows
+
+package cgotlstest
+
+import "testing"
+
+func TestTLS(t *testing.T) {
+	testTLS(t)
+}
diff --git a/misc/cgo/testtls/tls_unix.c b/misc/cgo/testtls/tls_unix.c
new file mode 100644
index 0000000..5459516
--- /dev/null
+++ b/misc/cgo/testtls/tls_unix.c
@@ -0,0 +1,19 @@
+// Copyright 2013 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.
+
+#include <pthread.h>
+
+static __thread int tls;
+
+void
+setTLS(int v)
+{
+	tls = v;
+}
+
+int
+getTLS()
+{
+	return tls;
+}
diff --git a/misc/dashboard/codereview/dashboard/people.go b/misc/dashboard/codereview/dashboard/people.go
index 45de03b..21bd8f8 100644
--- a/misc/dashboard/codereview/dashboard/people.go
+++ b/misc/dashboard/codereview/dashboard/people.go
@@ -47,8 +47,9 @@ func init() {
 		"dvyukov":  "dvyukov at google.com",
 		"gustavo":  "gustavo at niemeyer.net",
 		"jsing":    "jsing at google.com",
-		"mikioh":   "mikioh.mikioh at gmail.com",
+		"mikio":    "mikioh.mikioh at gmail.com",
 		"minux":    "minux.ma at gmail.com",
+		"remy":     "remyoudompheng at gmail.com",
 		"rminnich": "rminnich at gmail.com",
 	}
 	for p, e := range others {
diff --git a/misc/dist/bindist.go b/misc/dist/bindist.go
index 2d633be..76859bc 100644
--- a/misc/dist/bindist.go
+++ b/misc/dist/bindist.go
@@ -29,13 +29,15 @@ import (
 )
 
 var (
-	tag      = flag.String("tag", "release", "mercurial tag to check out")
-	repo     = flag.String("repo", "https://code.google.com/p/go", "repo URL")
-	tourPath = flag.String("tour", "code.google.com/p/go-tour", "Go tour repo import path")
-	verbose  = flag.Bool("v", false, "verbose output")
-	upload   = flag.Bool("upload", true, "upload resulting files to Google Code")
-	wxsFile  = flag.String("wxs", "", "path to custom installer.wxs")
-	addLabel = flag.String("label", "", "additional label to apply to file when uploading")
+	tag             = flag.String("tag", "release", "mercurial tag to check out")
+	repo            = flag.String("repo", "https://code.google.com/p/go", "repo URL")
+	tourPath        = flag.String("tour", "code.google.com/p/go-tour", "Go tour repo import path")
+	verbose         = flag.Bool("v", false, "verbose output")
+	upload          = flag.Bool("upload", true, "upload resulting files to Google Code")
+	wxsFile         = flag.String("wxs", "", "path to custom installer.wxs")
+	addLabel        = flag.String("label", "", "additional label to apply to file when uploading")
+	includeRace     = flag.Bool("race", true, "build race detector packages")
+	versionOverride = flag.String("version", "", "override version name")
 
 	username, password string // for Google Code upload
 )
@@ -79,7 +81,14 @@ var tourContent = []string{
 	"tour.article",
 }
 
-var fileRe = regexp.MustCompile(`^go\.([a-z0-9-.]+)\.(src|([a-z0-9]+)-([a-z0-9]+))\.`)
+// The os-arches that support the race toolchain.
+var raceAvailable = []string{
+	"darwin-amd64",
+	"linux-amd64",
+	"windows-amd64",
+}
+
+var fileRe = regexp.MustCompile(`^(go[a-z0-9-.]+)\.(src|([a-z0-9]+)-([a-z0-9]+))\.`)
 
 func main() {
 	flag.Usage = func() {
@@ -130,6 +139,13 @@ func main() {
 			}
 			b.OS = p[0]
 			b.Arch = p[1]
+			if *includeRace {
+				for _, t := range raceAvailable {
+					if t == targ {
+						b.Race = true
+					}
+				}
+			}
 		}
 		if err := b.Do(); err != nil {
 			log.Printf("%s: %v", targ, err)
@@ -139,6 +155,7 @@ func main() {
 
 type Build struct {
 	Source bool // if true, OS and Arch must be empty
+	Race   bool // build race toolchain
 	OS     string
 	Arch   string
 	root   string
@@ -183,15 +200,31 @@ func (b *Build) Do() error {
 		} else {
 			_, err = b.run(src, "bash", "make.bash")
 		}
+		if b.Race {
+			if err != nil {
+				return err
+			}
+			goCmd := filepath.Join(b.root, "bin", "go")
+			if b.OS == "windows" {
+				goCmd += ".exe"
+			}
+			_, err = b.run(src, goCmd, "install", "-race", "std")
+			if err != nil {
+				return err
+			}
+			// Re-install std without -race, so that we're not left
+			// with a slower, race-enabled cmd/go, cmd/godoc, etc.
+			_, err = b.run(src, goCmd, "install", "-a", "std")
+		}
+		if err != nil {
+			return err
+		}
+		err = b.tour()
 	}
 	if err != nil {
 		return err
 	}
 
-	if err := b.tour(); err != nil {
-		return err
-	}
-
 	// Get version strings.
 	var (
 		version     string // "weekly.2012-03-04"
@@ -212,6 +245,9 @@ func (b *Build) Do() error {
 	fullVersion = bytes.TrimSpace(fullVersion)
 	v := bytes.SplitN(fullVersion, []byte(" "), 2)
 	version = string(v[0])
+	if *versionOverride != "" {
+		version = *versionOverride
+	}
 
 	// Write VERSION file.
 	err = ioutil.WriteFile(filepath.Join(b.root, "VERSION"), fullVersion, 0644)
@@ -388,7 +424,7 @@ func (b *Build) tour() error {
 	// Copy gotour binary to tool directory as "tour"; invoked as "go tool tour".
 	gotour := "gotour"
 	if runtime.GOOS == "windows" {
-		gotour = "gotour.exe"
+		gotour += ".exe"
 	}
 	return cp(
 		filepath.Join(b.root, "pkg", "tool", b.OS+"_"+b.Arch, "tour"),
@@ -505,7 +541,12 @@ func (b *Build) Upload(version string, filename string) error {
 		ftype = "Source"
 		summary = fmt.Sprintf("%s (source only)", version)
 	}
-	labels = append(labels, "OpSys-"+opsys, "Type-"+ftype)
+	if opsys != "" {
+		labels = append(labels, "OpSys-"+opsys)
+	}
+	if ftype != "" {
+		labels = append(labels, "Type-"+ftype)
+	}
 	if *addLabel != "" {
 		labels = append(labels, *addLabel)
 	}
diff --git a/misc/emacs/go-mode.el b/misc/emacs/go-mode.el
index 9b6ea74..6f0442a 100644
--- a/misc/emacs/go-mode.el
+++ b/misc/emacs/go-mode.el
@@ -52,6 +52,14 @@
 (defun go--old-completion-list-style (list)
   (mapcar (lambda (x) (cons x nil)) list))
 
+;; GNU Emacs 24 has prog-mode, older GNU Emacs and XEmacs do not.
+;; Ideally we'd use defalias instead, but that breaks in XEmacs.
+;;
+;; TODO: If XEmacs decides to add prog-mode, change this to use
+;; defalias to alias prog-mode or fundamental-mode to go--prog-mode
+;; and use that in define-derived-mode.
+(if (not (fboundp 'prog-mode))
+    (define-derived-mode prog-mode fundamental-mode "" ""))
 
 (defun go--regexp-enclose-in-symbol (s)
   ;; XEmacs does not support \_<, GNU Emacs does. In GNU Emacs we make
@@ -370,7 +378,7 @@ current line will be returned."
       (forward-char))))
 
 ;;;###autoload
-(define-derived-mode go-mode fundamental-mode "Go"
+(define-derived-mode go-mode prog-mode "Go"
   "Major mode for editing Go source text.
 
 This mode provides (not just) basic editing capabilities for
@@ -557,8 +565,8 @@ buffer."
     (insert "gofmt errors:\n")
     (while (search-forward-regexp (concat "^\\(" (regexp-quote tmpfile) "\\):") nil t)
       (replace-match (file-name-nondirectory filename) t t nil 1))
-    (display-buffer errbuf)
-    (compilation-mode)))
+    (compilation-mode)
+    (display-buffer errbuf)))
 
 ;;;###autoload
 (defun gofmt-before-save ()
diff --git a/misc/kate/go.xml b/misc/kate/go.xml
index 1e00cfc..c187eda 100644
--- a/misc/kate/go.xml
+++ b/misc/kate/go.xml
@@ -95,7 +95,7 @@
         <HlCHex attribute="Hex" context="#stay"/>
         <HlCChar attribute="Char" context="#stay"/>
         <DetectChar attribute="String" context="String" char="""/>
-        <DetectChar attribute="Multiline String" context="Multiline String" char="`"/>
+        <DetectChar attribute="String" context="Multiline String" char="`"/>
         <Detect2Chars attribute="Comment" context="Comment 1" char="/" char1="/"/>
         <Detect2Chars attribute="Comment" context="Comment 2" char="/" char1="*" beginRegion="Comment"/>
         <AnyChar attribute="Symbol" context="#stay" String=":!%&()+,-/.*<=>?[]|~^;"/>
diff --git a/misc/vim/plugin/godoc.vim b/misc/vim/plugin/godoc.vim
index a9abb7a..a7b84de 100644
--- a/misc/vim/plugin/godoc.vim
+++ b/misc/vim/plugin/godoc.vim
@@ -70,13 +70,26 @@ endfunction
 function! s:Godoc(...)
   let word = join(a:000, ' ')
   if !len(word)
+    let oldiskeyword = &iskeyword
+    setlocal iskeyword+=.
     let word = expand('<cword>')
+    let &iskeyword = oldiskeyword
   endif
   let word = substitute(word, '[^a-zA-Z0-9\\/._~-]', '', 'g')
-  if !len(word)
+  let words = split(word, '\.')
+  if !len(words)
     return
   endif
-  call s:GodocWord(word)
+  call s:GodocWord(words[0])
+  if len(words) > 1
+    if search('^\%(const\|var\|type\|\s\+\) ' . words[1] . '\s\+=\s')
+      return
+    endif
+    if search('^func ' . words[1] . '(')
+      return
+    endif
+    echo 'No documentation found for "' . word . '".'
+  endif
 endfunction
 
 command! -nargs=* -range -complete=customlist,go#complete#Package Godoc :call s:Godoc(<q-args>)
diff --git a/src/all.bat b/src/all.bat
index 8929f77..0647a71 100644
--- a/src/all.bat
+++ b/src/all.bat
@@ -20,7 +20,7 @@ if %GOBUILDFAIL%==1 goto end
 :: can get the original %PATH% and give suggestion to add %GOROOT%/bin
 :: to %PATH% if necessary.
 set PATH=%OLDPATH%
-%GOTOOLDIR%/dist banner
+"%GOTOOLDIR%/dist" banner
 
 :end
 if x%GOBUILDEXIT%==x1 exit %GOBUILDFAIL%
diff --git a/src/cmd/5l/5.out.h b/src/cmd/5l/5.out.h
index 4aef8a2..97a2421 100644
--- a/src/cmd/5l/5.out.h
+++ b/src/cmd/5l/5.out.h
@@ -275,6 +275,7 @@ enum	as
 #define	D_PLT1		(D_NONE+44) // R_ARM_PLT32, 2nd inst: add ip, ip, #0xNN000
 #define	D_PLT2		(D_NONE+45) // R_ARM_PLT32, 3rd inst: ldr pc, [ip, #0xNNN]!
 #define	D_CALL		(D_NONE+46) // R_ARM_PLT32/R_ARM_CALL/R_ARM_JUMP24, bl xxxxx or b yyyyy
+#define	D_TLS		(D_NONE+47)
 
 /*
  * this is the ranlib header
diff --git a/src/cmd/5l/l.h b/src/cmd/5l/l.h
index 83c8b75..e7794c7 100644
--- a/src/cmd/5l/l.h
+++ b/src/cmd/5l/l.h
@@ -299,7 +299,6 @@ EXTERN	Auto*	curhist;
 EXTERN	Prog*	curp;
 EXTERN	Sym*	cursym;
 EXTERN	Sym*	datap;
-EXTERN	int32 	elfdatsize;
 EXTERN	int	debug[128];
 EXTERN	Sym*	etextp;
 EXTERN	char*	noname;
diff --git a/src/cmd/5l/obj.c b/src/cmd/5l/obj.c
index 1bcf436..24e6294 100644
--- a/src/cmd/5l/obj.c
+++ b/src/cmd/5l/obj.c
@@ -114,6 +114,8 @@ main(int argc, char *argv[])
 	flagcount("a", "disassemble output", &debug['a']);
 	flagcount("c", "dump call graph", &debug['c']);
 	flagcount("d", "disable dynamic executable", &debug['d']);
+	flagstr("extld", "linker to run in external mode", &extld);
+	flagstr("extldflags", "flags for external linker", &extldflags);
 	flagcount("f", "ignore version mismatch", &debug['f']);
 	flagcount("g", "disable go package data checks", &debug['g']);
 	flagstr("k", "sym: set field tracking symbol", &tracksym);
@@ -136,9 +138,16 @@ main(int argc, char *argv[])
 	if(argc != 1)
 		usage();
 
-	if(linkmode != LinkInternal) {
+	// getgoextlinkenabled is based on GO_EXTLINK_ENABLED when
+	// Go was built; see ../../make.bash.
+	if(linkmode == LinkAuto && strcmp(getgoextlinkenabled(), "0") == 0)
+		linkmode = LinkInternal;
+
+	if(linkmode == LinkExternal) {
 		diag("only -linkmode=internal is supported");
 		errorexit();
+	} else if(linkmode == LinkAuto) {
+		linkmode = LinkInternal;
 	}
 
 	libinit();
@@ -606,11 +615,15 @@ loop:
 		break;
 
 	case ALOCALS:
+		if(skip)
+			goto casedef;
 		cursym->locals = p->to.offset;
 		pc++;
 		break;
 
 	case ATYPE:
+		if(skip)
+			goto casedef;
 		pc++;
 		goto loop;
 
diff --git a/src/cmd/6g/peep.c b/src/cmd/6g/peep.c
index 5696557..bb24d41 100644
--- a/src/cmd/6g/peep.c
+++ b/src/cmd/6g/peep.c
@@ -472,6 +472,7 @@ elimshortmov(Reg *r)
 {
 	Prog *p;
 
+	USED(r);
 	for(r=firstr; r!=R; r=r->link) {
 		p = r->prog;
 		if(regtyp(&p->to)) {
@@ -555,7 +556,7 @@ elimshortmov(Reg *r)
 	}
 }
 
-int
+static int
 regconsttyp(Adr *a)
 {
 	if(regtyp(a))
@@ -758,7 +759,7 @@ subprop(Reg *r0)
 		}
 	}
 	if(debug['P'] && debug['v'])
-		print("\tran off end; return 0\n", p);
+		print("\tran off end; return 0\n");
 	return 0;
 
 gotit:
diff --git a/src/cmd/6g/reg.c b/src/cmd/6g/reg.c
index c56d716..7db6bea 100644
--- a/src/cmd/6g/reg.c
+++ b/src/cmd/6g/reg.c
@@ -182,7 +182,6 @@ regopt(Prog *firstp)
 		return;
 	}
 
-	r1 = R;
 	firstr = R;
 	lastr = R;
 
@@ -783,7 +782,7 @@ brk:
 				Var *v;
 
 				v = var + rgp->varno;
-				print("registerize %N+%d (bit=%2d et=%2E) in %R\n",
+				print("registerize %N+%lld (bit=%2d et=%2E) in %R\n",
 						v->node, v->offset, rgp->varno, v->etype, rgp->regno);
 			}
 			paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
@@ -1061,7 +1060,7 @@ mkvar(Reg *r, Adr *a)
 	v->node = node;
 
 	if(debug['R'])
-		print("bit=%2d et=%2E w=%d+%d %#N %D flag=%d\n", i, et, o, w, node, a, v->addr);
+		print("bit=%2d et=%2E w=%d+%lld %#N %D flag=%d\n", i, et, o, w, node, a, v->addr);
 
 	ostats.nvar++;
 
diff --git a/src/cmd/6l/6.out.h b/src/cmd/6l/6.out.h
index 28de749..237a802 100644
--- a/src/cmd/6l/6.out.h
+++ b/src/cmd/6l/6.out.h
@@ -866,6 +866,7 @@ enum
 
 	D_SIZE = D_INDIR + D_INDIR,	/* 6l internal */
 	D_PCREL,
+	D_TLS,
 
 	T_TYPE		= 1<<0,
 	T_INDEX		= 1<<1,
diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c
index 07ba59a..8807a6e 100644
--- a/src/cmd/6l/asm.c
+++ b/src/cmd/6l/asm.c
@@ -310,6 +310,13 @@ elfreloc1(Reloc *r, vlong sectoff)
 		else
 			return -1;
 		break;
+	
+	case D_TLS:
+		if(r->siz == 4)
+			VPUT(R_X86_64_TPOFF32 | (uint64)elfsym<<32);
+		else
+			return -1;
+		break;		
 	}
 
 	VPUT(r->xadd);
diff --git a/src/cmd/6l/l.h b/src/cmd/6l/l.h
index 1d6e55c..4d481c6 100644
--- a/src/cmd/6l/l.h
+++ b/src/cmd/6l/l.h
@@ -336,7 +336,6 @@ EXTERN	Auto*	curhist;
 EXTERN	Prog*	curp;
 EXTERN	Sym*	cursym;
 EXTERN	Sym*	datap;
-EXTERN	vlong	elfdatsize;
 EXTERN	int	debug[128];
 EXTERN	char	literal[32];
 EXTERN	Sym*	textp;
diff --git a/src/cmd/6l/obj.c b/src/cmd/6l/obj.c
index 3775df9..e98f91e 100644
--- a/src/cmd/6l/obj.c
+++ b/src/cmd/6l/obj.c
@@ -83,7 +83,7 @@ main(int argc, char *argv[])
 	INITRND = -1;
 	INITENTRY = 0;
 	LIBINITENTRY = 0;
-	linkmode = LinkInternal; // TODO: LinkAuto once everything works.
+	linkmode = LinkAuto;
 	nuxiinit();
 
 	flagcount("1", "use alternate profiling code", &debug['1']);
@@ -107,6 +107,8 @@ main(int argc, char *argv[])
 	flagcount("a", "disassemble output", &debug['a']);
 	flagcount("c", "dump call graph", &debug['c']);
 	flagcount("d", "disable dynamic executable", &debug['d']);
+	flagstr("extld", "linker to run in external mode", &extld);
+	flagstr("extldflags", "flags for external linker", &extldflags);
 	flagcount("f", "ignore version mismatch", &debug['f']);
 	flagcount("g", "disable go package data checks", &debug['g']);
 	flagfn1("linkmode", "mode: set link mode (internal, external, auto)", setlinkmode);
@@ -133,11 +135,16 @@ main(int argc, char *argv[])
 	if(HEADTYPE == -1)
 		HEADTYPE = headtype(goos);
 
+	// getgoextlinkenabled is based on GO_EXTLINK_ENABLED when
+	// Go was built; see ../../make.bash.
+	if(linkmode == LinkAuto && strcmp(getgoextlinkenabled(), "0") == 0)
+		linkmode = LinkInternal;
+
 	switch(HEADTYPE) {
 	default:
 		if(linkmode == LinkAuto)
 			linkmode = LinkInternal;
-		if(linkmode == LinkExternal)
+		if(linkmode == LinkExternal && strcmp(getgoextlinkenabled(), "1") != 0)
 			sysfatal("cannot use -linkmode=external with -H %s", headstr(HEADTYPE));
 		break;
 	case Hdarwin:
@@ -597,11 +604,15 @@ loop:
 		goto loop;
 
 	case ALOCALS:
+		if(skip)
+			goto casdef;
 		cursym->locals = p->to.offset;
 		pc++;
 		goto loop;
 	
 	case ATYPE:
+		if(skip)
+			goto casdef;
 		pc++;
 		goto loop;
 
diff --git a/src/cmd/6l/span.c b/src/cmd/6l/span.c
index fa94d8c..460a34f 100644
--- a/src/cmd/6l/span.c
+++ b/src/cmd/6l/span.c
@@ -32,6 +32,7 @@
 
 #include	"l.h"
 #include	"../ld/lib.h"
+#include	"../ld/elf.h"
 
 static int	rexflag;
 static int	asmode;
@@ -880,7 +881,30 @@ putrelv:
 		r = addrel(cursym);
 		*r = rel;
 		r->off = curp->pc + andptr - and;
+	} else if(iself && linkmode == LinkExternal && a->type == D_INDIR+D_FS
+		&& HEADTYPE != Hopenbsd) {
+		Reloc *r;
+		Sym *s;
+		
+		r = addrel(cursym);
+		r->off = curp->pc + andptr - and;
+		r->add = 0;
+		r->xadd = 0;
+		r->siz = 4;
+		r->type = D_TLS;
+		if(a->offset == tlsoffset+0)
+			s = lookup("runtime.g", 0);
+		else
+			s = lookup("runtime.m", 0);
+		s->type = STLSBSS;
+		s->reachable = 1;
+		s->size = PtrSize;
+		s->hide = 1;
+		r->sym = s;
+		r->xsym = s;
+		v = 0;
 	}
+		
 	put4(v);
 	return;
 
diff --git a/src/cmd/8a/a.y b/src/cmd/8a/a.y
index 516e5fb..2466434 100644
--- a/src/cmd/8a/a.y
+++ b/src/cmd/8a/a.y
@@ -507,6 +507,15 @@ omem:
 		$$.scale = $8;
 		checkscale($$.scale);
 	}
+|	con '(' LLREG ')' '(' LSREG '*' con ')'
+	{
+		$$ = nullgen;
+		$$.type = D_INDIR+$3;
+		$$.offset = $1;
+		$$.index = $6;
+		$$.scale = $8;
+		checkscale($$.scale);
+	}
 |	'(' LLREG ')'
 	{
 		$$ = nullgen;
diff --git a/src/cmd/8a/lex.c b/src/cmd/8a/lex.c
index b8fc2c0..a7840f6 100644
--- a/src/cmd/8a/lex.c
+++ b/src/cmd/8a/lex.c
@@ -760,10 +760,12 @@ struct
 	"ORPS",		LTYPE3,	AORPS,
 	"PADDQ",	LTYPE3,	APADDQ,
 	"PAND",		LTYPE3,	APAND,
+	"PCMPEQB",	LTYPE3,	APCMPEQB,
 	"PMAXSW",	LTYPE3,	APMAXSW,
 	"PMAXUB",	LTYPE3,	APMAXUB,
 	"PMINSW",	LTYPE3,	APMINSW,
 	"PMINUB",	LTYPE3,	APMINUB,
+	"PMOVMSKB",	LTYPE3,	APMOVMSKB,
 	"PSADBW",	LTYPE3,	APSADBW,
 	"PSHUFB",	LTYPE3, APSHUFB,
 	"PSUBB",	LTYPE3,	APSUBB,
diff --git a/src/cmd/8a/y.tab.c b/src/cmd/8a/y.tab.c
index 7eaff0b..6616c91 100644
--- a/src/cmd/8a/y.tab.c
+++ b/src/cmd/8a/y.tab.c
@@ -1,21 +1,24 @@
-/* A Bison parser, made by GNU Bison 2.5.  */
+/* A Bison parser, made by GNU Bison 2.3.  */
 
-/* Bison implementation for Yacc-like parsers in C
-   
-      Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc.
-   
-   This program is free software: you can redistribute it and/or modify
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
-   
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
 
 /* As a special exception, you may create a larger work that contains
    part or all of the Bison parser skeleton and distribute that work
@@ -26,7 +29,7 @@
    special exception, which will cause the skeleton and the resulting
    Bison output files to be licensed under the GNU General Public
    License without this special exception.
-   
+
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
@@ -44,7 +47,7 @@
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "2.5"
+#define YYBISON_VERSION "2.3"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
@@ -52,50 +55,11 @@
 /* Pure parsers.  */
 #define YYPURE 0
 
-/* Push parsers.  */
-#define YYPUSH 0
-
-/* Pull parsers.  */
-#define YYPULL 1
-
 /* Using locations.  */
 #define YYLSP_NEEDED 0
 
 
 
-/* Copy the first part of user declarations.  */
-
-/* Line 268 of yacc.c  */
-#line 31 "a.y"
-
-#include <u.h>
-#include <stdio.h>	/* if we don't, bison will, and a.h re-#defines getc */
-#include <libc.h>
-#include "a.h"
-
-
-/* Line 268 of yacc.c  */
-#line 79 "y.tab.c"
-
-/* Enabling traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-
-/* Enabling verbose error messages.  */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 0
-#endif
-
-/* Enabling the token table.  */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
-#endif
-
-
 /* Tokens.  */
 #ifndef YYTOKENTYPE
 # define YYTOKENTYPE
@@ -171,13 +135,37 @@
 
 
 
+/* Copy the first part of user declarations.  */
+#line 31 "a.y"
+
+#include <u.h>
+#include <stdio.h>	/* if we don't, bison will, and a.h re-#defines getc */
+#include <libc.h>
+#include "a.h"
+
+
+/* Enabling traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table.  */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef union YYSTYPE
-{
-
-/* Line 293 of yacc.c  */
 #line 37 "a.y"
-
+{
 	Sym	*sym;
 	int32	lval;
 	struct {
@@ -188,23 +176,22 @@ typedef union YYSTYPE
 	char	sval[8];
 	Gen	gen;
 	Gen2	gen2;
-
-
-
-/* Line 293 of yacc.c  */
-#line 196 "y.tab.c"
-} YYSTYPE;
-# define YYSTYPE_IS_TRIVIAL 1
+}
+/* Line 193 of yacc.c.  */
+#line 182 "y.tab.c"
+	YYSTYPE;
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
 #endif
 
 
+
 /* Copy the second part of user declarations.  */
 
 
-/* Line 343 of yacc.c  */
-#line 208 "y.tab.c"
+/* Line 216 of yacc.c.  */
+#line 195 "y.tab.c"
 
 #ifdef short
 # undef short
@@ -279,14 +266,14 @@ typedef short int yytype_int16;
 #if (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 static int
-YYID (int yyi)
+YYID (int i)
 #else
 static int
-YYID (yyi)
-    int yyi;
+YYID (i)
+    int i;
 #endif
 {
-  return yyi;
+  return i;
 }
 #endif
 
@@ -307,11 +294,11 @@ YYID (yyi)
 #    define alloca _alloca
 #   else
 #    define YYSTACK_ALLOC alloca
-#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
+#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 #     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#     ifndef EXIT_SUCCESS
-#      define EXIT_SUCCESS 0
+#     ifndef _STDLIB_H
+#      define _STDLIB_H 1
 #     endif
 #    endif
 #   endif
@@ -334,24 +321,24 @@ YYID (yyi)
 #  ifndef YYSTACK_ALLOC_MAXIMUM
 #   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
 #  endif
-#  if (defined __cplusplus && ! defined EXIT_SUCCESS \
+#  if (defined __cplusplus && ! defined _STDLIB_H \
        && ! ((defined YYMALLOC || defined malloc) \
 	     && (defined YYFREE || defined free)))
 #   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#   ifndef EXIT_SUCCESS
-#    define EXIT_SUCCESS 0
+#   ifndef _STDLIB_H
+#    define _STDLIB_H 1
 #   endif
 #  endif
 #  ifndef YYMALLOC
 #   define YYMALLOC malloc
-#   if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
+#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
 #   endif
 #  endif
 #  ifndef YYFREE
 #   define YYFREE free
-#   if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
+#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 void free (void *); /* INFRINGES ON USER NAME SPACE */
 #   endif
@@ -367,9 +354,9 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */
 /* A type that is properly aligned for any stack member.  */
 union yyalloc
 {
-  yytype_int16 yyss_alloc;
-  YYSTYPE yyvs_alloc;
-};
+  yytype_int16 yyss;
+  YYSTYPE yyvs;
+  };
 
 /* The size of the maximum gap between one aligned stack and the next.  */
 # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
@@ -380,27 +367,6 @@ union yyalloc
      ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
       + YYSTACK_GAP_MAXIMUM)
 
-# define YYCOPY_NEEDED 1
-
-/* Relocate STACK from its old location to the new one.  The
-   local variables YYSIZE and YYSTACKSIZE give the old and new number of
-   elements in the stack, and YYPTR gives the new location of the
-   stack.  Advance YYPTR to a properly aligned location for the next
-   stack.  */
-# define YYSTACK_RELOCATE(Stack_alloc, Stack)				\
-    do									\
-      {									\
-	YYSIZE_T yynewbytes;						\
-	YYCOPY (&yyptr->Stack_alloc, Stack, yysize);			\
-	Stack = &yyptr->Stack_alloc;					\
-	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
-	yyptr += yynewbytes / sizeof (*yyptr);				\
-      }									\
-    while (YYID (0))
-
-#endif
-
-#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
 /* Copy COUNT objects from FROM to TO.  The source and destination do
    not overlap.  */
 # ifndef YYCOPY
@@ -418,21 +384,38 @@ union yyalloc
       while (YYID (0))
 #  endif
 # endif
-#endif /* !YYCOPY_NEEDED */
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack)					\
+    do									\
+      {									\
+	YYSIZE_T yynewbytes;						\
+	YYCOPY (&yyptr->Stack, Stack, yysize);				\
+	Stack = &yyptr->Stack;						\
+	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+	yyptr += yynewbytes / sizeof (*yyptr);				\
+      }									\
+    while (YYID (0))
+
+#endif
 
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  2
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   553
+#define YYLAST   537
 
 /* YYNTOKENS -- Number of terminals.  */
 #define YYNTOKENS  52
 /* YYNNTS -- Number of nonterminals.  */
 #define YYNNTS  39
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  130
+#define YYNRULES  131
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  262
+#define YYNSTATES  266
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
@@ -490,10 +473,10 @@ static const yytype_uint16 yyprhs[] =
      216,   218,   223,   226,   229,   231,   233,   235,   237,   239,
      241,   244,   247,   250,   253,   258,   264,   268,   271,   273,
      276,   280,   285,   287,   289,   291,   296,   301,   308,   318,
-     322,   326,   331,   337,   346,   348,   355,   361,   369,   370,
-     373,   376,   378,   380,   382,   384,   386,   389,   392,   395,
-     399,   401,   405,   409,   413,   417,   421,   426,   431,   435,
-     439
+     328,   332,   336,   341,   347,   356,   358,   365,   371,   379,
+     380,   383,   386,   388,   390,   392,   394,   396,   399,   402,
+     405,   409,   411,   415,   419,   423,   427,   431,   436,   441,
+     445,   449
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
@@ -530,7 +513,8 @@ static const yytype_int8 yyrhs[] =
        9,    29,     9,    29,    -1,    84,    -1,    85,    -1,    89,
       -1,    89,    48,    34,    49,    -1,    89,    48,    40,    49,
       -1,    89,    48,    34,    10,    89,    49,    -1,    89,    48,
-      34,    49,    48,    34,    10,    89,    49,    -1,    48,    34,
+      34,    49,    48,    34,    10,    89,    49,    -1,    89,    48,
+      34,    49,    48,    35,    10,    89,    49,    -1,    48,    34,
       49,    -1,    48,    40,    49,    -1,    89,    48,    35,    49,
       -1,    48,    34,    10,    89,    49,    -1,    48,    34,    49,
       48,    34,    10,    89,    49,    -1,    86,    -1,    86,    48,
@@ -559,10 +543,10 @@ static const yytype_uint16 yyrline[] =
      331,   334,   340,   349,   358,   363,   368,   373,   378,   383,
      390,   396,   407,   413,   419,   425,   431,   439,   448,   453,
      458,   463,   470,   471,   474,   480,   486,   492,   501,   510,
-     515,   520,   526,   534,   544,   548,   557,   564,   573,   576,
-     580,   586,   587,   591,   594,   595,   599,   603,   607,   611,
-     617,   618,   622,   626,   630,   634,   638,   642,   646,   650,
-     654
+     519,   524,   529,   535,   543,   553,   557,   566,   573,   582,
+     585,   589,   595,   596,   600,   603,   604,   608,   612,   616,
+     620,   626,   627,   631,   635,   639,   643,   647,   651,   655,
+     659,   663
 };
 #endif
 
@@ -577,12 +561,11 @@ static const char *const yytname[] =
   "LTYPEM", "LTYPEI", "LTYPEG", "LTYPEXC", "LTYPEX", "LCONST", "LFP",
   "LPC", "LSB", "LBREG", "LLREG", "LSREG", "LFREG", "LXREG", "LFCONST",
   "LSCONST", "LSP", "LNAME", "LLAB", "LVAR", "':'", "';'", "'='", "','",
-  "'('", "')'", "'$'", "'~'", "$accept", "prog", "$@1", "line", "$@2",
-  "$@3", "inst", "nonnon", "rimrem", "remrim", "rimnon", "nonrem",
-  "nonrel", "spec1", "spec2", "spec3", "spec4", "spec5", "spec6", "spec7",
-  "spec8", "spec9", "spec10", "rem", "rom", "rim", "rel", "reg", "imm",
-  "imm2", "con2", "mem", "omem", "nmem", "nam", "offset", "pointer", "con",
-  "expr", 0
+  "'('", "')'", "'$'", "'~'", "$accept", "prog", "@1", "line", "@2", "@3",
+  "inst", "nonnon", "rimrem", "remrim", "rimnon", "nonrem", "nonrel",
+  "spec1", "spec2", "spec3", "spec4", "spec5", "spec6", "spec7", "spec8",
+  "spec9", "spec10", "rem", "rom", "rim", "rel", "reg", "imm", "imm2",
+  "con2", "mem", "omem", "nmem", "nam", "offset", "pointer", "con", "expr", 0
 };
 #endif
 
@@ -613,10 +596,10 @@ static const yytype_uint8 yyr1[] =
       77,    78,    78,    78,    79,    79,    79,    79,    79,    79,
       80,    80,    80,    80,    80,    80,    80,    81,    82,    82,
       82,    82,    83,    83,    84,    84,    84,    84,    84,    84,
-      84,    84,    84,    84,    85,    85,    86,    86,    87,    87,
-      87,    88,    88,    88,    89,    89,    89,    89,    89,    89,
-      90,    90,    90,    90,    90,    90,    90,    90,    90,    90,
-      90
+      84,    84,    84,    84,    84,    85,    85,    86,    86,    87,
+      87,    87,    88,    88,    88,    89,    89,    89,    89,    89,
+      89,    90,    90,    90,    90,    90,    90,    90,    90,    90,
+      90,    90
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
@@ -631,45 +614,45 @@ static const yytype_uint8 yyr2[] =
        1,     1,     1,     1,     2,     2,     1,     1,     1,     1,
        1,     4,     2,     2,     1,     1,     1,     1,     1,     1,
        2,     2,     2,     2,     4,     5,     3,     2,     1,     2,
-       3,     4,     1,     1,     1,     4,     4,     6,     9,     3,
-       3,     4,     5,     8,     1,     6,     5,     7,     0,     2,
-       2,     1,     1,     1,     1,     1,     2,     2,     2,     3,
-       1,     3,     3,     3,     3,     3,     4,     4,     3,     3,
-       3
+       3,     4,     1,     1,     1,     4,     4,     6,     9,     9,
+       3,     3,     4,     5,     8,     1,     6,     5,     7,     0,
+       2,     2,     1,     1,     1,     1,     1,     2,     2,     2,
+       3,     1,     3,     3,     3,     3,     3,     4,     4,     3,
+       3,     3
 };
 
-/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
-   Performed when YYTABLE doesn't specify something else to do.  Zero
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
    means the default is an error.  */
 static const yytype_uint8 yydefact[] =
 {
        2,     3,     1,     0,     0,    30,     0,     0,     0,     0,
        0,     0,    30,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     9,     4,     0,    11,    31,    14,
-       0,     0,   114,    74,    76,    79,    75,    77,    78,   108,
-     115,     0,     0,     0,    15,    37,    60,    61,    92,    93,
-     104,    94,     0,    16,    69,    35,    70,    17,     0,    18,
-       0,     0,   108,   108,     0,    22,    45,    62,    66,    68,
-      67,    63,    94,    20,     0,    31,    47,    48,    23,   108,
+       0,     0,   115,    74,    76,    79,    75,    77,    78,   109,
+     116,     0,     0,     0,    15,    37,    60,    61,    92,    93,
+     105,    94,     0,    16,    69,    35,    70,    17,     0,    18,
+       0,     0,   109,   109,     0,    22,    45,    62,    66,    68,
+      67,    63,    94,    20,     0,    31,    47,    48,    23,   109,
        0,     0,    19,    39,     0,     0,    21,     0,    24,     0,
       25,     0,    26,    54,    27,     0,    28,     0,    29,     0,
-       7,     0,     5,     0,    10,   117,   116,     0,     0,     0,
-       0,    36,     0,     0,   120,     0,   118,     0,     0,     0,
+       7,     0,     5,     0,    10,   118,   117,     0,     0,     0,
+       0,    36,     0,     0,   121,     0,   119,     0,     0,     0,
       83,    82,     0,    81,    80,    34,     0,     0,    64,    65,
       46,    72,    73,     0,    44,     0,     0,    72,    38,     0,
        0,     0,     0,     0,    53,     0,     0,     0,     0,    12,
-       0,    13,   108,   109,   110,     0,     0,    99,   100,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,   119,
+       0,    13,   109,   110,   111,     0,     0,   100,   101,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,   120,
        0,     0,     0,     0,    86,     0,     0,    32,    33,     0,
        0,    40,     0,    42,     0,    49,    51,    55,    56,     0,
-       0,     0,     8,     6,     0,   113,   111,   112,     0,     0,
-       0,   130,   129,   128,     0,     0,   121,   122,   123,   124,
-     125,     0,     0,    95,   101,    96,     0,    84,    71,     0,
+       0,     0,     8,     6,     0,   114,   112,   113,     0,     0,
+       0,   131,   130,   129,     0,     0,   122,   123,   124,   125,
+     126,     0,     0,    95,   102,    96,     0,    84,    71,     0,
        0,    88,    87,     0,     0,     0,     0,     0,     0,     0,
-     106,   102,     0,   126,   127,     0,     0,     0,    85,    41,
+     107,   103,     0,   127,   128,     0,     0,     0,    85,    41,
       89,     0,    43,    50,    52,    57,    58,    59,     0,     0,
-     105,    97,     0,     0,    90,   107,     0,     0,    91,   103,
-       0,    98
+     106,    97,     0,     0,     0,    90,   108,     0,     0,     0,
+      91,   104,     0,     0,    98,    99
 };
 
 /* YYDEFGOTO[NTERM-NUM].  */
@@ -686,47 +669,48 @@ static const yytype_int16 yydefgoto[] =
 #define YYPACT_NINF -100
 static const yytype_int16 yypact[] =
 {
-    -100,    22,  -100,   165,   -32,   -22,   263,   286,   286,   332,
-     195,    -1,   309,   212,   414,   286,   286,   286,   414,    81,
+    -100,    22,  -100,   165,   -32,   -22,   265,   288,   288,   334,
+     195,    -1,   311,   212,   416,   288,   288,   288,   416,    81,
        7,   -16,    24,   -12,  -100,  -100,    -4,  -100,  -100,  -100,
-     485,   485,  -100,  -100,  -100,  -100,  -100,  -100,  -100,    39,
-    -100,   332,   385,   485,  -100,  -100,  -100,  -100,  -100,  -100,
-      46,    65,   370,  -100,  -100,    72,  -100,  -100,    75,  -100,
-      76,   332,    39,   102,   240,  -100,  -100,  -100,  -100,  -100,
-    -100,  -100,    77,  -100,   117,   332,  -100,  -100,  -100,   102,
-     408,   485,  -100,  -100,    83,    85,  -100,    89,  -100,    91,
-    -100,    92,  -100,    97,  -100,    98,  -100,   100,  -100,   101,
-    -100,   485,  -100,   485,  -100,  -100,  -100,   135,   485,   485,
-     104,  -100,    -6,   113,  -100,    71,  -100,   119,    32,   423,
-    -100,  -100,   438,  -100,  -100,  -100,   332,   286,  -100,  -100,
-    -100,   104,  -100,   355,  -100,    29,   485,  -100,  -100,   408,
-     146,   455,   332,   332,   332,   461,   332,   332,   165,   164,
-     165,   164,   102,  -100,  -100,     6,   485,   161,  -100,   485,
-     485,   485,   206,   207,   485,   485,   485,   485,   485,  -100,
-     203,     4,   166,   167,  -100,   470,   173,  -100,  -100,   174,
-     178,  -100,    15,  -100,   179,   183,   189,  -100,  -100,   187,
-     193,   197,  -100,  -100,   204,  -100,  -100,  -100,   202,   208,
-     222,   533,   541,    78,   485,   485,    95,    95,  -100,  -100,
-    -100,   485,   485,   210,  -100,  -100,   215,  -100,  -100,     7,
-     232,   256,  -100,   216,   233,   235,     7,   485,    81,   236,
-    -100,  -100,   268,   188,   188,   230,   237,   250,  -100,  -100,
-     276,   258,  -100,  -100,  -100,  -100,  -100,  -100,   244,   485,
-    -100,  -100,   279,   272,  -100,  -100,   253,   485,  -100,  -100,
-     259,  -100
+     469,   469,  -100,  -100,  -100,  -100,  -100,  -100,  -100,    39,
+    -100,   334,   387,   469,  -100,  -100,  -100,  -100,  -100,  -100,
+      46,    65,   372,  -100,  -100,    72,  -100,  -100,    83,  -100,
+      86,   334,    39,   102,   242,  -100,  -100,  -100,  -100,  -100,
+    -100,  -100,    77,  -100,   117,   334,  -100,  -100,  -100,   102,
+     410,   469,  -100,  -100,    89,    90,  -100,    92,  -100,    97,
+    -100,    98,  -100,   100,  -100,   101,  -100,   105,  -100,   106,
+    -100,   469,  -100,   469,  -100,  -100,  -100,   135,   469,   469,
+     114,  -100,    -6,   128,  -100,    71,  -100,   175,    32,   218,
+    -100,  -100,   425,  -100,  -100,  -100,   334,   288,  -100,  -100,
+    -100,   114,  -100,   357,  -100,    29,   469,  -100,  -100,   410,
+     181,   440,   334,   334,   334,   457,   334,   334,   165,   164,
+     165,   164,   102,  -100,  -100,     6,   469,   166,  -100,   469,
+     469,   469,   207,   208,   469,   469,   469,   469,   469,  -100,
+     206,     4,   173,   174,  -100,   463,   176,  -100,  -100,   184,
+     187,  -100,    15,  -100,   193,   200,   213,  -100,  -100,   211,
+     217,   220,  -100,  -100,   222,  -100,  -100,  -100,   216,   219,
+     238,   517,   525,    78,   469,   469,    95,    95,  -100,  -100,
+    -100,   469,   469,   232,  -100,  -100,   237,  -100,  -100,     7,
+     252,   278,  -100,   239,   254,   256,     7,   469,    81,   263,
+    -100,  -100,   293,   188,   188,   255,   258,    88,  -100,  -100,
+     300,   281,  -100,  -100,  -100,  -100,  -100,  -100,   262,   469,
+    -100,  -100,   304,   305,   289,  -100,  -100,   277,   469,   469,
+    -100,  -100,   283,   284,  -100,  -100
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int16 yypgoto[] =
 {
-    -100,  -100,  -100,   -99,  -100,  -100,  -100,   293,  -100,  -100,
-    -100,   295,  -100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,
-    -100,  -100,  -100,    17,   245,     0,    -7,    -9,    -8,    90,
+    -100,  -100,  -100,   -99,  -100,  -100,  -100,   315,  -100,  -100,
+    -100,   318,  -100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,
+    -100,  -100,  -100,    17,   270,     0,    -7,    -9,    -8,   112,
     -100,    13,     1,    -3,    -2,   -44,  -100,   -10,   -64
 };
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
    positive, shift that token.  If negative, reduce the rule which
-   number is the opposite.  If YYTABLE_NINF, syntax error.  */
+   number is the opposite.  If zero, do what YYDEFACT says.
+   If YYTABLE_NINF, syntax error.  */
 #define YYTABLE_NINF -1
 static const yytype_uint16 yytable[] =
 {
@@ -742,58 +726,50 @@ static const yytype_uint16 yytable[] =
      168,   114,   111,   114,   117,   201,   202,   203,   153,   154,
      206,   207,   208,   209,   210,   166,   167,   168,   194,   106,
      108,   109,   114,   118,    33,    34,    35,    36,    37,   125,
-     169,    38,   126,   127,   128,   135,   180,   178,   136,    85,
-     139,   184,   181,   140,   129,   189,   141,   188,   142,   143,
-     233,   234,   152,   177,   144,   145,   199,   146,   147,   114,
-     114,   114,   155,   170,   114,   114,   114,   114,   114,   185,
-     186,   187,   158,   190,   191,   106,     4,   159,   160,   161,
-     162,   163,   164,   165,   166,   167,   168,   179,     5,     6,
+     169,    38,   252,   253,   128,   135,   180,   178,   136,    85,
+     126,   184,   181,   127,   129,   189,   139,   188,   140,   141,
+     233,   234,   152,   177,   142,   143,   199,   144,   145,   114,
+     114,   114,   146,   147,   114,   114,   114,   114,   114,   185,
+     186,   187,   155,   190,   191,   106,     4,   159,   160,   161,
+     162,   163,   164,   165,   166,   167,   168,   158,     5,     6,
        7,     8,     9,    10,    11,    12,    13,    14,    15,    16,
       17,    18,    19,    20,   114,   114,   164,   165,   166,   167,
-     168,   235,   236,    30,    31,    61,    21,    22,    23,   200,
-      24,   239,   204,   211,   205,   214,   215,   246,   245,   247,
-      30,    31,   217,   218,    32,   219,   223,   224,    33,    34,
-      35,    36,    37,   225,   226,    38,    62,    63,    40,   256,
-     227,    32,    64,    42,   228,    52,    43,   260,    30,    31,
-     133,   230,   229,    79,    63,    40,   232,   231,   237,    80,
-      81,   240,    52,    43,   238,   241,   182,   243,   248,    32,
-     244,    30,    31,    33,    34,    35,    36,    37,   249,   250,
-      38,    62,    63,    40,   252,   253,   251,   254,    42,   257,
-      52,    43,    32,   255,    30,    31,    33,    34,    35,    36,
-      37,   258,   259,    38,    39,    76,    40,    77,   261,   134,
-      41,    42,     0,   242,    43,    32,     0,    30,    31,    33,
-      34,    35,    36,    37,     0,     0,    38,    39,     0,    40,
-       0,     0,     0,     0,    42,     0,    52,    43,    32,     0,
-      30,    31,    33,    34,    35,    36,    37,     0,     0,    38,
-      39,     0,    40,     0,     0,     0,    75,    42,     0,     0,
-      43,    32,     0,    30,    31,    33,    34,    35,    36,    37,
-       0,     0,    38,    39,     0,    40,     0,     0,    30,   119,
-      42,     0,     0,    43,    32,     0,     0,     0,    33,    34,
-      35,    36,    37,    30,    31,    38,     0,     0,    40,    32,
-       0,     0,     0,    42,     0,     0,    43,     0,   120,   121,
-       0,    39,     0,    40,    32,     0,    30,    31,   122,   112,
-       0,    43,    30,    31,     0,   113,     0,     0,    40,     0,
-       0,    30,    31,    81,     0,     0,    43,    32,     0,     0,
-       0,     0,     0,    32,     0,     0,    30,   175,     0,    79,
-      63,    40,    32,     0,     0,    39,    81,    40,     0,    43,
-       0,   174,    42,    30,    31,    43,    40,    32,     0,    30,
-      31,    81,     0,     0,    43,     0,   176,     0,    30,    31,
-       0,    40,     0,     0,    32,     0,    81,     0,     0,    43,
-      32,     0,     0,    30,    31,     0,     0,     0,    40,    32,
-       0,     0,     0,    81,    40,   182,    43,     0,   216,    81,
-       0,    52,    43,    40,    32,     0,     0,     0,    81,     0,
-       0,    43,     0,     0,     0,     0,     0,     0,    40,     0,
-       0,     0,     0,    81,     0,     0,    43,   160,   161,   162,
-     163,   164,   165,   166,   167,   168,   161,   162,   163,   164,
-     165,   166,   167,   168
+     168,   235,   236,    30,    31,    61,    21,    22,    23,   170,
+      24,   239,   179,   204,   200,   205,   211,   246,   245,   247,
+      30,    31,   214,   215,    32,   217,    30,    31,    33,    34,
+      35,    36,    37,   218,   219,    38,    62,    63,    40,   257,
+     223,    32,    64,    42,   224,    52,    43,    32,   262,   263,
+      30,    31,   133,    79,    63,    40,   174,   225,   226,    80,
+      81,    40,    52,    43,   227,   230,    81,   228,   231,    43,
+     229,    32,   232,    30,    31,    33,    34,    35,    36,    37,
+     237,   240,    38,    62,    63,    40,   238,   241,   243,   182,
+      42,   244,    52,    43,    32,   248,    30,    31,    33,    34,
+      35,    36,    37,   249,   250,    38,    39,   251,    40,   254,
+     255,   256,    41,    42,   258,   259,    43,    32,   260,    30,
+      31,    33,    34,    35,    36,    37,   261,    76,    38,    39,
+      77,    40,   264,   265,   134,   242,    42,     0,    52,    43,
+      32,     0,    30,    31,    33,    34,    35,    36,    37,     0,
+       0,    38,    39,     0,    40,     0,     0,     0,    75,    42,
+       0,     0,    43,    32,     0,    30,    31,    33,    34,    35,
+      36,    37,     0,     0,    38,    39,     0,    40,     0,     0,
+      30,   119,    42,     0,     0,    43,    32,     0,     0,     0,
+      33,    34,    35,    36,    37,    30,    31,    38,     0,     0,
+      40,    32,     0,     0,     0,    42,     0,     0,    43,     0,
+     120,   121,     0,    39,     0,    40,    32,     0,    30,    31,
+     122,   112,     0,    43,    30,    31,     0,   113,     0,     0,
+      40,     0,     0,    30,   175,    81,     0,     0,    43,    32,
+       0,     0,     0,     0,     0,    32,     0,     0,    30,    31,
+       0,    79,    63,    40,    32,     0,     0,    39,    81,    40,
+       0,    43,     0,   176,    42,    30,    31,    43,    40,    32,
+       0,    30,    31,    81,     0,     0,    43,    30,    31,     0,
+       0,     0,     0,    40,     0,     0,    32,     0,    81,     0,
+     182,    43,    32,     0,     0,     0,     0,     0,    32,     0,
+      40,   216,     0,     0,     0,    81,    40,    52,    43,     0,
+       0,    81,    40,     0,    43,     0,     0,    81,     0,     0,
+      43,   160,   161,   162,   163,   164,   165,   166,   167,   168,
+     161,   162,   163,   164,   165,   166,   167,   168
 };
 
-#define yypact_value_is_default(yystate) \
-  ((yystate) == (-100))
-
-#define yytable_value_is_error(yytable_value) \
-  YYID (0)
-
 static const yytype_int16 yycheck[] =
 {
       10,    10,    10,    13,    10,    13,    13,    10,     8,    11,
@@ -808,50 +784,48 @@ static const yytype_int16 yycheck[] =
       12,   101,    75,   103,    48,   159,   160,   161,   108,   109,
      164,   165,   166,   167,   168,    10,    11,    12,   152,   119,
        8,     9,   122,    48,    33,    34,    35,    36,    37,    47,
-      49,    40,    47,    47,   133,    48,   136,   127,    11,   139,
-      47,   141,   139,    48,   133,   145,    47,   145,    47,    47,
+      49,    40,    34,    35,   133,    48,   136,   127,    11,   139,
+      47,   141,   139,    47,   133,   145,    47,   145,    48,    47,
      204,   205,     7,   126,    47,    47,   156,    47,    47,   159,
-     160,   161,    48,    34,   164,   165,   166,   167,   168,   142,
-     143,   144,    49,   146,   147,   175,     1,     3,     4,     5,
-       6,     7,     8,     9,    10,    11,    12,    31,    13,    14,
+     160,   161,    47,    47,   164,   165,   166,   167,   168,   142,
+     143,   144,    48,   146,   147,   175,     1,     3,     4,     5,
+       6,     7,     8,     9,    10,    11,    12,    49,    13,    14,
       15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
       25,    26,    27,    28,   204,   205,     8,     9,    10,    11,
-      12,   211,   212,     8,     9,    10,    41,    42,    43,    48,
-      45,   219,     6,    10,     7,    49,    49,   227,   226,   228,
-       8,     9,    49,    49,    29,    47,    47,    44,    33,    34,
-      35,    36,    37,    44,    47,    40,    41,    42,    43,   249,
-      47,    29,    47,    48,    47,    50,    51,   257,     8,     9,
-      10,    49,    48,    41,    42,    43,    34,    49,    48,    47,
-      48,    29,    50,    51,    49,     9,    50,    34,    32,    29,
-      35,     8,     9,    33,    34,    35,    36,    37,    10,    49,
-      40,    41,    42,    43,    34,     9,    49,    29,    48,    10,
-      50,    51,    29,    49,     8,     9,    33,    34,    35,    36,
-      37,    29,    49,    40,    41,    12,    43,    12,    49,    64,
-      47,    48,    -1,   223,    51,    29,    -1,     8,     9,    33,
-      34,    35,    36,    37,    -1,    -1,    40,    41,    -1,    43,
-      -1,    -1,    -1,    -1,    48,    -1,    50,    51,    29,    -1,
-       8,     9,    33,    34,    35,    36,    37,    -1,    -1,    40,
-      41,    -1,    43,    -1,    -1,    -1,    47,    48,    -1,    -1,
-      51,    29,    -1,     8,     9,    33,    34,    35,    36,    37,
-      -1,    -1,    40,    41,    -1,    43,    -1,    -1,     8,     9,
-      48,    -1,    -1,    51,    29,    -1,    -1,    -1,    33,    34,
-      35,    36,    37,     8,     9,    40,    -1,    -1,    43,    29,
-      -1,    -1,    -1,    48,    -1,    -1,    51,    -1,    38,    39,
-      -1,    41,    -1,    43,    29,    -1,     8,     9,    48,    34,
-      -1,    51,     8,     9,    -1,    40,    -1,    -1,    43,    -1,
-      -1,     8,     9,    48,    -1,    -1,    51,    29,    -1,    -1,
-      -1,    -1,    -1,    29,    -1,    -1,     8,     9,    -1,    41,
-      42,    43,    29,    -1,    -1,    41,    48,    43,    -1,    51,
-      -1,    38,    48,     8,     9,    51,    43,    29,    -1,     8,
-       9,    48,    -1,    -1,    51,    -1,    38,    -1,     8,     9,
-      -1,    43,    -1,    -1,    29,    -1,    48,    -1,    -1,    51,
-      29,    -1,    -1,     8,     9,    -1,    -1,    -1,    43,    29,
-      -1,    -1,    -1,    48,    43,    50,    51,    -1,    38,    48,
-      -1,    50,    51,    43,    29,    -1,    -1,    -1,    48,    -1,
-      -1,    51,    -1,    -1,    -1,    -1,    -1,    -1,    43,    -1,
-      -1,    -1,    -1,    48,    -1,    -1,    51,     4,     5,     6,
-       7,     8,     9,    10,    11,    12,     5,     6,     7,     8,
-       9,    10,    11,    12
+      12,   211,   212,     8,     9,    10,    41,    42,    43,    34,
+      45,   219,    31,     6,    48,     7,    10,   227,   226,   228,
+       8,     9,    49,    49,    29,    49,     8,     9,    33,    34,
+      35,    36,    37,    49,    47,    40,    41,    42,    43,   249,
+      47,    29,    47,    48,    44,    50,    51,    29,   258,   259,
+       8,     9,    10,    41,    42,    43,    38,    44,    47,    47,
+      48,    43,    50,    51,    47,    49,    48,    47,    49,    51,
+      48,    29,    34,     8,     9,    33,    34,    35,    36,    37,
+      48,    29,    40,    41,    42,    43,    49,     9,    34,    50,
+      48,    35,    50,    51,    29,    32,     8,     9,    33,    34,
+      35,    36,    37,    10,    49,    40,    41,    49,    43,     9,
+      29,    49,    47,    48,    10,    10,    51,    29,    29,     8,
+       9,    33,    34,    35,    36,    37,    49,    12,    40,    41,
+      12,    43,    49,    49,    64,   223,    48,    -1,    50,    51,
+      29,    -1,     8,     9,    33,    34,    35,    36,    37,    -1,
+      -1,    40,    41,    -1,    43,    -1,    -1,    -1,    47,    48,
+      -1,    -1,    51,    29,    -1,     8,     9,    33,    34,    35,
+      36,    37,    -1,    -1,    40,    41,    -1,    43,    -1,    -1,
+       8,     9,    48,    -1,    -1,    51,    29,    -1,    -1,    -1,
+      33,    34,    35,    36,    37,     8,     9,    40,    -1,    -1,
+      43,    29,    -1,    -1,    -1,    48,    -1,    -1,    51,    -1,
+      38,    39,    -1,    41,    -1,    43,    29,    -1,     8,     9,
+      48,    34,    -1,    51,     8,     9,    -1,    40,    -1,    -1,
+      43,    -1,    -1,     8,     9,    48,    -1,    -1,    51,    29,
+      -1,    -1,    -1,    -1,    -1,    29,    -1,    -1,     8,     9,
+      -1,    41,    42,    43,    29,    -1,    -1,    41,    48,    43,
+      -1,    51,    -1,    38,    48,     8,     9,    51,    43,    29,
+      -1,     8,     9,    48,    -1,    -1,    51,     8,     9,    -1,
+      -1,    -1,    -1,    43,    -1,    -1,    29,    -1,    48,    -1,
+      50,    51,    29,    -1,    -1,    -1,    -1,    -1,    29,    -1,
+      43,    38,    -1,    -1,    -1,    48,    43,    50,    51,    -1,
+      -1,    48,    43,    -1,    51,    -1,    -1,    48,    -1,    -1,
+      51,     4,     5,     6,     7,     8,     9,    10,    11,    12,
+       5,     6,     7,     8,     9,    10,    11,    12
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
@@ -883,8 +857,8 @@ static const yytype_uint8 yystos[] =
        9,    29,    82,    47,    44,    44,    47,    47,    47,    48,
       49,    49,    34,    90,    90,    89,    89,    48,    49,    80,
       29,     9,    81,    34,    35,    80,    89,    79,    32,    10,
-      49,    49,    34,     9,    29,    49,    89,    10,    29,    49,
-      89,    49
+      49,    49,    34,    35,     9,    29,    49,    89,    10,    10,
+      29,    49,    89,    89,    49,    49
 };
 
 #define yyerrok		(yyerrstatus = 0)
@@ -899,18 +873,9 @@ static const yytype_uint8 yystos[] =
 
 /* Like YYERROR except do call yyerror.  This remains here temporarily
    to ease the transition to the new meaning of YYERROR, for GCC.
-   Once GCC version 2 has supplanted version 1, this can go.  However,
-   YYFAIL appears to be in use.  Nevertheless, it is formally deprecated
-   in Bison 2.4.2's NEWS entry, where a plan to phase it out is
-   discussed.  */
+   Once GCC version 2 has supplanted version 1, this can go.  */
 
 #define YYFAIL		goto yyerrlab
-#if defined YYFAIL
-  /* This is here to suppress warnings from the GCC cpp's
-     -Wunused-macros.  Normally we don't worry about that warning, but
-     some users do, and we want to make it easy for users to remove
-     YYFAIL uses, which will produce warnings from Bison 2.5.  */
-#endif
 
 #define YYRECOVERING()  (!!yyerrstatus)
 
@@ -920,6 +885,7 @@ do								\
     {								\
       yychar = (Token);						\
       yylval = (Value);						\
+      yytoken = YYTRANSLATE (yychar);				\
       YYPOPSTACK (1);						\
       goto yybackup;						\
     }								\
@@ -961,10 +927,19 @@ while (YYID (0))
 #endif
 
 
-/* This macro is provided for backward compatibility. */
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+   This macro was not mandated originally: define only if we know
+   we won't break user code: when these are the locations we know.  */
 
 #ifndef YY_LOCATION_PRINT
-# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+#  define YY_LOCATION_PRINT(File, Loc)			\
+     fprintf (File, "%d.%d-%d.%d",			\
+	      (Loc).first_line, (Loc).first_column,	\
+	      (Loc).last_line,  (Loc).last_column)
+# else
+#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
 #endif
 
 
@@ -1068,20 +1043,17 @@ yy_symbol_print (yyoutput, yytype, yyvaluep)
 #if (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 static void
-yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
 #else
 static void
-yy_stack_print (yybottom, yytop)
-    yytype_int16 *yybottom;
-    yytype_int16 *yytop;
+yy_stack_print (bottom, top)
+    yytype_int16 *bottom;
+    yytype_int16 *top;
 #endif
 {
   YYFPRINTF (stderr, "Stack now");
-  for (; yybottom <= yytop; yybottom++)
-    {
-      int yybot = *yybottom;
-      YYFPRINTF (stderr, " %d", yybot);
-    }
+  for (; bottom <= top; ++bottom)
+    YYFPRINTF (stderr, " %d", *bottom);
   YYFPRINTF (stderr, "\n");
 }
 
@@ -1115,11 +1087,11 @@ yy_reduce_print (yyvsp, yyrule)
   /* The symbols being reduced.  */
   for (yyi = 0; yyi < yynrhs; yyi++)
     {
-      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
+      fprintf (stderr, "   $%d = ", yyi + 1);
       yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
 		       &(yyvsp[(yyi + 1) - (yynrhs)])
 		       		       );
-      YYFPRINTF (stderr, "\n");
+      fprintf (stderr, "\n");
     }
 }
 
@@ -1156,6 +1128,7 @@ int yydebug;
 # define YYMAXDEPTH 10000
 #endif
 
+
 
 #if YYERROR_VERBOSE
 
@@ -1258,142 +1231,115 @@ yytnamerr (char *yyres, const char *yystr)
 }
 # endif
 
-/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
-   about the unexpected token YYTOKEN for the state stack whose top is
-   YYSSP.
-
-   Return 0 if *YYMSG was successfully written.  Return 1 if *YYMSG is
-   not large enough to hold the message.  In that case, also set
-   *YYMSG_ALLOC to the required number of bytes.  Return 2 if the
-   required number of bytes is too large to store.  */
-static int
-yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
-                yytype_int16 *yyssp, int yytoken)
+/* Copy into YYRESULT an error message about the unexpected token
+   YYCHAR while in state YYSTATE.  Return the number of bytes copied,
+   including the terminating null byte.  If YYRESULT is null, do not
+   copy anything; just return the number of bytes that would be
+   copied.  As a special case, return 0 if an ordinary "syntax error"
+   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
+   size calculation.  */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
 {
-  YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]);
-  YYSIZE_T yysize = yysize0;
-  YYSIZE_T yysize1;
-  enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
-  /* Internationalized format string. */
-  const char *yyformat = 0;
-  /* Arguments of yyformat. */
-  char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
-  /* Number of reported tokens (one for the "unexpected", one per
-     "expected"). */
-  int yycount = 0;
-
-  /* There are many possibilities here to consider:
-     - Assume YYFAIL is not used.  It's too flawed to consider.  See
-       <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html>
-       for details.  YYERROR is fine as it does not invoke this
-       function.
-     - If this state is a consistent state with a default action, then
-       the only way this function was invoked is if the default action
-       is an error action.  In that case, don't check for expected
-       tokens because there are none.
-     - The only way there can be no lookahead present (in yychar) is if
-       this state is a consistent state with a default action.  Thus,
-       detecting the absence of a lookahead is sufficient to determine
-       that there is no unexpected or expected token to report.  In that
-       case, just report a simple "syntax error".
-     - Don't assume there isn't a lookahead just because this state is a
-       consistent state with a default action.  There might have been a
-       previous inconsistent state, consistent state with a non-default
-       action, or user semantic action that manipulated yychar.
-     - Of course, the expected token list depends on states to have
-       correct lookahead information, and it depends on the parser not
-       to perform extra reductions after fetching a lookahead from the
-       scanner and before detecting a syntax error.  Thus, state merging
-       (from LALR or IELR) and default reductions corrupt the expected
-       token list.  However, the list is correct for canonical LR with
-       one exception: it will still contain any token that will not be
-       accepted due to an error action in a later state.
-  */
-  if (yytoken != YYEMPTY)
-    {
-      int yyn = yypact[*yyssp];
-      yyarg[yycount++] = yytname[yytoken];
-      if (!yypact_value_is_default (yyn))
-        {
-          /* Start YYX at -YYN if negative to avoid negative indexes in
-             YYCHECK.  In other words, skip the first -YYN actions for
-             this state because they are default actions.  */
-          int yyxbegin = yyn < 0 ? -yyn : 0;
-          /* Stay within bounds of both yycheck and yytname.  */
-          int yychecklim = YYLAST - yyn + 1;
-          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
-          int yyx;
-
-          for (yyx = yyxbegin; yyx < yyxend; ++yyx)
-            if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
-                && !yytable_value_is_error (yytable[yyx + yyn]))
-              {
-                if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
-                  {
-                    yycount = 1;
-                    yysize = yysize0;
-                    break;
-                  }
-                yyarg[yycount++] = yytname[yyx];
-                yysize1 = yysize + yytnamerr (0, yytname[yyx]);
-                if (! (yysize <= yysize1
-                       && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
-                  return 2;
-                yysize = yysize1;
-              }
-        }
-    }
+  int yyn = yypact[yystate];
 
-  switch (yycount)
-    {
-# define YYCASE_(N, S)                      \
-      case N:                               \
-        yyformat = S;                       \
-      break
-      YYCASE_(0, YY_("syntax error"));
-      YYCASE_(1, YY_("syntax error, unexpected %s"));
-      YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
-      YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
-      YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
-      YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
-# undef YYCASE_
-    }
+  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+    return 0;
+  else
+    {
+      int yytype = YYTRANSLATE (yychar);
+      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+      YYSIZE_T yysize = yysize0;
+      YYSIZE_T yysize1;
+      int yysize_overflow = 0;
+      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+      int yyx;
+
+# if 0
+      /* This is so xgettext sees the translatable formats that are
+	 constructed on the fly.  */
+      YY_("syntax error, unexpected %s");
+      YY_("syntax error, unexpected %s, expecting %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+      char *yyfmt;
+      char const *yyf;
+      static char const yyunexpected[] = "syntax error, unexpected %s";
+      static char const yyexpecting[] = ", expecting %s";
+      static char const yyor[] = " or %s";
+      char yyformat[sizeof yyunexpected
+		    + sizeof yyexpecting - 1
+		    + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+		       * (sizeof yyor - 1))];
+      char const *yyprefix = yyexpecting;
+
+      /* Start YYX at -YYN if negative to avoid negative indexes in
+	 YYCHECK.  */
+      int yyxbegin = yyn < 0 ? -yyn : 0;
+
+      /* Stay within bounds of both yycheck and yytname.  */
+      int yychecklim = YYLAST - yyn + 1;
+      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+      int yycount = 1;
+
+      yyarg[0] = yytname[yytype];
+      yyfmt = yystpcpy (yyformat, yyunexpected);
+
+      for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+	if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+	  {
+	    if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+	      {
+		yycount = 1;
+		yysize = yysize0;
+		yyformat[sizeof yyunexpected - 1] = '\0';
+		break;
+	      }
+	    yyarg[yycount++] = yytname[yyx];
+	    yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+	    yysize_overflow |= (yysize1 < yysize);
+	    yysize = yysize1;
+	    yyfmt = yystpcpy (yyfmt, yyprefix);
+	    yyprefix = yyor;
+	  }
 
-  yysize1 = yysize + yystrlen (yyformat);
-  if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
-    return 2;
-  yysize = yysize1;
+      yyf = YY_(yyformat);
+      yysize1 = yysize + yystrlen (yyf);
+      yysize_overflow |= (yysize1 < yysize);
+      yysize = yysize1;
 
-  if (*yymsg_alloc < yysize)
-    {
-      *yymsg_alloc = 2 * yysize;
-      if (! (yysize <= *yymsg_alloc
-             && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
-        *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
-      return 1;
-    }
+      if (yysize_overflow)
+	return YYSIZE_MAXIMUM;
 
-  /* Avoid sprintf, as that infringes on the user's name space.
-     Don't have undefined behavior even if the translation
-     produced a string with the wrong number of "%s"s.  */
-  {
-    char *yyp = *yymsg;
-    int yyi = 0;
-    while ((*yyp = *yyformat) != '\0')
-      if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
-        {
-          yyp += yytnamerr (yyp, yyarg[yyi++]);
-          yyformat += 2;
-        }
-      else
-        {
-          yyp++;
-          yyformat++;
-        }
-  }
-  return 0;
+      if (yyresult)
+	{
+	  /* Avoid sprintf, as that infringes on the user's name space.
+	     Don't have undefined behavior even if the translation
+	     produced a string with the wrong number of "%s"s.  */
+	  char *yyp = yyresult;
+	  int yyi = 0;
+	  while ((*yyp = *yyf) != '\0')
+	    {
+	      if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+		{
+		  yyp += yytnamerr (yyp, yyarg[yyi++]);
+		  yyf += 2;
+		}
+	      else
+		{
+		  yyp++;
+		  yyf++;
+		}
+	    }
+	}
+      return yysize;
+    }
 }
 #endif /* YYERROR_VERBOSE */
+
 
 /*-----------------------------------------------.
 | Release the memory associated to this symbol.  |
@@ -1425,9 +1371,10 @@ yydestruct (yymsg, yytype, yyvaluep)
 	break;
     }
 }
-
+
 
 /* Prevent warnings from -Wmissing-prototypes.  */
+
 #ifdef YYPARSE_PARAM
 #if defined __STDC__ || defined __cplusplus
 int yyparse (void *YYPARSE_PARAM);
@@ -1443,16 +1390,18 @@ int yyparse ();
 #endif /* ! YYPARSE_PARAM */
 
 
-/* The lookahead symbol.  */
+
+/* The look-ahead symbol.  */
 int yychar;
 
-/* The semantic value of the lookahead symbol.  */
+/* The semantic value of the look-ahead symbol.  */
 YYSTYPE yylval;
 
 /* Number of syntax errors so far.  */
 int yynerrs;
 
 
+
 /*----------.
 | yyparse.  |
 `----------*/
@@ -1479,37 +1428,14 @@ yyparse ()
 #endif
 #endif
 {
-    int yystate;
-    /* Number of tokens to shift before error messages enabled.  */
-    int yyerrstatus;
-
-    /* The stacks and their tools:
-       `yyss': related to states.
-       `yyvs': related to semantic values.
-
-       Refer to the stacks thru separate pointers, to allow yyoverflow
-       to reallocate them elsewhere.  */
-
-    /* The state stack.  */
-    yytype_int16 yyssa[YYINITDEPTH];
-    yytype_int16 *yyss;
-    yytype_int16 *yyssp;
-
-    /* The semantic value stack.  */
-    YYSTYPE yyvsa[YYINITDEPTH];
-    YYSTYPE *yyvs;
-    YYSTYPE *yyvsp;
-
-    YYSIZE_T yystacksize;
-
+  
+  int yystate;
   int yyn;
   int yyresult;
-  /* Lookahead token as an internal (translated) token number.  */
-  int yytoken;
-  /* The variables used to return semantic value and location from the
-     action routines.  */
-  YYSTYPE yyval;
-
+  /* Number of tokens to shift before error messages enabled.  */
+  int yyerrstatus;
+  /* Look-ahead token as an internal (translated) token number.  */
+  int yytoken = 0;
 #if YYERROR_VERBOSE
   /* Buffer for error messages, and its allocated size.  */
   char yymsgbuf[128];
@@ -1517,28 +1443,51 @@ yyparse ()
   YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
 #endif
 
+  /* Three stacks and their tools:
+     `yyss': related to states,
+     `yyvs': related to semantic values,
+     `yyls': related to locations.
+
+     Refer to the stacks thru separate pointers, to allow yyoverflow
+     to reallocate them elsewhere.  */
+
+  /* The state stack.  */
+  yytype_int16 yyssa[YYINITDEPTH];
+  yytype_int16 *yyss = yyssa;
+  yytype_int16 *yyssp;
+
+  /* The semantic value stack.  */
+  YYSTYPE yyvsa[YYINITDEPTH];
+  YYSTYPE *yyvs = yyvsa;
+  YYSTYPE *yyvsp;
+
+
+
 #define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
 
+  YYSIZE_T yystacksize = YYINITDEPTH;
+
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+
+
   /* The number of symbols on the RHS of the reduced rule.
      Keep to zero when no symbol should be popped.  */
   int yylen = 0;
 
-  yytoken = 0;
-  yyss = yyssa;
-  yyvs = yyvsa;
-  yystacksize = YYINITDEPTH;
-
   YYDPRINTF ((stderr, "Starting parse\n"));
 
   yystate = 0;
   yyerrstatus = 0;
   yynerrs = 0;
-  yychar = YYEMPTY; /* Cause a token to be read.  */
+  yychar = YYEMPTY;		/* Cause a token to be read.  */
 
   /* Initialize stack pointers.
      Waste one element of value and location stack
      so that they stay on the same level as the state stack.
      The wasted elements are never initialized.  */
+
   yyssp = yyss;
   yyvsp = yyvs;
 
@@ -1568,6 +1517,7 @@ yyparse ()
 	YYSTYPE *yyvs1 = yyvs;
 	yytype_int16 *yyss1 = yyss;
 
+
 	/* Each stack pointer address is followed by the size of the
 	   data in use in that stack, in bytes.  This used to be a
 	   conditional around just the two extra args, but that might
@@ -1575,6 +1525,7 @@ yyparse ()
 	yyoverflow (YY_("memory exhausted"),
 		    &yyss1, yysize * sizeof (*yyssp),
 		    &yyvs1, yysize * sizeof (*yyvsp),
+
 		    &yystacksize);
 
 	yyss = yyss1;
@@ -1597,8 +1548,9 @@ yyparse ()
 	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
 	if (! yyptr)
 	  goto yyexhaustedlab;
-	YYSTACK_RELOCATE (yyss_alloc, yyss);
-	YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+	YYSTACK_RELOCATE (yyss);
+	YYSTACK_RELOCATE (yyvs);
+
 #  undef YYSTACK_RELOCATE
 	if (yyss1 != yyssa)
 	  YYSTACK_FREE (yyss1);
@@ -1609,6 +1561,7 @@ yyparse ()
       yyssp = yyss + yysize - 1;
       yyvsp = yyvs + yysize - 1;
 
+
       YYDPRINTF ((stderr, "Stack size increased to %lu\n",
 		  (unsigned long int) yystacksize));
 
@@ -1618,9 +1571,6 @@ yyparse ()
 
   YYDPRINTF ((stderr, "Entering state %d\n", yystate));
 
-  if (yystate == YYFINAL)
-    YYACCEPT;
-
   goto yybackup;
 
 /*-----------.
@@ -1629,16 +1579,16 @@ yyparse ()
 yybackup:
 
   /* Do appropriate processing given the current state.  Read a
-     lookahead token if we need one and don't already have one.  */
+     look-ahead token if we need one and don't already have one.  */
 
-  /* First try to decide what to do without reference to lookahead token.  */
+  /* First try to decide what to do without reference to look-ahead token.  */
   yyn = yypact[yystate];
-  if (yypact_value_is_default (yyn))
+  if (yyn == YYPACT_NINF)
     goto yydefault;
 
-  /* Not known => get a lookahead token if don't already have one.  */
+  /* Not known => get a look-ahead token if don't already have one.  */
 
-  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol.  */
   if (yychar == YYEMPTY)
     {
       YYDPRINTF ((stderr, "Reading a token: "));
@@ -1664,22 +1614,26 @@ yybackup:
   yyn = yytable[yyn];
   if (yyn <= 0)
     {
-      if (yytable_value_is_error (yyn))
-        goto yyerrlab;
+      if (yyn == 0 || yyn == YYTABLE_NINF)
+	goto yyerrlab;
       yyn = -yyn;
       goto yyreduce;
     }
 
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
   /* Count tokens shifted since error; after three, turn off error
      status.  */
   if (yyerrstatus)
     yyerrstatus--;
 
-  /* Shift the lookahead token.  */
+  /* Shift the look-ahead token.  */
   YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
 
-  /* Discard the shifted token.  */
-  yychar = YYEMPTY;
+  /* Discard the shifted token unless it is eof.  */
+  if (yychar != YYEOF)
+    yychar = YYEMPTY;
 
   yystate = yyn;
   *++yyvsp = yylval;
@@ -1719,8 +1673,6 @@ yyreduce:
   switch (yyn)
     {
         case 3:
-
-/* Line 1806 of yacc.c  */
 #line 70 "a.y"
     {
 		stmtline = lineno;
@@ -1728,8 +1680,6 @@ yyreduce:
     break;
 
   case 5:
-
-/* Line 1806 of yacc.c  */
 #line 77 "a.y"
     {
 		if((yyvsp[(1) - (2)].sym)->value != pc)
@@ -1739,8 +1689,6 @@ yyreduce:
     break;
 
   case 7:
-
-/* Line 1806 of yacc.c  */
 #line 84 "a.y"
     {
 		(yyvsp[(1) - (2)].sym)->type = LLAB;
@@ -1749,8 +1697,6 @@ yyreduce:
     break;
 
   case 12:
-
-/* Line 1806 of yacc.c  */
 #line 95 "a.y"
     {
 		(yyvsp[(1) - (3)].sym)->type = LVAR;
@@ -1759,8 +1705,6 @@ yyreduce:
     break;
 
   case 13:
-
-/* Line 1806 of yacc.c  */
 #line 100 "a.y"
     {
 		if((yyvsp[(1) - (3)].sym)->value != (yyvsp[(3) - (3)].lval))
@@ -1770,120 +1714,86 @@ yyreduce:
     break;
 
   case 14:
-
-/* Line 1806 of yacc.c  */
 #line 105 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
     break;
 
   case 15:
-
-/* Line 1806 of yacc.c  */
 #line 106 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
     break;
 
   case 16:
-
-/* Line 1806 of yacc.c  */
 #line 107 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
     break;
 
   case 17:
-
-/* Line 1806 of yacc.c  */
 #line 108 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
     break;
 
   case 18:
-
-/* Line 1806 of yacc.c  */
 #line 109 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
     break;
 
   case 19:
-
-/* Line 1806 of yacc.c  */
 #line 110 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
     break;
 
   case 20:
-
-/* Line 1806 of yacc.c  */
 #line 111 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
     break;
 
   case 21:
-
-/* Line 1806 of yacc.c  */
 #line 112 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
     break;
 
   case 22:
-
-/* Line 1806 of yacc.c  */
 #line 113 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
     break;
 
   case 23:
-
-/* Line 1806 of yacc.c  */
 #line 114 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
     break;
 
   case 24:
-
-/* Line 1806 of yacc.c  */
 #line 115 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
     break;
 
   case 25:
-
-/* Line 1806 of yacc.c  */
 #line 116 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
     break;
 
   case 26:
-
-/* Line 1806 of yacc.c  */
 #line 117 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
     break;
 
   case 27:
-
-/* Line 1806 of yacc.c  */
 #line 118 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
     break;
 
   case 28:
-
-/* Line 1806 of yacc.c  */
 #line 119 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
     break;
 
   case 29:
-
-/* Line 1806 of yacc.c  */
 #line 120 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
     break;
 
   case 30:
-
-/* Line 1806 of yacc.c  */
 #line 123 "a.y"
     {
 		(yyval.gen2).from = nullgen;
@@ -1892,8 +1802,6 @@ yyreduce:
     break;
 
   case 31:
-
-/* Line 1806 of yacc.c  */
 #line 128 "a.y"
     {
 		(yyval.gen2).from = nullgen;
@@ -1902,8 +1810,6 @@ yyreduce:
     break;
 
   case 32:
-
-/* Line 1806 of yacc.c  */
 #line 135 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
@@ -1912,8 +1818,6 @@ yyreduce:
     break;
 
   case 33:
-
-/* Line 1806 of yacc.c  */
 #line 142 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
@@ -1922,8 +1826,6 @@ yyreduce:
     break;
 
   case 34:
-
-/* Line 1806 of yacc.c  */
 #line 149 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (2)].gen);
@@ -1932,8 +1834,6 @@ yyreduce:
     break;
 
   case 35:
-
-/* Line 1806 of yacc.c  */
 #line 154 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (1)].gen);
@@ -1942,8 +1842,6 @@ yyreduce:
     break;
 
   case 36:
-
-/* Line 1806 of yacc.c  */
 #line 161 "a.y"
     {
 		(yyval.gen2).from = nullgen;
@@ -1952,8 +1850,6 @@ yyreduce:
     break;
 
   case 37:
-
-/* Line 1806 of yacc.c  */
 #line 166 "a.y"
     {
 		(yyval.gen2).from = nullgen;
@@ -1962,8 +1858,6 @@ yyreduce:
     break;
 
   case 38:
-
-/* Line 1806 of yacc.c  */
 #line 173 "a.y"
     {
 		(yyval.gen2).from = nullgen;
@@ -1972,8 +1866,6 @@ yyreduce:
     break;
 
   case 39:
-
-/* Line 1806 of yacc.c  */
 #line 178 "a.y"
     {
 		(yyval.gen2).from = nullgen;
@@ -1982,8 +1874,6 @@ yyreduce:
     break;
 
   case 40:
-
-/* Line 1806 of yacc.c  */
 #line 183 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
@@ -1992,8 +1882,6 @@ yyreduce:
     break;
 
   case 41:
-
-/* Line 1806 of yacc.c  */
 #line 190 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (5)].gen);
@@ -2003,8 +1891,6 @@ yyreduce:
     break;
 
   case 42:
-
-/* Line 1806 of yacc.c  */
 #line 198 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
@@ -2013,8 +1899,6 @@ yyreduce:
     break;
 
   case 43:
-
-/* Line 1806 of yacc.c  */
 #line 203 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (5)].gen);
@@ -2024,8 +1908,6 @@ yyreduce:
     break;
 
   case 44:
-
-/* Line 1806 of yacc.c  */
 #line 211 "a.y"
     {
 		(yyval.gen2).from = nullgen;
@@ -2034,8 +1916,6 @@ yyreduce:
     break;
 
   case 45:
-
-/* Line 1806 of yacc.c  */
 #line 216 "a.y"
     {
 		(yyval.gen2).from = nullgen;
@@ -2044,8 +1924,6 @@ yyreduce:
     break;
 
   case 46:
-
-/* Line 1806 of yacc.c  */
 #line 221 "a.y"
     {
 		(yyval.gen2).from = nullgen;
@@ -2056,8 +1934,6 @@ yyreduce:
     break;
 
   case 49:
-
-/* Line 1806 of yacc.c  */
 #line 234 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
@@ -2066,8 +1942,6 @@ yyreduce:
     break;
 
   case 50:
-
-/* Line 1806 of yacc.c  */
 #line 239 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (5)].gen);
@@ -2079,8 +1953,6 @@ yyreduce:
     break;
 
   case 51:
-
-/* Line 1806 of yacc.c  */
 #line 249 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
@@ -2089,8 +1961,6 @@ yyreduce:
     break;
 
   case 52:
-
-/* Line 1806 of yacc.c  */
 #line 254 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (5)].gen);
@@ -2102,8 +1972,6 @@ yyreduce:
     break;
 
   case 53:
-
-/* Line 1806 of yacc.c  */
 #line 264 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (2)].gen);
@@ -2112,8 +1980,6 @@ yyreduce:
     break;
 
   case 54:
-
-/* Line 1806 of yacc.c  */
 #line 269 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (1)].gen);
@@ -2122,8 +1988,6 @@ yyreduce:
     break;
 
   case 55:
-
-/* Line 1806 of yacc.c  */
 #line 274 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
@@ -2132,8 +1996,6 @@ yyreduce:
     break;
 
   case 56:
-
-/* Line 1806 of yacc.c  */
 #line 281 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
@@ -2142,8 +2004,6 @@ yyreduce:
     break;
 
   case 57:
-
-/* Line 1806 of yacc.c  */
 #line 286 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (5)].gen);
@@ -2153,8 +2013,6 @@ yyreduce:
     break;
 
   case 58:
-
-/* Line 1806 of yacc.c  */
 #line 294 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (5)].gen);
@@ -2164,8 +2022,6 @@ yyreduce:
     break;
 
   case 59:
-
-/* Line 1806 of yacc.c  */
 #line 302 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(3) - (5)].gen);
@@ -2177,8 +2033,6 @@ yyreduce:
     break;
 
   case 64:
-
-/* Line 1806 of yacc.c  */
 #line 318 "a.y"
     {
 		(yyval.gen) = (yyvsp[(2) - (2)].gen);
@@ -2186,8 +2040,6 @@ yyreduce:
     break;
 
   case 65:
-
-/* Line 1806 of yacc.c  */
 #line 322 "a.y"
     {
 		(yyval.gen) = (yyvsp[(2) - (2)].gen);
@@ -2195,8 +2047,6 @@ yyreduce:
     break;
 
   case 71:
-
-/* Line 1806 of yacc.c  */
 #line 335 "a.y"
     {
 		(yyval.gen) = nullgen;
@@ -2206,8 +2056,6 @@ yyreduce:
     break;
 
   case 72:
-
-/* Line 1806 of yacc.c  */
 #line 341 "a.y"
     {
 		(yyval.gen) = nullgen;
@@ -2220,8 +2068,6 @@ yyreduce:
     break;
 
   case 73:
-
-/* Line 1806 of yacc.c  */
 #line 350 "a.y"
     {
 		(yyval.gen) = nullgen;
@@ -2232,8 +2078,6 @@ yyreduce:
     break;
 
   case 74:
-
-/* Line 1806 of yacc.c  */
 #line 359 "a.y"
     {
 		(yyval.gen) = nullgen;
@@ -2242,8 +2086,6 @@ yyreduce:
     break;
 
   case 75:
-
-/* Line 1806 of yacc.c  */
 #line 364 "a.y"
     {
 		(yyval.gen) = nullgen;
@@ -2252,8 +2094,6 @@ yyreduce:
     break;
 
   case 76:
-
-/* Line 1806 of yacc.c  */
 #line 369 "a.y"
     {
 		(yyval.gen) = nullgen;
@@ -2262,8 +2102,6 @@ yyreduce:
     break;
 
   case 77:
-
-/* Line 1806 of yacc.c  */
 #line 374 "a.y"
     {
 		(yyval.gen) = nullgen;
@@ -2272,8 +2110,6 @@ yyreduce:
     break;
 
   case 78:
-
-/* Line 1806 of yacc.c  */
 #line 379 "a.y"
     {
 		(yyval.gen) = nullgen;
@@ -2282,8 +2118,6 @@ yyreduce:
     break;
 
   case 79:
-
-/* Line 1806 of yacc.c  */
 #line 384 "a.y"
     {
 		(yyval.gen) = nullgen;
@@ -2292,8 +2126,6 @@ yyreduce:
     break;
 
   case 80:
-
-/* Line 1806 of yacc.c  */
 #line 391 "a.y"
     {
 		(yyval.gen) = nullgen;
@@ -2303,8 +2135,6 @@ yyreduce:
     break;
 
   case 81:
-
-/* Line 1806 of yacc.c  */
 #line 397 "a.y"
     {
 		(yyval.gen) = (yyvsp[(2) - (2)].gen);
@@ -2319,8 +2149,6 @@ yyreduce:
     break;
 
   case 82:
-
-/* Line 1806 of yacc.c  */
 #line 408 "a.y"
     {
 		(yyval.gen) = nullgen;
@@ -2330,8 +2158,6 @@ yyreduce:
     break;
 
   case 83:
-
-/* Line 1806 of yacc.c  */
 #line 414 "a.y"
     {
 		(yyval.gen) = nullgen;
@@ -2341,8 +2167,6 @@ yyreduce:
     break;
 
   case 84:
-
-/* Line 1806 of yacc.c  */
 #line 420 "a.y"
     {
 		(yyval.gen) = nullgen;
@@ -2352,8 +2176,6 @@ yyreduce:
     break;
 
   case 85:
-
-/* Line 1806 of yacc.c  */
 #line 426 "a.y"
     {
 		(yyval.gen) = nullgen;
@@ -2363,8 +2185,6 @@ yyreduce:
     break;
 
   case 86:
-
-/* Line 1806 of yacc.c  */
 #line 432 "a.y"
     {
 		(yyval.gen) = nullgen;
@@ -2374,8 +2194,6 @@ yyreduce:
     break;
 
   case 87:
-
-/* Line 1806 of yacc.c  */
 #line 440 "a.y"
     {
 		(yyval.gen) = nullgen;
@@ -2386,8 +2204,6 @@ yyreduce:
     break;
 
   case 88:
-
-/* Line 1806 of yacc.c  */
 #line 449 "a.y"
     {
 		(yyval.con2).v1 = (yyvsp[(1) - (1)].lval);
@@ -2396,8 +2212,6 @@ yyreduce:
     break;
 
   case 89:
-
-/* Line 1806 of yacc.c  */
 #line 454 "a.y"
     {
 		(yyval.con2).v1 = -(yyvsp[(2) - (2)].lval);
@@ -2406,8 +2220,6 @@ yyreduce:
     break;
 
   case 90:
-
-/* Line 1806 of yacc.c  */
 #line 459 "a.y"
     {
 		(yyval.con2).v1 = (yyvsp[(1) - (3)].lval);
@@ -2416,8 +2228,6 @@ yyreduce:
     break;
 
   case 91:
-
-/* Line 1806 of yacc.c  */
 #line 464 "a.y"
     {
 		(yyval.con2).v1 = -(yyvsp[(2) - (4)].lval);
@@ -2426,8 +2236,6 @@ yyreduce:
     break;
 
   case 94:
-
-/* Line 1806 of yacc.c  */
 #line 475 "a.y"
     {
 		(yyval.gen) = nullgen;
@@ -2437,8 +2245,6 @@ yyreduce:
     break;
 
   case 95:
-
-/* Line 1806 of yacc.c  */
 #line 481 "a.y"
     {
 		(yyval.gen) = nullgen;
@@ -2448,8 +2254,6 @@ yyreduce:
     break;
 
   case 96:
-
-/* Line 1806 of yacc.c  */
 #line 487 "a.y"
     {
 		(yyval.gen) = nullgen;
@@ -2459,8 +2263,6 @@ yyreduce:
     break;
 
   case 97:
-
-/* Line 1806 of yacc.c  */
 #line 493 "a.y"
     {
 		(yyval.gen) = nullgen;
@@ -2473,8 +2275,6 @@ yyreduce:
     break;
 
   case 98:
-
-/* Line 1806 of yacc.c  */
 #line 502 "a.y"
     {
 		(yyval.gen) = nullgen;
@@ -2487,29 +2287,35 @@ yyreduce:
     break;
 
   case 99:
-
-/* Line 1806 of yacc.c  */
 #line 511 "a.y"
     {
 		(yyval.gen) = nullgen;
-		(yyval.gen).type = D_INDIR+(yyvsp[(2) - (3)].lval);
+		(yyval.gen).type = D_INDIR+(yyvsp[(3) - (9)].lval);
+		(yyval.gen).offset = (yyvsp[(1) - (9)].lval);
+		(yyval.gen).index = (yyvsp[(6) - (9)].lval);
+		(yyval.gen).scale = (yyvsp[(8) - (9)].lval);
+		checkscale((yyval.gen).scale);
 	}
     break;
 
   case 100:
-
-/* Line 1806 of yacc.c  */
-#line 516 "a.y"
+#line 520 "a.y"
     {
 		(yyval.gen) = nullgen;
-		(yyval.gen).type = D_INDIR+D_SP;
+		(yyval.gen).type = D_INDIR+(yyvsp[(2) - (3)].lval);
 	}
     break;
 
   case 101:
+#line 525 "a.y"
+    {
+		(yyval.gen) = nullgen;
+		(yyval.gen).type = D_INDIR+D_SP;
+	}
+    break;
 
-/* Line 1806 of yacc.c  */
-#line 521 "a.y"
+  case 102:
+#line 530 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_INDIR+(yyvsp[(3) - (4)].lval);
@@ -2517,10 +2323,8 @@ yyreduce:
 	}
     break;
 
-  case 102:
-
-/* Line 1806 of yacc.c  */
-#line 527 "a.y"
+  case 103:
+#line 536 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_INDIR+D_NONE;
@@ -2530,10 +2334,8 @@ yyreduce:
 	}
     break;
 
-  case 103:
-
-/* Line 1806 of yacc.c  */
-#line 535 "a.y"
+  case 104:
+#line 544 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_INDIR+(yyvsp[(2) - (8)].lval);
@@ -2543,19 +2345,15 @@ yyreduce:
 	}
     break;
 
-  case 104:
-
-/* Line 1806 of yacc.c  */
-#line 545 "a.y"
+  case 105:
+#line 554 "a.y"
     {
 		(yyval.gen) = (yyvsp[(1) - (1)].gen);
 	}
     break;
 
-  case 105:
-
-/* Line 1806 of yacc.c  */
-#line 549 "a.y"
+  case 106:
+#line 558 "a.y"
     {
 		(yyval.gen) = (yyvsp[(1) - (6)].gen);
 		(yyval.gen).index = (yyvsp[(3) - (6)].lval);
@@ -2564,10 +2362,8 @@ yyreduce:
 	}
     break;
 
-  case 106:
-
-/* Line 1806 of yacc.c  */
-#line 558 "a.y"
+  case 107:
+#line 567 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = (yyvsp[(4) - (5)].lval);
@@ -2576,10 +2372,8 @@ yyreduce:
 	}
     break;
 
-  case 107:
-
-/* Line 1806 of yacc.c  */
-#line 565 "a.y"
+  case 108:
+#line 574 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_STATIC;
@@ -2588,194 +2382,144 @@ yyreduce:
 	}
     break;
 
-  case 108:
-
-/* Line 1806 of yacc.c  */
-#line 573 "a.y"
+  case 109:
+#line 582 "a.y"
     {
 		(yyval.lval) = 0;
 	}
     break;
 
-  case 109:
-
-/* Line 1806 of yacc.c  */
-#line 577 "a.y"
+  case 110:
+#line 586 "a.y"
     {
 		(yyval.lval) = (yyvsp[(2) - (2)].lval);
 	}
     break;
 
-  case 110:
-
-/* Line 1806 of yacc.c  */
-#line 581 "a.y"
+  case 111:
+#line 590 "a.y"
     {
 		(yyval.lval) = -(yyvsp[(2) - (2)].lval);
 	}
     break;
 
-  case 112:
-
-/* Line 1806 of yacc.c  */
-#line 588 "a.y"
+  case 113:
+#line 597 "a.y"
     {
 		(yyval.lval) = D_AUTO;
 	}
     break;
 
-  case 115:
-
-/* Line 1806 of yacc.c  */
-#line 596 "a.y"
+  case 116:
+#line 605 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (1)].sym)->value;
 	}
     break;
 
-  case 116:
-
-/* Line 1806 of yacc.c  */
-#line 600 "a.y"
+  case 117:
+#line 609 "a.y"
     {
 		(yyval.lval) = -(yyvsp[(2) - (2)].lval);
 	}
     break;
 
-  case 117:
-
-/* Line 1806 of yacc.c  */
-#line 604 "a.y"
+  case 118:
+#line 613 "a.y"
     {
 		(yyval.lval) = (yyvsp[(2) - (2)].lval);
 	}
     break;
 
-  case 118:
-
-/* Line 1806 of yacc.c  */
-#line 608 "a.y"
+  case 119:
+#line 617 "a.y"
     {
 		(yyval.lval) = ~(yyvsp[(2) - (2)].lval);
 	}
     break;
 
-  case 119:
-
-/* Line 1806 of yacc.c  */
-#line 612 "a.y"
+  case 120:
+#line 621 "a.y"
     {
 		(yyval.lval) = (yyvsp[(2) - (3)].lval);
 	}
     break;
 
-  case 121:
-
-/* Line 1806 of yacc.c  */
-#line 619 "a.y"
+  case 122:
+#line 628 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (3)].lval) + (yyvsp[(3) - (3)].lval);
 	}
     break;
 
-  case 122:
-
-/* Line 1806 of yacc.c  */
-#line 623 "a.y"
+  case 123:
+#line 632 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (3)].lval) - (yyvsp[(3) - (3)].lval);
 	}
     break;
 
-  case 123:
-
-/* Line 1806 of yacc.c  */
-#line 627 "a.y"
+  case 124:
+#line 636 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (3)].lval) * (yyvsp[(3) - (3)].lval);
 	}
     break;
 
-  case 124:
-
-/* Line 1806 of yacc.c  */
-#line 631 "a.y"
+  case 125:
+#line 640 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (3)].lval) / (yyvsp[(3) - (3)].lval);
 	}
     break;
 
-  case 125:
-
-/* Line 1806 of yacc.c  */
-#line 635 "a.y"
+  case 126:
+#line 644 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (3)].lval) % (yyvsp[(3) - (3)].lval);
 	}
     break;
 
-  case 126:
-
-/* Line 1806 of yacc.c  */
-#line 639 "a.y"
+  case 127:
+#line 648 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (4)].lval) << (yyvsp[(4) - (4)].lval);
 	}
     break;
 
-  case 127:
-
-/* Line 1806 of yacc.c  */
-#line 643 "a.y"
+  case 128:
+#line 652 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (4)].lval) >> (yyvsp[(4) - (4)].lval);
 	}
     break;
 
-  case 128:
-
-/* Line 1806 of yacc.c  */
-#line 647 "a.y"
+  case 129:
+#line 656 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (3)].lval) & (yyvsp[(3) - (3)].lval);
 	}
     break;
 
-  case 129:
-
-/* Line 1806 of yacc.c  */
-#line 651 "a.y"
+  case 130:
+#line 660 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (3)].lval) ^ (yyvsp[(3) - (3)].lval);
 	}
     break;
 
-  case 130:
-
-/* Line 1806 of yacc.c  */
-#line 655 "a.y"
+  case 131:
+#line 664 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (3)].lval) | (yyvsp[(3) - (3)].lval);
 	}
     break;
 
 
-
-/* Line 1806 of yacc.c  */
-#line 2766 "y.tab.c"
+/* Line 1267 of yacc.c.  */
+#line 2521 "y.tab.c"
       default: break;
     }
-  /* User semantic actions sometimes alter yychar, and that requires
-     that yytoken be updated with the new translation.  We take the
-     approach of translating immediately before every use of yytoken.
-     One alternative is translating here after every semantic action,
-     but that translation would be missed if the semantic action invokes
-     YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
-     if it invokes YYBACKUP.  In the case of YYABORT or YYACCEPT, an
-     incorrect destructor might then be invoked immediately.  In the
-     case of YYERROR or YYBACKUP, subsequent parser actions might lead
-     to an incorrect destructor call or verbose syntax error message
-     before the lookahead is translated.  */
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
 
   YYPOPSTACK (yylen);
@@ -2784,6 +2528,7 @@ yyreduce:
 
   *++yyvsp = yyval;
 
+
   /* Now `shift' the result of the reduction.  Determine what state
      that goes to, based on the state we popped back to and the rule
      number reduced by.  */
@@ -2803,10 +2548,6 @@ yyreduce:
 | yyerrlab -- here on detecting error |
 `------------------------------------*/
 yyerrlab:
-  /* Make sure we have latest lookahead translation.  See comments at
-     user semantic actions for why this is necessary.  */
-  yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
-
   /* If not already recovering from an error, report this error.  */
   if (!yyerrstatus)
     {
@@ -2814,36 +2555,37 @@ yyerrlab:
 #if ! YYERROR_VERBOSE
       yyerror (YY_("syntax error"));
 #else
-# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
-                                        yyssp, yytoken)
       {
-        char const *yymsgp = YY_("syntax error");
-        int yysyntax_error_status;
-        yysyntax_error_status = YYSYNTAX_ERROR;
-        if (yysyntax_error_status == 0)
-          yymsgp = yymsg;
-        else if (yysyntax_error_status == 1)
-          {
-            if (yymsg != yymsgbuf)
-              YYSTACK_FREE (yymsg);
-            yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
-            if (!yymsg)
-              {
-                yymsg = yymsgbuf;
-                yymsg_alloc = sizeof yymsgbuf;
-                yysyntax_error_status = 2;
-              }
-            else
-              {
-                yysyntax_error_status = YYSYNTAX_ERROR;
-                yymsgp = yymsg;
-              }
-          }
-        yyerror (yymsgp);
-        if (yysyntax_error_status == 2)
-          goto yyexhaustedlab;
+	YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+	if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+	  {
+	    YYSIZE_T yyalloc = 2 * yysize;
+	    if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+	      yyalloc = YYSTACK_ALLOC_MAXIMUM;
+	    if (yymsg != yymsgbuf)
+	      YYSTACK_FREE (yymsg);
+	    yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+	    if (yymsg)
+	      yymsg_alloc = yyalloc;
+	    else
+	      {
+		yymsg = yymsgbuf;
+		yymsg_alloc = sizeof yymsgbuf;
+	      }
+	  }
+
+	if (0 < yysize && yysize <= yymsg_alloc)
+	  {
+	    (void) yysyntax_error (yymsg, yystate, yychar);
+	    yyerror (yymsg);
+	  }
+	else
+	  {
+	    yyerror (YY_("syntax error"));
+	    if (yysize != 0)
+	      goto yyexhaustedlab;
+	  }
       }
-# undef YYSYNTAX_ERROR
 #endif
     }
 
@@ -2851,7 +2593,7 @@ yyerrlab:
 
   if (yyerrstatus == 3)
     {
-      /* If just tried and failed to reuse lookahead token after an
+      /* If just tried and failed to reuse look-ahead token after an
 	 error, discard it.  */
 
       if (yychar <= YYEOF)
@@ -2868,7 +2610,7 @@ yyerrlab:
 	}
     }
 
-  /* Else will try to reuse lookahead token after shifting the error
+  /* Else will try to reuse look-ahead token after shifting the error
      token.  */
   goto yyerrlab1;
 
@@ -2902,7 +2644,7 @@ yyerrlab1:
   for (;;)
     {
       yyn = yypact[yystate];
-      if (!yypact_value_is_default (yyn))
+      if (yyn != YYPACT_NINF)
 	{
 	  yyn += YYTERROR;
 	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
@@ -2925,6 +2667,9 @@ yyerrlab1:
       YY_STACK_PRINT (yyss, yyssp);
     }
 
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
   *++yyvsp = yylval;
 
 
@@ -2949,7 +2694,7 @@ yyabortlab:
   yyresult = 1;
   goto yyreturn;
 
-#if !defined(yyoverflow) || YYERROR_VERBOSE
+#ifndef yyoverflow
 /*-------------------------------------------------.
 | yyexhaustedlab -- memory exhaustion comes here.  |
 `-------------------------------------------------*/
@@ -2960,14 +2705,9 @@ yyexhaustedlab:
 #endif
 
 yyreturn:
-  if (yychar != YYEMPTY)
-    {
-      /* Make sure we have latest lookahead translation.  See comments at
-         user semantic actions for why this is necessary.  */
-      yytoken = YYTRANSLATE (yychar);
-      yydestruct ("Cleanup: discarding lookahead",
-                  yytoken, &yylval);
-    }
+  if (yychar != YYEOF && yychar != YYEMPTY)
+     yydestruct ("Cleanup: discarding lookahead",
+		 yytoken, &yylval);
   /* Do not reclaim the symbols of the rule which action triggered
      this YYABORT or YYACCEPT.  */
   YYPOPSTACK (yylen);
diff --git a/src/cmd/8a/y.tab.h b/src/cmd/8a/y.tab.h
index 4d7bbe8..4a84b53 100644
--- a/src/cmd/8a/y.tab.h
+++ b/src/cmd/8a/y.tab.h
@@ -1,21 +1,24 @@
-/* A Bison parser, made by GNU Bison 2.5.  */
+/* A Bison parser, made by GNU Bison 2.3.  */
 
-/* Bison interface for Yacc-like parsers in C
-   
-      Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc.
-   
-   This program is free software: you can redistribute it and/or modify
+/* Skeleton interface for Bison's Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
-   
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
 
 /* As a special exception, you may create a larger work that contains
    part or all of the Bison parser skeleton and distribute that work
@@ -26,11 +29,10 @@
    special exception, which will cause the skeleton and the resulting
    Bison output files to be licensed under the GNU General Public
    License without this special exception.
-   
+
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
-
 /* Tokens.  */
 #ifndef YYTOKENTYPE
 # define YYTOKENTYPE
@@ -108,11 +110,8 @@
 
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef union YYSTYPE
-{
-
-/* Line 2068 of yacc.c  */
 #line 37 "a.y"
-
+{
 	Sym	*sym;
 	int32	lval;
 	struct {
@@ -123,17 +122,14 @@ typedef union YYSTYPE
 	char	sval[8];
 	Gen	gen;
 	Gen2	gen2;
-
-
-
-/* Line 2068 of yacc.c  */
-#line 131 "y.tab.h"
-} YYSTYPE;
-# define YYSTYPE_IS_TRIVIAL 1
+}
+/* Line 1529 of yacc.c.  */
+#line 128 "y.tab.h"
+	YYSTYPE;
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
 #endif
 
 extern YYSTYPE yylval;
 
-
diff --git a/src/cmd/8l/8.out.h b/src/cmd/8l/8.out.h
index 93d44eb..cf0bc9f 100644
--- a/src/cmd/8l/8.out.h
+++ b/src/cmd/8l/8.out.h
@@ -534,10 +534,12 @@ enum	as
 	AORPS,
 	APADDQ,
 	APAND,
+	APCMPEQB,
 	APMAXSW,
 	APMAXUB,
 	APMINSW,
 	APMINUB,
+	APMOVMSKB,
 	APSADBW,
 	APSUBB,
 	APSUBL,
@@ -654,6 +656,7 @@ enum
 	D_PCREL,
 	D_GOTOFF,
 	D_GOTREL,
+	D_TLS,
 
 	T_TYPE		= 1<<0,
 	T_INDEX		= 1<<1,
diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c
index bfeb138..18591cd 100644
--- a/src/cmd/8l/asm.c
+++ b/src/cmd/8l/asm.c
@@ -294,6 +294,12 @@ elfreloc1(Reloc *r, vlong sectoff)
 		else
 			return -1;
 		break;
+	
+	case D_TLS:
+		if(r->siz == 4)
+			LPUT(R_386_TLS_LE | elfsym<<8);
+		else
+			return -1;
 	}
 
 	return 0;
diff --git a/src/cmd/8l/l.h b/src/cmd/8l/l.h
index 980a7f8..ce12d59 100644
--- a/src/cmd/8l/l.h
+++ b/src/cmd/8l/l.h
@@ -286,14 +286,12 @@ EXTERN	int32	INITTEXT;
 EXTERN	int32	INITDAT;
 EXTERN	char*	INITENTRY;		/* entry point */
 EXTERN	char*	LIBINITENTRY;		/* shared library entry point */
-EXTERN	int32	casepc;
 EXTERN	char*	pcstr;
 EXTERN	Auto*	curauto;
 EXTERN	Auto*	curhist;
 EXTERN	Prog*	curp;
 EXTERN	Sym*	cursym;
 EXTERN	Sym*	datap;
-EXTERN	int32	elfdatsize;
 EXTERN	int	debug[128];
 EXTERN	char	literal[32];
 EXTERN	Sym*	etextp;
@@ -319,7 +317,6 @@ EXTERN	int	dtype;
 EXTERN	int	tlsoffset;
 EXTERN	Sym*	adrgotype;	// type symbol on last Adr read
 EXTERN	Sym*	fromgotype;	// type symbol on last p->from read
-EXTERN	int	elftextsh;
 
 extern	Optab	optab[];
 extern	char*	anames[];
diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c
index 306e288..c819b99 100644
--- a/src/cmd/8l/obj.c
+++ b/src/cmd/8l/obj.c
@@ -90,7 +90,7 @@ main(int argc, char *argv[])
 	INITRND = -1;
 	INITENTRY = 0;
 	LIBINITENTRY = 0;
-	linkmode = LinkInternal; // TODO: LinkAuto once everything works.
+	linkmode = LinkAuto;
 	nuxiinit();
 
 	flagcount("1", "use alternate profiling code", &debug['1']);
@@ -113,6 +113,8 @@ main(int argc, char *argv[])
 	flagcount("a", "disassemble output", &debug['a']);
 	flagcount("c", "dump call graph", &debug['c']);
 	flagcount("d", "disable dynamic executable", &debug['d']);
+	flagstr("extld", "linker to run in external mode", &extld);
+	flagstr("extldflags", "flags for external linker", &extldflags);
 	flagcount("f", "ignore version mismatch", &debug['f']);
 	flagcount("g", "disable go package data checks", &debug['g']);
 	flagfn1("linkmode", "mode: set link mode (internal, external, auto)", setlinkmode);
@@ -139,11 +141,16 @@ main(int argc, char *argv[])
 	if(HEADTYPE == -1)
 		HEADTYPE = headtype(goos);
 
+	// getgoextlinkenabled is based on GO_EXTLINK_ENABLED when
+	// Go was built; see ../../make.bash.
+	if(linkmode == LinkAuto && strcmp(getgoextlinkenabled(), "0") == 0)
+		linkmode = LinkInternal;
+
 	switch(HEADTYPE) {
 	default:
 		if(linkmode == LinkAuto)
 			linkmode = LinkInternal;
-		if(linkmode == LinkExternal)
+		if(linkmode == LinkExternal && strcmp(getgoextlinkenabled(), "1") != 0)
 			sysfatal("cannot use -linkmode=external with -H %s", headstr(HEADTYPE));
 		break;
 	case Hdarwin:
@@ -607,11 +614,15 @@ loop:
 		goto loop;
 
 	case ALOCALS:
+		if(skip)
+			goto casdef;
 		cursym->locals = p->to.offset;
 		pc++;
 		goto loop;
 
 	case ATYPE:
+		if(skip)
+			goto casdef;
 		pc++;
 		goto loop;
 
diff --git a/src/cmd/8l/optab.c b/src/cmd/8l/optab.c
index a6ebf06..1d9d2f5 100644
--- a/src/cmd/8l/optab.c
+++ b/src/cmd/8l/optab.c
@@ -364,6 +364,12 @@ uchar	ysvrs[] =
 	Ym,	Ynone,	Zm_o,	2,
 	0
 };
+uchar	ymskb[] =
+{
+	Yxr,	Yrl,	Zm_r_xm,	2,
+	Ymr,	Yrl,	Zm_r_xm,	1,
+	0
+};
 uchar	yxm[] = 
 {
 	Yxm,	Yxr,	Zm_r_xm,	1,
@@ -950,10 +956,12 @@ Optab optab[] =
 	{ AORPS,	yxm,	Pm, 0x56 },
 	{ APADDQ,	yxm,	Pe, 0xd4 },
 	{ APAND,	yxm,	Pe, 0xdb },
+	{ APCMPEQB,	yxmq,	Pe ,0x74 },
 	{ APMAXSW,	yxm,	Pe, 0xee },
 	{ APMAXUB,	yxm,	Pe, 0xde },
 	{ APMINSW,	yxm,	Pe, 0xea },
 	{ APMINUB,	yxm,	Pe, 0xda },
+	{ APMOVMSKB,	ymskb,	Px, Pe,0xd7,0xd7 },
 	{ APSADBW,	yxm,	Pq, 0xf6 },
 	{ APSUBB,	yxm,	Pe, 0xf8 },
 	{ APSUBL,	yxm,	Pe, 0xfa },
diff --git a/src/cmd/8l/pass.c b/src/cmd/8l/pass.c
index 14dd3e0..4871761 100644
--- a/src/cmd/8l/pass.c
+++ b/src/cmd/8l/pass.c
@@ -296,16 +296,23 @@ patch(void)
 				//	MOVL 0(GS), reg
 				// and then off(reg) instead of saying off(GS) directly
 				// when the offset is negative.
+				// In external mode we just produce a reloc.
 				if(p->from.type == D_INDIR+D_GS && p->from.offset < 0
 				&& p->to.type >= D_AX && p->to.type <= D_DI) {
-					q = appendp(p);
-					q->from = p->from;
-					q->from.type = D_INDIR + p->to.type;
-					q->to = p->to;
-					q->as = p->as;
-					p->as = AMOVL;
-					p->from.type = D_INDIR+D_GS;
-					p->from.offset = 0;
+					if(linkmode != LinkExternal) {
+						q = appendp(p);
+						q->from = p->from;
+						q->from.type = D_INDIR + p->to.type;
+						q->to = p->to;
+						q->as = p->as;
+						p->as = AMOVL;
+						p->from.type = D_INDIR+D_GS;
+						p->from.offset = 0;
+					} else {
+						// Add signals to relocate.
+						p->from.index = D_GS;
+						p->from.scale = 1;
+					}
 				}
 			}
 			if(HEADTYPE == Hplan9x32) {
@@ -450,16 +457,25 @@ dostkoff(void)
 				break;
 			
 			case Hlinux:
-				p->as = AMOVL;
-				p->from.type = D_INDIR+D_GS;
-				p->from.offset = 0;
-				p->to.type = D_CX;
+				if(linkmode != LinkExternal) {
+					p->as = AMOVL;
+					p->from.type = D_INDIR+D_GS;
+					p->from.offset = 0;
+					p->to.type = D_CX;
 
-				p = appendp(p);
-				p->as = AMOVL;
-				p->from.type = D_INDIR+D_CX;
-				p->from.offset = tlsoffset + 0;
-				p->to.type = D_CX;
+					p = appendp(p);
+					p->as = AMOVL;
+					p->from.type = D_INDIR+D_CX;
+					p->from.offset = tlsoffset + 0;
+					p->to.type = D_CX;
+				} else {
+					p->as = AMOVL;
+					p->from.type = D_INDIR+D_GS;
+					p->from.offset = tlsoffset + 0;
+					p->to.type = D_CX;
+					p->from.index = D_GS;
+					p->from.scale = 1;
+				}
 				break;
 			
 			case Hplan9x32:
diff --git a/src/cmd/8l/span.c b/src/cmd/8l/span.c
index 0678fa8..980186b 100644
--- a/src/cmd/8l/span.c
+++ b/src/cmd/8l/span.c
@@ -32,6 +32,7 @@
 
 #include	"l.h"
 #include	"../ld/lib.h"
+#include	"../ld/elf.h"
 
 static int32	vaddr(Adr*, Reloc*);
 
@@ -559,6 +560,14 @@ vaddr(Adr *a, Reloc *r)
 	return v;
 }
 
+static int
+istls(Adr *a)
+{
+	if(HEADTYPE == Hlinux)
+		return a->index == D_GS;
+	return a->type == D_INDIR+D_GS;
+}
+
 void
 asmand(Adr *a, int r)
 {
@@ -569,7 +578,7 @@ asmand(Adr *a, int r)
 	v = a->offset;
 	t = a->type;
 	rel.siz = 0;
-	if(a->index != D_NONE) {
+	if(a->index != D_NONE && a->index != D_FS && a->index != D_GS) {
 		if(t < D_INDIR || t >= 2*D_INDIR) {
 			switch(t) {
 			default:
@@ -658,7 +667,7 @@ asmand(Adr *a, int r)
 			*andptr++ = (0 << 6) | (reg[t] << 0) | (r << 3);
 			return;
 		}
-		if(v >= -128 && v < 128 && rel.siz == 0) {
+		if(v >= -128 && v < 128 && rel.siz == 0 && a->index != D_FS && a->index != D_GS) {
 			andptr[0] = (1 << 6) | (reg[t] << 0) | (r << 3);
 			andptr[1] = v;
 			andptr += 2;
@@ -680,7 +689,29 @@ putrelv:
 		r = addrel(cursym);
 		*r = rel;
 		r->off = curp->pc + andptr - and;
+	} else if(iself && linkmode == LinkExternal && istls(a) && HEADTYPE != Hopenbsd) {
+		Reloc *r;
+		Sym *s;
+
+		r = addrel(cursym);
+		r->off = curp->pc + andptr - and;
+		r->add = 0;
+		r->xadd = 0;
+		r->siz = 4;
+		r->type = D_TLS;
+		if(a->offset == tlsoffset+0)
+			s = lookup("runtime.g", 0);
+		else
+			s = lookup("runtime.m", 0);
+		s->type = STLSBSS;
+		s->reachable = 1;
+		s->hide = 1;
+		s->size = PtrSize;
+		r->sym = s;
+		r->xsym = s;
+		v = 0;
 	}
+
 	put4(v);
 	return;
 
diff --git a/src/cmd/cc/cc.h b/src/cmd/cc/cc.h
index 866aeb0..c8de941 100644
--- a/src/cmd/cc/cc.h
+++ b/src/cmd/cc/cc.h
@@ -800,6 +800,7 @@ int	machcap(Node*);
 #pragma	varargck	type	"Q"	int32
 #pragma	varargck	type	"O"	int
 #pragma	varargck	type	"O"	uint
+#pragma	varargck	type	"S"	ushort*
 #pragma	varargck	type	"T"	Type*
 #pragma	varargck	type	"U"	char*
 #pragma	varargck	type	"|"	int
diff --git a/src/cmd/cc/funct.c b/src/cmd/cc/funct.c
index 0571519..7921277 100644
--- a/src/cmd/cc/funct.c
+++ b/src/cmd/cc/funct.c
@@ -269,7 +269,7 @@ dclfunct(Type *t, Sym *s)
 		goto bad;
 
 	f = alloc(sizeof(*f));
-	for(o=0; o<sizeof(f->sym); o++)
+	for(o=0; o<nelem(f->sym); o++)
 		f->sym[o] = S;
 
 	t->funct = f;
diff --git a/src/cmd/cc/lexbody b/src/cmd/cc/lexbody
index 5fa9802..f4a6973 100644
--- a/src/cmd/cc/lexbody
+++ b/src/cmd/cc/lexbody
@@ -263,7 +263,7 @@ lookup(void)
 	for(s = hash[h]; s != S; s = s->link) {
 		if(s->name[0] != c)
 			continue;
-		if(memcmp(s->name, symb, l) == 0)
+		if(strcmp(s->name, symb) == 0)
 			return s;
 	}
 	s = alloc(sizeof(*s));
diff --git a/src/cmd/dist/a.h b/src/cmd/dist/a.h
index fcd81cc..73c1264 100644
--- a/src/cmd/dist/a.h
+++ b/src/cmd/dist/a.h
@@ -72,6 +72,7 @@ extern char *gohostos;
 extern char *goos;
 extern char *goroot;
 extern char *goroot_final;
+extern char *goextlinkenabled;
 extern char *goversion;
 extern char *workdir;
 extern char *tooldir;
diff --git a/src/cmd/dist/build.c b/src/cmd/dist/build.c
index fd6a329..e948623 100644
--- a/src/cmd/dist/build.c
+++ b/src/cmd/dist/build.c
@@ -20,6 +20,7 @@ char *goarm;
 char *go386;
 char *goroot = GOROOT_FINAL;
 char *goroot_final = GOROOT_FINAL;
+char *goextlinkenabled = "";
 char *workdir;
 char *tooldir;
 char *gochar;
@@ -139,6 +140,13 @@ init(void)
 	bprintf(&b, "%c", gochars[i]);
 	gochar = btake(&b);
 
+	xgetenv(&b, "GO_EXTLINK_ENABLED");
+	if(b.len > 0) {
+		goextlinkenabled = btake(&b);
+		if(!streq(goextlinkenabled, "0") && !streq(goextlinkenabled, "1"))
+			fatal("unknown $GO_EXTLINK_ENABLED %s", goextlinkenabled);
+	}
+
 	xsetenv("GOROOT", goroot);
 	xsetenv("GOARCH", goarch);
 	xsetenv("GOOS", goos);
@@ -922,6 +930,8 @@ install(char *dir)
 				vadd(&compile, bprintf(&b, "GOARM=\"%s\"", goarm));
 				vadd(&compile, "-D");
 				vadd(&compile, bprintf(&b, "GO386=\"%s\"", go386));
+				vadd(&compile, "-D");
+				vadd(&compile, bprintf(&b, "GO_EXTLINK_ENABLED=\"%s\"", goextlinkenabled));
 			}
 
 			// gc/lex.c records the GOEXPERIMENT setting used during the build.
diff --git a/src/cmd/dist/buildruntime.c b/src/cmd/dist/buildruntime.c
index f46f72d..ee86756 100644
--- a/src/cmd/dist/buildruntime.c
+++ b/src/cmd/dist/buildruntime.c
@@ -133,12 +133,17 @@ static struct {
 		"// which is where these macros come into play.\n"
 		"// get_tls sets up the temporary and then g and r use it.\n"
 		"//\n"
-		"// The final wrinkle is that get_tls needs to read from %gs:0,\n"
+		"// Another wrinkle is that get_tls needs to read from %gs:0,\n"
 		"// but in 8l input it's called 8(GS), because 8l is going to\n"
 		"// subtract 8 from all the offsets, as described above.\n"
+		"//\n"
+		"// The final wrinkle is that when generating an ELF .o file for\n"
+		"// external linking mode, we need to be able to relocate the\n"
+		"// -8(r) and -4(r) instructions. Tag them with an extra (GS*1)\n"
+		"// that is ignored by the linker except for that identification.\n"
 		"#define	get_tls(r)	MOVL 8(GS), r\n"
-		"#define	g(r)	-8(r)\n"
-		"#define	m(r)	-4(r)\n"
+		"#define	g(r)	-8(r)(GS*1)\n"
+		"#define	m(r)	-4(r)(GS*1)\n"
 	},
 	{"386", "",
 		"#define	get_tls(r)\n"
diff --git a/src/cmd/dist/unix.c b/src/cmd/dist/unix.c
index e4e2dcc..f2ea489 100644
--- a/src/cmd/dist/unix.c
+++ b/src/cmd/dist/unix.c
@@ -698,6 +698,19 @@ main(int argc, char **argv)
 	if(strcmp(gohostarch, "arm") == 0)
 		maxnbg = 1;
 
+	// The OS X 10.6 linker does not support external
+	// linking mode; see
+	// https://code.google.com/p/go/issues/detail?id=5130 .
+	// The mapping from the uname release field to the OS X
+	// version number is complicated, but basically 10 or under is
+	// OS X 10.6 or earlier.
+	if(strcmp(gohostos, "darwin") == 0) {
+		if(uname(&u) < 0)
+			fatal("uname: %s", strerror(errno));
+		if(u.release[1] == '.' || hasprefix(u.release, "10"))
+			goextlinkenabled = "0";
+	}
+
 	init();
 	xmain(argc, argv);
 	bfree(&b);
diff --git a/src/cmd/gc/builtin.c b/src/cmd/gc/builtin.c
index f1d0931..9053dfe 100644
--- a/src/cmd/gc/builtin.c
+++ b/src/cmd/gc/builtin.c
@@ -1,3 +1,4 @@
+// AUTO-GENERATED by mkbuiltin; DO NOT EDIT
 char *runtimeimport =
 	"package runtime\n"
 	"import runtime \"runtime\"\n"
diff --git a/src/cmd/gc/closure.c b/src/cmd/gc/closure.c
index aca30dc..c1a9eb1 100644
--- a/src/cmd/gc/closure.c
+++ b/src/cmd/gc/closure.c
@@ -76,7 +76,7 @@ closurebody(NodeList *body)
 	return func;
 }
 
-static Node* makeclosure(Node *func, int nowrap);
+static Node* makeclosure(Node *func);
 
 void
 typecheckclosure(Node *func, int top)
@@ -125,11 +125,11 @@ typecheckclosure(Node *func, int top)
 	}
 
 	// Create top-level function 
-	xtop = list(xtop, makeclosure(func, func->cvars==nil || (top&Ecall)));
+	xtop = list(xtop, makeclosure(func));
 }
 
 static Node*
-makeclosure(Node *func, int nowrap)
+makeclosure(Node *func)
 {
 	Node *xtype, *v, *addr, *xfunc, *cv;
 	NodeList *l, *body;
diff --git a/src/cmd/gc/const.c b/src/cmd/gc/const.c
index add438d..e9d99df 100644
--- a/src/cmd/gc/const.c
+++ b/src/cmd/gc/const.c
@@ -1136,7 +1136,6 @@ defaultlit(Node **np, Type *t)
 
 	lno = setlineno(n);
 	ctype = idealkind(n);
-	t1 = T;
 	switch(ctype) {
 	default:
 		if(t != T) {
diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c
index 429f212..d3759ef 100644
--- a/src/cmd/gc/dcl.c
+++ b/src/cmd/gc/dcl.c
@@ -1339,6 +1339,8 @@ addmethod(Sym *sf, Type *t, int local, int nointerface)
 	f = methtype(pa, 1);
 	if(f == T) {
 		t = pa;
+		if(t == T) // rely on typecheck having complained before
+			return;
 		if(t != T) {
 			if(isptr[t->etype]) {
 				if(t->sym != S) {
@@ -1347,10 +1349,8 @@ addmethod(Sym *sf, Type *t, int local, int nointerface)
 				}
 				t = t->type;
 			}
-		}
-		if(t->broke) // rely on typecheck having complained before
-			return;
-		if(t != T) {
+			if(t->broke) // rely on typecheck having complained before
+				return;
 			if(t->sym == S) {
 				yyerror("invalid receiver type %T (%T is an unnamed type)", pa, t);
 				return;
diff --git a/src/cmd/gc/fmt.c b/src/cmd/gc/fmt.c
index ee5b9e9..8a14aa2 100644
--- a/src/cmd/gc/fmt.c
+++ b/src/cmd/gc/fmt.c
@@ -630,7 +630,7 @@ typefmt(Fmt *fp, Type *t)
 
 	case TARRAY:
 		if(t->bound >= 0)
-			return fmtprint(fp, "[%d]%T", (int)t->bound, t->type);
+			return fmtprint(fp, "[%lld]%T", t->bound, t->type);
 		if(t->bound == -100)
 			return fmtprint(fp, "[...]%T", t->type);
 		return fmtprint(fp, "[]%T", t->type);
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index 6be0ec8..1f5fb41 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -155,7 +155,7 @@ struct	Type
 	Type*	orig;		// original type (type literal or predefined type)
 	int		lineno;
 
-	// TFUNCT
+	// TFUNC
 	uchar	thistuple;
 	uchar	outtuple;
 	uchar	intuple;
@@ -394,6 +394,7 @@ struct	Pkg
 	uchar	imported;	// export data of this package was parsed
 	char	exported;	// import line written in export data
 	char	direct;	// imported directly
+	char	safe;	// whether the package is marked as safe
 };
 
 typedef	struct	Iter	Iter;
diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y
index a12da56..29cd370 100644
--- a/src/cmd/gc/go.y
+++ b/src/cmd/gc/go.y
@@ -251,7 +251,8 @@ import_package:
 		} else if(strcmp(importpkg->name, $2->name) != 0)
 			yyerror("conflicting names %s and %s for package \"%Z\"", importpkg->name, $2->name, importpkg->path);
 		importpkg->direct = 1;
-		
+		importpkg->safe = curio.importsafe;
+
 		if(safemode && !curio.importsafe)
 			yyerror("cannot import unsafe package \"%Z\"", importpkg->path);
 	}
diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c
index 118a0d7..b7f71d5 100644
--- a/src/cmd/gc/lex.c
+++ b/src/cmd/gc/lex.c
@@ -602,7 +602,7 @@ void
 importfile(Val *f, int line)
 {
 	Biobuf *imp;
-	char *file, *p, *q;
+	char *file, *p, *q, *tag;
 	int32 c;
 	int len;
 	Strlit *path;
@@ -610,8 +610,6 @@ importfile(Val *f, int line)
 
 	USED(line);
 
-	// TODO(rsc): don't bother reloading imports more than once?
-
 	if(f->ctype != CTSTR) {
 		yyerror("import statement not a string");
 		fakeimport();
@@ -686,7 +684,11 @@ importfile(Val *f, int line)
 	// to the lexer to avoid parsing export data twice.
 	if(importpkg->imported) {
 		file = strdup(namebuf);
-		p = smprint("package %s\n$$\n", importpkg->name);
+		tag = "";
+		if(importpkg->safe) {
+			tag = "safe";
+		}
+		p = smprint("package %s %s\n$$\n", importpkg->name, tag);
 		cannedimports(file, p);
 		return;
 	}
diff --git a/src/cmd/gc/mkbuiltin b/src/cmd/gc/mkbuiltin
index 2f76e6f..1dab1c9 100755
--- a/src/cmd/gc/mkbuiltin
+++ b/src/cmd/gc/mkbuiltin
@@ -19,6 +19,7 @@ fi
 GC=${GOCHAR}g
 gcc -o mkbuiltin1 mkbuiltin1.c
 rm -f _builtin.c
+echo "// AUTO-GENERATED by mkbuiltin; DO NOT EDIT" >>_builtin.c
 for i in runtime unsafe
 do
 	go tool $GC -A $i.go
diff --git a/src/cmd/gc/racewalk.c b/src/cmd/gc/racewalk.c
index 3e5e592..5d4f62e 100644
--- a/src/cmd/gc/racewalk.c
+++ b/src/cmd/gc/racewalk.c
@@ -26,6 +26,7 @@ static Node* uintptraddr(Node *n);
 static Node* basenod(Node *n);
 static void foreach(Node *n, void(*f)(Node*, void*), void *c);
 static void hascallspred(Node *n, void *c);
+static void appendinit(Node **np, NodeList *init);
 static Node* detachexpr(Node *n, NodeList **init);
 
 // Do not instrument the following packages at all,
@@ -132,14 +133,13 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
 	case OASOP:
 	case OAS:
 	case OAS2:
-	case OAS2DOTTYPE:
 	case OAS2RECV:
 	case OAS2FUNC:
 	case OAS2MAPR:
 		racewalknode(&n->left, init, 1, 0);
 		racewalknode(&n->right, init, 0, 0);
 		goto ret;
-	
+
 	case OCFUNC:
 		// can't matter
 		goto ret;
@@ -185,12 +185,6 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
 		racewalknode(&n->left, init, 0, 0);
 		goto ret;
 
-	case OSWITCH:
-		if(n->ntest->op == OTYPESW)
-			// TODO(dvyukov): the expression can contain calls or reads.
-			return;
-		goto ret;
-
 	case ONOT:
 	case OMINUS:
 	case OPLUS:
@@ -240,6 +234,7 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
 	case OXOR:
 	case OSUB:
 	case OMUL:
+	case OHMUL:
 	case OEQ:
 	case ONE:
 	case OLT:
@@ -255,9 +250,13 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
 	case OANDAND:
 	case OOROR:
 		racewalknode(&n->left, init, wr, 0);
-		// It requires more complex tree transformation,
-		// because we don't know whether it will be executed or not.
-		//racewalknode(&n->right, init, wr, 0);
+		// walk has ensured the node has moved to a location where
+		// side effects are safe.
+		// n->right may not be executed,
+		// so instrumentation goes to n->right->ninit, not init.
+		l = nil;
+		racewalknode(&n->right, &l, wr, 0);
+		appendinit(&n->right, l);
 		goto ret;
 
 	case ONAME:
@@ -307,6 +306,14 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
 		racewalknode(&n->right, init, 0, 0);
 		goto ret;
 
+	case OITAB:
+		racewalknode(&n->left, init, 0, 0);
+		goto ret;
+
+	case OTYPESW:
+		racewalknode(&n->right, init, 0, 0);
+		goto ret;
+
 	// should not appear in AST by now
 	case OSEND:
 	case ORECV:
@@ -318,11 +325,13 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
 	case OPANIC:
 	case ORECOVER:
 	case OCONVIFACE:
+	case OCMPIFACE:
 	case OMAKECHAN:
 	case OMAKEMAP:
 	case OMAKESLICE:
 	case OCALL:
 	case OCOPY:
+	case OAPPEND:
 	case ORUNESTR:
 	case OARRAYBYTESTR:
 	case OARRAYRUNESTR:
@@ -333,6 +342,13 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
 	case OADDSTR:
 	case ODOTTYPE:
 	case ODOTTYPE2:
+	case OAS2DOTTYPE:
+	case OCALLPART: // lowered to PTRLIT
+	case OCLOSURE:  // lowered to PTRLIT
+	case ORANGE:    // lowered to ordinary for loop
+	case OARRAYLIT: // lowered to assignments
+	case OMAPLIT:
+	case OSTRUCTLIT:
 		yyerror("racewalk: %O must be lowered by now", n->op);
 		goto ret;
 
@@ -347,6 +363,7 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
 	case OIF:
 	case OCALLMETH:
 	case ORETURN:
+	case OSWITCH:
 	case OSELECT:
 	case OEMPTY:
 	case OBREAK:
@@ -359,30 +376,18 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
 	// does not require instrumentation
 	case OPRINT:     // don't bother instrumenting it
 	case OPRINTN:    // don't bother instrumenting it
+	case OCHECKNOTNIL: // always followed by a read.
 	case OPARAM:     // it appears only in fn->exit to copy heap params back
-		goto ret;
-
-	// unimplemented
-	case OSLICESTR:
-	case OAPPEND:
-	case OCMPIFACE:
-	case OARRAYLIT:
-	case OMAPLIT:
-	case OSTRUCTLIT:
-	case OCLOSURE:
-	case ODCL:
+	case OCLOSUREVAR:// immutable pointer to captured variable
+	case ODOTMETH:   // either part of CALLMETH or CALLPART (lowered to PTRLIT)
+	case OINDREG:    // at this stage, only n(SP) nodes from nodarg
+	case ODCL:       // declarations (without value) cannot be races
 	case ODCLCONST:
 	case ODCLTYPE:
-	case OLITERAL:
-	case ORANGE:
 	case OTYPE:
 	case ONONAME:
-	case OINDREG:
-	case ODOTMETH:
-	case OITAB:
-	case OHMUL:
-	case OCHECKNOTNIL:
-	case OCLOSUREVAR:
+	case OLITERAL:
+	case OSLICESTR:  // always preceded by bounds checking, avoid double instrumentation.
 		goto ret;
 	}
 
@@ -398,7 +403,6 @@ ret:
 	racewalklist(n->nbody, nil);
 	racewalklist(n->nelse, nil);
 	racewalklist(n->rlist, nil);
-
 	*np = n;
 }
 
@@ -440,6 +444,7 @@ callinstr(Node **np, NodeList **init, int wr, int skip)
 	if(isartificial(n))
 		return 0;
 	if(t->etype == TSTRUCT) {
+		// TODO: instrument arrays similarly.
 		// PARAMs w/o PHEAP are not interesting.
 		if(n->class == PPARAM || n->class == PPARAMOUT)
 			return 0;
@@ -476,7 +481,7 @@ callinstr(Node **np, NodeList **init, int wr, int skip)
 	// that has got a pointer inside. Whether it points to
 	// the heap or not is impossible to know at compile time
 	if((class&PHEAP) || class == PPARAMREF || class == PEXTERN
-		|| b->type->etype == TARRAY || b->op == ODOTPTR || b->op == OIND || b->op == OXDOT) {
+		|| b->op == OINDEX || b->op == ODOTPTR || b->op == OIND || b->op == OXDOT) {
 		hascalls = 0;
 		foreach(n, hascallspred, &hascalls);
 		if(hascalls) {
@@ -502,6 +507,8 @@ uintptraddr(Node *n)
 	return r;
 }
 
+// basenod returns the simplest child node of n pointing to the same
+// memory area.
 static Node*
 basenod(Node *n)
 {
@@ -510,7 +517,7 @@ basenod(Node *n)
 			n = n->left;
 			continue;
 		}
-		if(n->op == OINDEX) {
+		if(n->op == OINDEX && isfixedarray(n->type)) {
 			n = n->left;
 			continue;
 		}
@@ -575,3 +582,30 @@ hascallspred(Node *n, void *c)
 		(*(int*)c)++;
 	}
 }
+
+// appendinit is like addinit in subr.c
+// but appends rather than prepends.
+static void
+appendinit(Node **np, NodeList *init)
+{
+	Node *n;
+
+	if(init == nil)
+		return;
+
+	n = *np;
+	switch(n->op) {
+	case ONAME:
+	case OLITERAL:
+		// There may be multiple refs to this node;
+		// introduce OCONVNOP to hold init list.
+		n = nod(OCONVNOP, n, N);
+		n->type = n->left->type;
+		n->typecheck = 1;
+		*np = n;
+		break;
+	}
+	n->ninit = concat(n->ninit, init);
+	n->ullman = UINF;
+}
+
diff --git a/src/cmd/gc/range.c b/src/cmd/gc/range.c
index e80a8c7..8af45b9 100644
--- a/src/cmd/gc/range.c
+++ b/src/cmd/gc/range.c
@@ -181,9 +181,9 @@ walkrange(Node *n)
 	case TMAP:
 		th = typ(TARRAY);
 		th->type = ptrto(types[TUINT8]);
-		// see ../../pkg/runtime/hashmap.h:/hash_iter
+		// see ../../pkg/runtime/hashmap.c:/hash_iter
 		// Size of hash_iter in # of pointers.
-		th->bound = 10;
+		th->bound = 11;
 		hit = temp(th);
 
 		fn = syslook("mapiterinit", 1);
diff --git a/src/cmd/gc/reflect.c b/src/cmd/gc/reflect.c
index 8b546e2..d128bf1 100644
--- a/src/cmd/gc/reflect.c
+++ b/src/cmd/gc/reflect.c
@@ -1069,6 +1069,7 @@ dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size)
 
 	case TPTR32:
 	case TPTR64:
+		// NOTE: Any changes here need to be made to reflect.PtrTo as well.
 		if(*off % widthptr != 0)
 			fatal("dgcsym1: invalid alignment, %T", t);
 		if(!haspointers(t->type) || t->type->etype == TUINT8) {
@@ -1093,6 +1094,7 @@ dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size)
 
 	// struct Hchan*
 	case TCHAN:
+		// NOTE: Any changes here need to be made to reflect.ChanOf as well.
 		if(*off % widthptr != 0)
 			fatal("dgcsym1: invalid alignment, %T", t);
 		ot = duintptr(s, ot, GC_CHAN_PTR);
@@ -1103,6 +1105,7 @@ dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size)
 
 	// struct Hmap*
 	case TMAP:
+		// NOTE: Any changes here need to be made to reflect.MapOf as well.
 		if(*off % widthptr != 0)
 			fatal("dgcsym1: invalid alignment, %T", t);
 		ot = duintptr(s, ot, GC_MAP_PTR);
@@ -1139,6 +1142,7 @@ dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size)
 		if(t->bound < -1)
 			fatal("dgcsym1: invalid bound, %T", t);
 		if(isslice(t)) {
+			// NOTE: Any changes here need to be made to reflect.SliceOf as well.
 			// struct { byte* array; uint32 len; uint32 cap; }
 			if(*off % widthptr != 0)
 				fatal("dgcsym1: invalid alignment, %T", t);
@@ -1152,6 +1156,9 @@ dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size)
 			}
 			*off += t->width;
 		} else {
+			// NOTE: Any changes here need to be made to reflect.ArrayOf as well,
+			// at least once ArrayOf's gc info is implemented and ArrayOf is exported.
+			// struct { byte* array; uint32 len; uint32 cap; }
 			if(t->bound < 1 || !haspointers(t->type)) {
 				*off += t->width;
 			} else if(gcinline(t)) {
diff --git a/src/cmd/gc/runtime.go b/src/cmd/gc/runtime.go
index c49d05c..2139a95 100644
--- a/src/cmd/gc/runtime.go
+++ b/src/cmd/gc/runtime.go
@@ -89,7 +89,13 @@ func equal(typ *byte, x1, x2 any) (ret bool)
 // *byte is really *runtime.Type
 func makemap(mapType *byte, hint int64) (hmap map[any]any)
 func mapaccess1(mapType *byte, hmap map[any]any, key any) (val any)
+func mapaccess1_fast32(mapType *byte, hmap map[any]any, key any) (val *any)
+func mapaccess1_fast64(mapType *byte, hmap map[any]any, key any) (val *any)
+func mapaccess1_faststr(mapType *byte, hmap map[any]any, key any) (val *any)
 func mapaccess2(mapType *byte, hmap map[any]any, key any) (val any, pres bool)
+func mapaccess2_fast32(mapType *byte, hmap map[any]any, key any) (val *any, pres bool)
+func mapaccess2_fast64(mapType *byte, hmap map[any]any, key any) (val *any, pres bool)
+func mapaccess2_faststr(mapType *byte, hmap map[any]any, key any) (val *any, pres bool)
 func mapassign1(mapType *byte, hmap map[any]any, key any, val any)
 func mapiterinit(mapType *byte, hmap map[any]any, hiter *any)
 func mapdelete(mapType *byte, hmap map[any]any, key any)
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index 796851f..bd78fb0 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -548,6 +548,12 @@ algtype1(Type *t, Type **bad)
 		*bad = T;
 
 	switch(t->etype) {
+	case TANY:
+	case TFORW:
+		// will be defined later.
+		*bad = t;
+		return -1;
+
 	case TINT8:
 	case TUINT8:
 	case TINT16:
@@ -665,11 +671,14 @@ Type*
 maptype(Type *key, Type *val)
 {
 	Type *t;
+	Type *bad;
+	int atype;
 
 	if(key != nil) {
-		switch(key->etype) {
+		atype = algtype1(key, &bad);
+		switch(bad == T ? key->etype : bad->etype) {
 		default:
-			if(algtype1(key, nil) == ANOEQ)
+			if(atype == ANOEQ)
 				yyerror("invalid map key type %T", key);
 			break;
 		case TANY:
@@ -714,6 +723,12 @@ methcmp(const void *va, const void *vb)
 	
 	a = *(Type**)va;
 	b = *(Type**)vb;
+	if(a->sym == S && b->sym == S)
+		return 0;
+	if(a->sym == S)
+		return -1;
+	if(b->sym == S)
+		return 1;
 	i = strcmp(a->sym->name, b->sym->name);
 	if(i != 0)
 		return i;
@@ -1393,7 +1408,7 @@ assignconv(Node *n, Type *t, char *context)
 	Node *r, *old;
 	char *why;
 	
-	if(n == N || n->type == T)
+	if(n == N || n->type == T || n->type->broke)
 		return n;
 
 	old = n;
@@ -1759,6 +1774,13 @@ ullmancalc(Node *n)
 	case OCALLINTER:
 		ul = UINF;
 		goto out;
+	case OANDAND:
+	case OOROR:
+		// hard with race detector
+		if(flag_race) {
+			ul = UINF;
+			goto out;
+		}
 	}
 	ul = 1;
 	if(n->left != N)
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index 50e05fc..d9c6341 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -2856,11 +2856,19 @@ walkcompare(Node **np, NodeList **init)
 	typecheck(&call, Etop);
 	walkstmt(&call);
 	*init = list(*init, call);
-	
-	if(n->op == OEQ)
-		r = tempbool;
-	else
-		r = nod(ONOT, tempbool, N);
+
+	// tempbool cannot be used directly as multiple comparison
+	// expressions may exist in the same statement. Create another
+	// temporary to hold the value (its address is not taken so it can
+	// be optimized away).
+	r = temp(types[TBOOL]);
+	a = nod(OAS, r, tempbool);
+	typecheck(&a, Etop);
+	walkstmt(&a);
+	*init = list(*init, a);
+
+	if(n->op != OEQ)
+		r = nod(ONOT, r, N);
 	typecheck(&r, Erv);
 	walkexpr(&r, init);
 	*np = r;
@@ -2889,14 +2897,29 @@ hard:
 static int
 samecheap(Node *a, Node *b)
 {
-	if(a == N || b == N || a->op != b->op)
-		return 0;
-	
-	switch(a->op) {
-	case ONAME:
-		return a == b;
-	// TODO: Could do more here, but maybe this is enough.
-	// It's all cheapexpr does.
+	Node *ar, *br;
+	while(a != N && b != N && a->op == b->op) {
+		switch(a->op) {
+		default:
+			return 0;
+		case ONAME:
+			return a == b;
+		case ODOT:
+		case ODOTPTR:
+			ar = a->right;
+			br = b->right;
+			if(ar->op != ONAME || br->op != ONAME || ar->sym != br->sym)
+				return 0;
+			break;
+		case OINDEX:
+			ar = a->right;
+			br = b->right;
+			if(!isconst(ar, CTINT) || !isconst(br, CTINT) || mpcmpfixfix(ar->val.u.xval, br->val.u.xval) != 0)
+				return 0;
+			break;
+		}
+		a = a->left;
+		b = b->left;
 	}
 	return 0;
 }
diff --git a/src/cmd/gc/y.tab.c b/src/cmd/gc/y.tab.c
index dee7939..21c67e8 100644
--- a/src/cmd/gc/y.tab.c
+++ b/src/cmd/gc/y.tab.c
@@ -658,39 +658,39 @@ static const yytype_uint16 yyrline[] =
 {
        0,   124,   124,   133,   140,   151,   151,   166,   167,   170,
      171,   172,   175,   208,   219,   220,   223,   230,   237,   246,
-     259,   260,   267,   267,   280,   284,   285,   289,   294,   300,
-     304,   308,   312,   318,   324,   330,   335,   339,   343,   349,
-     355,   359,   363,   369,   373,   379,   380,   384,   390,   399,
-     405,   423,   428,   440,   456,   461,   468,   488,   506,   515,
-     534,   533,   548,   547,   578,   581,   588,   587,   598,   604,
-     613,   624,   630,   633,   641,   640,   651,   657,   669,   673,
-     678,   668,   699,   698,   711,   714,   720,   723,   735,   739,
-     734,   757,   756,   772,   773,   777,   781,   785,   789,   793,
-     797,   801,   805,   809,   813,   817,   821,   825,   829,   833,
-     837,   841,   845,   850,   856,   857,   861,   872,   876,   880,
-     884,   889,   893,   903,   907,   912,   920,   924,   925,   936,
-     940,   944,   948,   952,   953,   959,   966,   972,   979,   982,
-     989,   995,  1012,  1019,  1020,  1027,  1028,  1047,  1048,  1051,
-    1054,  1058,  1069,  1078,  1084,  1087,  1090,  1097,  1098,  1104,
-    1119,  1127,  1139,  1144,  1150,  1151,  1152,  1153,  1154,  1155,
-    1161,  1162,  1163,  1164,  1170,  1171,  1172,  1173,  1174,  1180,
-    1181,  1184,  1187,  1188,  1189,  1190,  1191,  1194,  1195,  1208,
-    1212,  1217,  1222,  1227,  1231,  1232,  1235,  1241,  1248,  1254,
-    1261,  1267,  1278,  1292,  1321,  1361,  1386,  1404,  1413,  1416,
-    1424,  1428,  1432,  1439,  1445,  1450,  1462,  1465,  1475,  1476,
-    1482,  1483,  1489,  1493,  1499,  1500,  1506,  1510,  1516,  1539,
-    1544,  1550,  1556,  1563,  1572,  1581,  1596,  1602,  1607,  1611,
-    1618,  1631,  1632,  1638,  1644,  1647,  1651,  1657,  1660,  1669,
-    1672,  1673,  1677,  1678,  1684,  1685,  1686,  1687,  1688,  1690,
-    1689,  1704,  1709,  1713,  1717,  1721,  1725,  1730,  1749,  1755,
-    1763,  1767,  1773,  1777,  1783,  1787,  1793,  1797,  1806,  1810,
-    1814,  1818,  1824,  1827,  1835,  1836,  1838,  1839,  1842,  1845,
-    1848,  1851,  1854,  1857,  1860,  1863,  1866,  1869,  1872,  1875,
-    1878,  1881,  1887,  1891,  1895,  1899,  1903,  1907,  1927,  1934,
-    1945,  1946,  1947,  1950,  1951,  1954,  1958,  1968,  1972,  1976,
-    1980,  1984,  1988,  1992,  1998,  2004,  2012,  2020,  2026,  2033,
-    2049,  2067,  2071,  2077,  2080,  2083,  2087,  2097,  2101,  2116,
-    2124,  2125,  2137,  2138,  2141,  2145,  2151,  2155,  2161,  2165
+     260,   261,   268,   268,   281,   285,   286,   290,   295,   301,
+     305,   309,   313,   319,   325,   331,   336,   340,   344,   350,
+     356,   360,   364,   370,   374,   380,   381,   385,   391,   400,
+     406,   424,   429,   441,   457,   462,   469,   489,   507,   516,
+     535,   534,   549,   548,   579,   582,   589,   588,   599,   605,
+     614,   625,   631,   634,   642,   641,   652,   658,   670,   674,
+     679,   669,   700,   699,   712,   715,   721,   724,   736,   740,
+     735,   758,   757,   773,   774,   778,   782,   786,   790,   794,
+     798,   802,   806,   810,   814,   818,   822,   826,   830,   834,
+     838,   842,   846,   851,   857,   858,   862,   873,   877,   881,
+     885,   890,   894,   904,   908,   913,   921,   925,   926,   937,
+     941,   945,   949,   953,   954,   960,   967,   973,   980,   983,
+     990,   996,  1013,  1020,  1021,  1028,  1029,  1048,  1049,  1052,
+    1055,  1059,  1070,  1079,  1085,  1088,  1091,  1098,  1099,  1105,
+    1120,  1128,  1140,  1145,  1151,  1152,  1153,  1154,  1155,  1156,
+    1162,  1163,  1164,  1165,  1171,  1172,  1173,  1174,  1175,  1181,
+    1182,  1185,  1188,  1189,  1190,  1191,  1192,  1195,  1196,  1209,
+    1213,  1218,  1223,  1228,  1232,  1233,  1236,  1242,  1249,  1255,
+    1262,  1268,  1279,  1293,  1322,  1362,  1387,  1405,  1414,  1417,
+    1425,  1429,  1433,  1440,  1446,  1451,  1463,  1466,  1476,  1477,
+    1483,  1484,  1490,  1494,  1500,  1501,  1507,  1511,  1517,  1540,
+    1545,  1551,  1557,  1564,  1573,  1582,  1597,  1603,  1608,  1612,
+    1619,  1632,  1633,  1639,  1645,  1648,  1652,  1658,  1661,  1670,
+    1673,  1674,  1678,  1679,  1685,  1686,  1687,  1688,  1689,  1691,
+    1690,  1705,  1710,  1714,  1718,  1722,  1726,  1731,  1750,  1756,
+    1764,  1768,  1774,  1778,  1784,  1788,  1794,  1798,  1807,  1811,
+    1815,  1819,  1825,  1828,  1836,  1837,  1839,  1840,  1843,  1846,
+    1849,  1852,  1855,  1858,  1861,  1864,  1867,  1870,  1873,  1876,
+    1879,  1882,  1888,  1892,  1896,  1900,  1904,  1908,  1928,  1935,
+    1946,  1947,  1948,  1951,  1952,  1955,  1959,  1969,  1973,  1977,
+    1981,  1985,  1989,  1993,  1999,  2005,  2013,  2021,  2027,  2034,
+    2050,  2068,  2072,  2078,  2081,  2084,  2088,  2098,  2102,  2117,
+    2125,  2126,  2138,  2139,  2142,  2146,  2152,  2156,  2162,  2166
 };
 #endif
 
@@ -2494,14 +2494,15 @@ yyreduce:
 		} else if(strcmp(importpkg->name, (yyvsp[(2) - (4)].sym)->name) != 0)
 			yyerror("conflicting names %s and %s for package \"%Z\"", importpkg->name, (yyvsp[(2) - (4)].sym)->name, importpkg->path);
 		importpkg->direct = 1;
-		
+		importpkg->safe = curio.importsafe;
+
 		if(safemode && !curio.importsafe)
 			yyerror("cannot import unsafe package \"%Z\"", importpkg->path);
 	}
     break;
 
   case 21:
-#line 261 "go.y"
+#line 262 "go.y"
     {
 		if(strcmp((yyvsp[(1) - (1)].sym)->name, "safe") == 0)
 			curio.importsafe = 1;
@@ -2509,14 +2510,14 @@ yyreduce:
     break;
 
   case 22:
-#line 267 "go.y"
+#line 268 "go.y"
     {
 		defercheckwidth();
 	}
     break;
 
   case 23:
-#line 271 "go.y"
+#line 272 "go.y"
     {
 		resumecheckwidth();
 		unimportfile();
@@ -2524,7 +2525,7 @@ yyreduce:
     break;
 
   case 24:
-#line 280 "go.y"
+#line 281 "go.y"
     {
 		yyerror("empty top-level declaration");
 		(yyval.list) = nil;
@@ -2532,14 +2533,14 @@ yyreduce:
     break;
 
   case 26:
-#line 286 "go.y"
+#line 287 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
   case 27:
-#line 290 "go.y"
+#line 291 "go.y"
     {
 		yyerror("non-declaration statement outside function body");
 		(yyval.list) = nil;
@@ -2547,35 +2548,35 @@ yyreduce:
     break;
 
   case 28:
-#line 295 "go.y"
+#line 296 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
   case 29:
-#line 301 "go.y"
+#line 302 "go.y"
     {
 		(yyval.list) = (yyvsp[(2) - (2)].list);
 	}
     break;
 
   case 30:
-#line 305 "go.y"
+#line 306 "go.y"
     {
 		(yyval.list) = (yyvsp[(3) - (5)].list);
 	}
     break;
 
   case 31:
-#line 309 "go.y"
+#line 310 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
   case 32:
-#line 313 "go.y"
+#line 314 "go.y"
     {
 		(yyval.list) = (yyvsp[(2) - (2)].list);
 		iota = -100000;
@@ -2584,7 +2585,7 @@ yyreduce:
     break;
 
   case 33:
-#line 319 "go.y"
+#line 320 "go.y"
     {
 		(yyval.list) = (yyvsp[(3) - (5)].list);
 		iota = -100000;
@@ -2593,7 +2594,7 @@ yyreduce:
     break;
 
   case 34:
-#line 325 "go.y"
+#line 326 "go.y"
     {
 		(yyval.list) = concat((yyvsp[(3) - (7)].list), (yyvsp[(5) - (7)].list));
 		iota = -100000;
@@ -2602,7 +2603,7 @@ yyreduce:
     break;
 
   case 35:
-#line 331 "go.y"
+#line 332 "go.y"
     {
 		(yyval.list) = nil;
 		iota = -100000;
@@ -2610,84 +2611,84 @@ yyreduce:
     break;
 
   case 36:
-#line 336 "go.y"
+#line 337 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(2) - (2)].node));
 	}
     break;
 
   case 37:
-#line 340 "go.y"
+#line 341 "go.y"
     {
 		(yyval.list) = (yyvsp[(3) - (5)].list);
 	}
     break;
 
   case 38:
-#line 344 "go.y"
+#line 345 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
   case 39:
-#line 350 "go.y"
+#line 351 "go.y"
     {
 		iota = 0;
 	}
     break;
 
   case 40:
-#line 356 "go.y"
+#line 357 "go.y"
     {
 		(yyval.list) = variter((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node), nil);
 	}
     break;
 
   case 41:
-#line 360 "go.y"
+#line 361 "go.y"
     {
 		(yyval.list) = variter((yyvsp[(1) - (4)].list), (yyvsp[(2) - (4)].node), (yyvsp[(4) - (4)].list));
 	}
     break;
 
   case 42:
-#line 364 "go.y"
+#line 365 "go.y"
     {
 		(yyval.list) = variter((yyvsp[(1) - (3)].list), nil, (yyvsp[(3) - (3)].list));
 	}
     break;
 
   case 43:
-#line 370 "go.y"
+#line 371 "go.y"
     {
 		(yyval.list) = constiter((yyvsp[(1) - (4)].list), (yyvsp[(2) - (4)].node), (yyvsp[(4) - (4)].list));
 	}
     break;
 
   case 44:
-#line 374 "go.y"
+#line 375 "go.y"
     {
 		(yyval.list) = constiter((yyvsp[(1) - (3)].list), N, (yyvsp[(3) - (3)].list));
 	}
     break;
 
   case 46:
-#line 381 "go.y"
+#line 382 "go.y"
     {
 		(yyval.list) = constiter((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node), nil);
 	}
     break;
 
   case 47:
-#line 385 "go.y"
+#line 386 "go.y"
     {
 		(yyval.list) = constiter((yyvsp[(1) - (1)].list), N, nil);
 	}
     break;
 
   case 48:
-#line 391 "go.y"
+#line 392 "go.y"
     {
 		// different from dclname because the name
 		// becomes visible right here, not at the end
@@ -2697,14 +2698,14 @@ yyreduce:
     break;
 
   case 49:
-#line 400 "go.y"
+#line 401 "go.y"
     {
 		(yyval.node) = typedcl1((yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node), 1);
 	}
     break;
 
   case 50:
-#line 406 "go.y"
+#line 407 "go.y"
     {
 		(yyval.node) = (yyvsp[(1) - (1)].node);
 
@@ -2725,7 +2726,7 @@ yyreduce:
     break;
 
   case 51:
-#line 424 "go.y"
+#line 425 "go.y"
     {
 		(yyval.node) = nod(OASOP, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 		(yyval.node)->etype = (yyvsp[(2) - (3)].i);			// rathole to pass opcode
@@ -2733,7 +2734,7 @@ yyreduce:
     break;
 
   case 52:
-#line 429 "go.y"
+#line 430 "go.y"
     {
 		if((yyvsp[(1) - (3)].list)->next == nil && (yyvsp[(3) - (3)].list)->next == nil) {
 			// simple
@@ -2748,7 +2749,7 @@ yyreduce:
     break;
 
   case 53:
-#line 441 "go.y"
+#line 442 "go.y"
     {
 		if((yyvsp[(3) - (3)].list)->n->op == OTYPESW) {
 			(yyval.node) = nod(OTYPESW, N, (yyvsp[(3) - (3)].list)->n->right);
@@ -2767,7 +2768,7 @@ yyreduce:
     break;
 
   case 54:
-#line 457 "go.y"
+#line 458 "go.y"
     {
 		(yyval.node) = nod(OASOP, (yyvsp[(1) - (2)].node), nodintconst(1));
 		(yyval.node)->etype = OADD;
@@ -2775,7 +2776,7 @@ yyreduce:
     break;
 
   case 55:
-#line 462 "go.y"
+#line 463 "go.y"
     {
 		(yyval.node) = nod(OASOP, (yyvsp[(1) - (2)].node), nodintconst(1));
 		(yyval.node)->etype = OSUB;
@@ -2783,7 +2784,7 @@ yyreduce:
     break;
 
   case 56:
-#line 469 "go.y"
+#line 470 "go.y"
     {
 		Node *n, *nn;
 
@@ -2806,7 +2807,7 @@ yyreduce:
     break;
 
   case 57:
-#line 489 "go.y"
+#line 490 "go.y"
     {
 		Node *n;
 
@@ -2827,7 +2828,7 @@ yyreduce:
     break;
 
   case 58:
-#line 507 "go.y"
+#line 508 "go.y"
     {
 		// will be converted to OCASE
 		// right will point to next case
@@ -2839,7 +2840,7 @@ yyreduce:
     break;
 
   case 59:
-#line 516 "go.y"
+#line 517 "go.y"
     {
 		Node *n, *nn;
 
@@ -2858,14 +2859,14 @@ yyreduce:
     break;
 
   case 60:
-#line 534 "go.y"
+#line 535 "go.y"
     {
 		markdcl();
 	}
     break;
 
   case 61:
-#line 538 "go.y"
+#line 539 "go.y"
     {
 		if((yyvsp[(3) - (4)].list) == nil)
 			(yyval.node) = nod(OEMPTY, N, N);
@@ -2876,7 +2877,7 @@ yyreduce:
     break;
 
   case 62:
-#line 548 "go.y"
+#line 549 "go.y"
     {
 		// If the last token read by the lexer was consumed
 		// as part of the case, clear it (parser has cleared yychar).
@@ -2889,7 +2890,7 @@ yyreduce:
     break;
 
   case 63:
-#line 558 "go.y"
+#line 559 "go.y"
     {
 		int last;
 
@@ -2911,28 +2912,28 @@ yyreduce:
     break;
 
   case 64:
-#line 578 "go.y"
+#line 579 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
   case 65:
-#line 582 "go.y"
+#line 583 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node));
 	}
     break;
 
   case 66:
-#line 588 "go.y"
+#line 589 "go.y"
     {
 		markdcl();
 	}
     break;
 
   case 67:
-#line 592 "go.y"
+#line 593 "go.y"
     {
 		(yyval.list) = (yyvsp[(3) - (4)].list);
 		popdcl();
@@ -2940,7 +2941,7 @@ yyreduce:
     break;
 
   case 68:
-#line 599 "go.y"
+#line 600 "go.y"
     {
 		(yyval.node) = nod(ORANGE, N, (yyvsp[(4) - (4)].node));
 		(yyval.node)->list = (yyvsp[(1) - (4)].list);
@@ -2949,7 +2950,7 @@ yyreduce:
     break;
 
   case 69:
-#line 605 "go.y"
+#line 606 "go.y"
     {
 		(yyval.node) = nod(ORANGE, N, (yyvsp[(4) - (4)].node));
 		(yyval.node)->list = (yyvsp[(1) - (4)].list);
@@ -2959,7 +2960,7 @@ yyreduce:
     break;
 
   case 70:
-#line 614 "go.y"
+#line 615 "go.y"
     {
 		// init ; test ; incr
 		if((yyvsp[(5) - (5)].node) != N && (yyvsp[(5) - (5)].node)->colas != 0)
@@ -2973,7 +2974,7 @@ yyreduce:
     break;
 
   case 71:
-#line 625 "go.y"
+#line 626 "go.y"
     {
 		// normal test
 		(yyval.node) = nod(OFOR, N, N);
@@ -2982,7 +2983,7 @@ yyreduce:
     break;
 
   case 73:
-#line 634 "go.y"
+#line 635 "go.y"
     {
 		(yyval.node) = (yyvsp[(1) - (2)].node);
 		(yyval.node)->nbody = concat((yyval.node)->nbody, (yyvsp[(2) - (2)].list));
@@ -2990,14 +2991,14 @@ yyreduce:
     break;
 
   case 74:
-#line 641 "go.y"
+#line 642 "go.y"
     {
 		markdcl();
 	}
     break;
 
   case 75:
-#line 645 "go.y"
+#line 646 "go.y"
     {
 		(yyval.node) = (yyvsp[(3) - (3)].node);
 		popdcl();
@@ -3005,7 +3006,7 @@ yyreduce:
     break;
 
   case 76:
-#line 652 "go.y"
+#line 653 "go.y"
     {
 		// test
 		(yyval.node) = nod(OIF, N, N);
@@ -3014,7 +3015,7 @@ yyreduce:
     break;
 
   case 77:
-#line 658 "go.y"
+#line 659 "go.y"
     {
 		// init ; test
 		(yyval.node) = nod(OIF, N, N);
@@ -3025,14 +3026,14 @@ yyreduce:
     break;
 
   case 78:
-#line 669 "go.y"
+#line 670 "go.y"
     {
 		markdcl();
 	}
     break;
 
   case 79:
-#line 673 "go.y"
+#line 674 "go.y"
     {
 		if((yyvsp[(3) - (3)].node)->ntest == N)
 			yyerror("missing condition in if statement");
@@ -3040,14 +3041,14 @@ yyreduce:
     break;
 
   case 80:
-#line 678 "go.y"
+#line 679 "go.y"
     {
 		(yyvsp[(3) - (5)].node)->nbody = (yyvsp[(5) - (5)].list);
 	}
     break;
 
   case 81:
-#line 682 "go.y"
+#line 683 "go.y"
     {
 		Node *n;
 		NodeList *nn;
@@ -3065,14 +3066,14 @@ yyreduce:
     break;
 
   case 82:
-#line 699 "go.y"
+#line 700 "go.y"
     {
 		markdcl();
 	}
     break;
 
   case 83:
-#line 703 "go.y"
+#line 704 "go.y"
     {
 		if((yyvsp[(4) - (5)].node)->ntest == N)
 			yyerror("missing condition in if statement");
@@ -3082,28 +3083,28 @@ yyreduce:
     break;
 
   case 84:
-#line 711 "go.y"
+#line 712 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
   case 85:
-#line 715 "go.y"
+#line 716 "go.y"
     {
 		(yyval.list) = concat((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].list));
 	}
     break;
 
   case 86:
-#line 720 "go.y"
+#line 721 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
   case 87:
-#line 724 "go.y"
+#line 725 "go.y"
     {
 		NodeList *node;
 		
@@ -3115,14 +3116,14 @@ yyreduce:
     break;
 
   case 88:
-#line 735 "go.y"
+#line 736 "go.y"
     {
 		markdcl();
 	}
     break;
 
   case 89:
-#line 739 "go.y"
+#line 740 "go.y"
     {
 		Node *n;
 		n = (yyvsp[(3) - (3)].node)->ntest;
@@ -3133,7 +3134,7 @@ yyreduce:
     break;
 
   case 90:
-#line 747 "go.y"
+#line 748 "go.y"
     {
 		(yyval.node) = (yyvsp[(3) - (7)].node);
 		(yyval.node)->op = OSWITCH;
@@ -3144,14 +3145,14 @@ yyreduce:
     break;
 
   case 91:
-#line 757 "go.y"
+#line 758 "go.y"
     {
 		typesw = nod(OXXX, typesw, N);
 	}
     break;
 
   case 92:
-#line 761 "go.y"
+#line 762 "go.y"
     {
 		(yyval.node) = nod(OSELECT, N, N);
 		(yyval.node)->lineno = typesw->lineno;
@@ -3161,154 +3162,154 @@ yyreduce:
     break;
 
   case 94:
-#line 774 "go.y"
+#line 775 "go.y"
     {
 		(yyval.node) = nod(OOROR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 95:
-#line 778 "go.y"
+#line 779 "go.y"
     {
 		(yyval.node) = nod(OANDAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 96:
-#line 782 "go.y"
+#line 783 "go.y"
     {
 		(yyval.node) = nod(OEQ, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 97:
-#line 786 "go.y"
+#line 787 "go.y"
     {
 		(yyval.node) = nod(ONE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 98:
-#line 790 "go.y"
+#line 791 "go.y"
     {
 		(yyval.node) = nod(OLT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 99:
-#line 794 "go.y"
+#line 795 "go.y"
     {
 		(yyval.node) = nod(OLE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 100:
-#line 798 "go.y"
+#line 799 "go.y"
     {
 		(yyval.node) = nod(OGE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 101:
-#line 802 "go.y"
+#line 803 "go.y"
     {
 		(yyval.node) = nod(OGT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 102:
-#line 806 "go.y"
+#line 807 "go.y"
     {
 		(yyval.node) = nod(OADD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 103:
-#line 810 "go.y"
+#line 811 "go.y"
     {
 		(yyval.node) = nod(OSUB, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 104:
-#line 814 "go.y"
+#line 815 "go.y"
     {
 		(yyval.node) = nod(OOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 105:
-#line 818 "go.y"
+#line 819 "go.y"
     {
 		(yyval.node) = nod(OXOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 106:
-#line 822 "go.y"
+#line 823 "go.y"
     {
 		(yyval.node) = nod(OMUL, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 107:
-#line 826 "go.y"
+#line 827 "go.y"
     {
 		(yyval.node) = nod(ODIV, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 108:
-#line 830 "go.y"
+#line 831 "go.y"
     {
 		(yyval.node) = nod(OMOD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 109:
-#line 834 "go.y"
+#line 835 "go.y"
     {
 		(yyval.node) = nod(OAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 110:
-#line 838 "go.y"
+#line 839 "go.y"
     {
 		(yyval.node) = nod(OANDNOT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 111:
-#line 842 "go.y"
+#line 843 "go.y"
     {
 		(yyval.node) = nod(OLSH, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 112:
-#line 846 "go.y"
+#line 847 "go.y"
     {
 		(yyval.node) = nod(ORSH, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 113:
-#line 851 "go.y"
+#line 852 "go.y"
     {
 		(yyval.node) = nod(OSEND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 115:
-#line 858 "go.y"
+#line 859 "go.y"
     {
 		(yyval.node) = nod(OIND, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
   case 116:
-#line 862 "go.y"
+#line 863 "go.y"
     {
 		if((yyvsp[(2) - (2)].node)->op == OCOMPLIT) {
 			// Special case for &T{...}: turn into (*T){...}.
@@ -3322,28 +3323,28 @@ yyreduce:
     break;
 
   case 117:
-#line 873 "go.y"
+#line 874 "go.y"
     {
 		(yyval.node) = nod(OPLUS, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
   case 118:
-#line 877 "go.y"
+#line 878 "go.y"
     {
 		(yyval.node) = nod(OMINUS, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
   case 119:
-#line 881 "go.y"
+#line 882 "go.y"
     {
 		(yyval.node) = nod(ONOT, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
   case 120:
-#line 885 "go.y"
+#line 886 "go.y"
     {
 		yyerror("the bitwise complement operator is ^");
 		(yyval.node) = nod(OCOM, (yyvsp[(2) - (2)].node), N);
@@ -3351,28 +3352,28 @@ yyreduce:
     break;
 
   case 121:
-#line 890 "go.y"
+#line 891 "go.y"
     {
 		(yyval.node) = nod(OCOM, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
   case 122:
-#line 894 "go.y"
+#line 895 "go.y"
     {
 		(yyval.node) = nod(ORECV, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
   case 123:
-#line 904 "go.y"
+#line 905 "go.y"
     {
 		(yyval.node) = nod(OCALL, (yyvsp[(1) - (3)].node), N);
 	}
     break;
 
   case 124:
-#line 908 "go.y"
+#line 909 "go.y"
     {
 		(yyval.node) = nod(OCALL, (yyvsp[(1) - (5)].node), N);
 		(yyval.node)->list = (yyvsp[(3) - (5)].list);
@@ -3380,7 +3381,7 @@ yyreduce:
     break;
 
   case 125:
-#line 913 "go.y"
+#line 914 "go.y"
     {
 		(yyval.node) = nod(OCALL, (yyvsp[(1) - (6)].node), N);
 		(yyval.node)->list = (yyvsp[(3) - (6)].list);
@@ -3389,14 +3390,14 @@ yyreduce:
     break;
 
   case 126:
-#line 921 "go.y"
+#line 922 "go.y"
     {
 		(yyval.node) = nodlit((yyvsp[(1) - (1)].val));
 	}
     break;
 
   case 128:
-#line 926 "go.y"
+#line 927 "go.y"
     {
 		if((yyvsp[(1) - (3)].node)->op == OPACK) {
 			Sym *s;
@@ -3410,35 +3411,35 @@ yyreduce:
     break;
 
   case 129:
-#line 937 "go.y"
+#line 938 "go.y"
     {
 		(yyval.node) = nod(ODOTTYPE, (yyvsp[(1) - (5)].node), (yyvsp[(4) - (5)].node));
 	}
     break;
 
   case 130:
-#line 941 "go.y"
+#line 942 "go.y"
     {
 		(yyval.node) = nod(OTYPESW, N, (yyvsp[(1) - (5)].node));
 	}
     break;
 
   case 131:
-#line 945 "go.y"
+#line 946 "go.y"
     {
 		(yyval.node) = nod(OINDEX, (yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].node));
 	}
     break;
 
   case 132:
-#line 949 "go.y"
+#line 950 "go.y"
     {
 		(yyval.node) = nod(OSLICE, (yyvsp[(1) - (6)].node), nod(OKEY, (yyvsp[(3) - (6)].node), (yyvsp[(5) - (6)].node)));
 	}
     break;
 
   case 134:
-#line 954 "go.y"
+#line 955 "go.y"
     {
 		// conversion
 		(yyval.node) = nod(OCALL, (yyvsp[(1) - (5)].node), N);
@@ -3447,7 +3448,7 @@ yyreduce:
     break;
 
   case 135:
-#line 960 "go.y"
+#line 961 "go.y"
     {
 		(yyval.node) = (yyvsp[(3) - (5)].node);
 		(yyval.node)->right = (yyvsp[(1) - (5)].node);
@@ -3457,7 +3458,7 @@ yyreduce:
     break;
 
   case 136:
-#line 967 "go.y"
+#line 968 "go.y"
     {
 		(yyval.node) = (yyvsp[(3) - (5)].node);
 		(yyval.node)->right = (yyvsp[(1) - (5)].node);
@@ -3466,7 +3467,7 @@ yyreduce:
     break;
 
   case 137:
-#line 973 "go.y"
+#line 974 "go.y"
     {
 		yyerror("cannot parenthesize type in composite literal");
 		(yyval.node) = (yyvsp[(5) - (7)].node);
@@ -3476,7 +3477,7 @@ yyreduce:
     break;
 
   case 139:
-#line 982 "go.y"
+#line 983 "go.y"
     {
 		// composite expression.
 		// make node early so we get the right line number.
@@ -3485,14 +3486,14 @@ yyreduce:
     break;
 
   case 140:
-#line 990 "go.y"
+#line 991 "go.y"
     {
 		(yyval.node) = nod(OKEY, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 141:
-#line 996 "go.y"
+#line 997 "go.y"
     {
 		// These nodes do not carry line numbers.
 		// Since a composite literal commonly spans several lines,
@@ -3512,7 +3513,7 @@ yyreduce:
     break;
 
   case 142:
-#line 1013 "go.y"
+#line 1014 "go.y"
     {
 		(yyval.node) = (yyvsp[(2) - (4)].node);
 		(yyval.node)->list = (yyvsp[(3) - (4)].list);
@@ -3520,7 +3521,7 @@ yyreduce:
     break;
 
   case 144:
-#line 1021 "go.y"
+#line 1022 "go.y"
     {
 		(yyval.node) = (yyvsp[(2) - (4)].node);
 		(yyval.node)->list = (yyvsp[(3) - (4)].list);
@@ -3528,7 +3529,7 @@ yyreduce:
     break;
 
   case 146:
-#line 1029 "go.y"
+#line 1030 "go.y"
     {
 		(yyval.node) = (yyvsp[(2) - (3)].node);
 		
@@ -3548,21 +3549,21 @@ yyreduce:
     break;
 
   case 150:
-#line 1055 "go.y"
+#line 1056 "go.y"
     {
 		(yyval.i) = LBODY;
 	}
     break;
 
   case 151:
-#line 1059 "go.y"
+#line 1060 "go.y"
     {
 		(yyval.i) = '{';
 	}
     break;
 
   case 152:
-#line 1070 "go.y"
+#line 1071 "go.y"
     {
 		if((yyvsp[(1) - (1)].sym) == S)
 			(yyval.node) = N;
@@ -3572,21 +3573,21 @@ yyreduce:
     break;
 
   case 153:
-#line 1079 "go.y"
+#line 1080 "go.y"
     {
 		(yyval.node) = dclname((yyvsp[(1) - (1)].sym));
 	}
     break;
 
   case 154:
-#line 1084 "go.y"
+#line 1085 "go.y"
     {
 		(yyval.node) = N;
 	}
     break;
 
   case 156:
-#line 1091 "go.y"
+#line 1092 "go.y"
     {
 		(yyval.sym) = (yyvsp[(1) - (1)].sym);
 		// during imports, unqualified non-exported identifiers are from builtinpkg
@@ -3596,14 +3597,14 @@ yyreduce:
     break;
 
   case 158:
-#line 1099 "go.y"
+#line 1100 "go.y"
     {
 		(yyval.sym) = S;
 	}
     break;
 
   case 159:
-#line 1105 "go.y"
+#line 1106 "go.y"
     {
 		Pkg *p;
 
@@ -3619,7 +3620,7 @@ yyreduce:
     break;
 
   case 160:
-#line 1120 "go.y"
+#line 1121 "go.y"
     {
 		(yyval.node) = oldname((yyvsp[(1) - (1)].sym));
 		if((yyval.node)->pack != N)
@@ -3628,7 +3629,7 @@ yyreduce:
     break;
 
   case 162:
-#line 1140 "go.y"
+#line 1141 "go.y"
     {
 		yyerror("final argument in variadic function missing type");
 		(yyval.node) = nod(ODDD, typenod(typ(TINTER)), N);
@@ -3636,35 +3637,35 @@ yyreduce:
     break;
 
   case 163:
-#line 1145 "go.y"
+#line 1146 "go.y"
     {
 		(yyval.node) = nod(ODDD, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
   case 169:
-#line 1156 "go.y"
+#line 1157 "go.y"
     {
 		(yyval.node) = nod(OTPAREN, (yyvsp[(2) - (3)].node), N);
 	}
     break;
 
   case 173:
-#line 1165 "go.y"
+#line 1166 "go.y"
     {
 		(yyval.node) = nod(OIND, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
   case 178:
-#line 1175 "go.y"
+#line 1176 "go.y"
     {
 		(yyval.node) = nod(OTPAREN, (yyvsp[(2) - (3)].node), N);
 	}
     break;
 
   case 188:
-#line 1196 "go.y"
+#line 1197 "go.y"
     {
 		if((yyvsp[(1) - (3)].node)->op == OPACK) {
 			Sym *s;
@@ -3678,14 +3679,14 @@ yyreduce:
     break;
 
   case 189:
-#line 1209 "go.y"
+#line 1210 "go.y"
     {
 		(yyval.node) = nod(OTARRAY, (yyvsp[(2) - (4)].node), (yyvsp[(4) - (4)].node));
 	}
     break;
 
   case 190:
-#line 1213 "go.y"
+#line 1214 "go.y"
     {
 		// array literal of nelem
 		(yyval.node) = nod(OTARRAY, nod(ODDD, N, N), (yyvsp[(4) - (4)].node));
@@ -3693,7 +3694,7 @@ yyreduce:
     break;
 
   case 191:
-#line 1218 "go.y"
+#line 1219 "go.y"
     {
 		(yyval.node) = nod(OTCHAN, (yyvsp[(2) - (2)].node), N);
 		(yyval.node)->etype = Cboth;
@@ -3701,7 +3702,7 @@ yyreduce:
     break;
 
   case 192:
-#line 1223 "go.y"
+#line 1224 "go.y"
     {
 		(yyval.node) = nod(OTCHAN, (yyvsp[(3) - (3)].node), N);
 		(yyval.node)->etype = Csend;
@@ -3709,21 +3710,21 @@ yyreduce:
     break;
 
   case 193:
-#line 1228 "go.y"
+#line 1229 "go.y"
     {
 		(yyval.node) = nod(OTMAP, (yyvsp[(3) - (5)].node), (yyvsp[(5) - (5)].node));
 	}
     break;
 
   case 196:
-#line 1236 "go.y"
+#line 1237 "go.y"
     {
 		(yyval.node) = nod(OIND, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
   case 197:
-#line 1242 "go.y"
+#line 1243 "go.y"
     {
 		(yyval.node) = nod(OTCHAN, (yyvsp[(3) - (3)].node), N);
 		(yyval.node)->etype = Crecv;
@@ -3731,7 +3732,7 @@ yyreduce:
     break;
 
   case 198:
-#line 1249 "go.y"
+#line 1250 "go.y"
     {
 		(yyval.node) = nod(OTSTRUCT, N, N);
 		(yyval.node)->list = (yyvsp[(3) - (5)].list);
@@ -3740,7 +3741,7 @@ yyreduce:
     break;
 
   case 199:
-#line 1255 "go.y"
+#line 1256 "go.y"
     {
 		(yyval.node) = nod(OTSTRUCT, N, N);
 		fixlbrace((yyvsp[(2) - (3)].i));
@@ -3748,7 +3749,7 @@ yyreduce:
     break;
 
   case 200:
-#line 1262 "go.y"
+#line 1263 "go.y"
     {
 		(yyval.node) = nod(OTINTER, N, N);
 		(yyval.node)->list = (yyvsp[(3) - (5)].list);
@@ -3757,7 +3758,7 @@ yyreduce:
     break;
 
   case 201:
-#line 1268 "go.y"
+#line 1269 "go.y"
     {
 		(yyval.node) = nod(OTINTER, N, N);
 		fixlbrace((yyvsp[(2) - (3)].i));
@@ -3765,7 +3766,7 @@ yyreduce:
     break;
 
   case 202:
-#line 1279 "go.y"
+#line 1280 "go.y"
     {
 		(yyval.node) = (yyvsp[(2) - (3)].node);
 		if((yyval.node) == N)
@@ -3780,7 +3781,7 @@ yyreduce:
     break;
 
   case 203:
-#line 1293 "go.y"
+#line 1294 "go.y"
     {
 		Node *t;
 
@@ -3812,7 +3813,7 @@ yyreduce:
     break;
 
   case 204:
-#line 1322 "go.y"
+#line 1323 "go.y"
     {
 		Node *rcvr, *t;
 
@@ -3853,7 +3854,7 @@ yyreduce:
     break;
 
   case 205:
-#line 1362 "go.y"
+#line 1363 "go.y"
     {
 		Sym *s;
 		Type *t;
@@ -3881,7 +3882,7 @@ yyreduce:
     break;
 
   case 206:
-#line 1387 "go.y"
+#line 1388 "go.y"
     {
 		(yyval.node) = methodname1(newname((yyvsp[(4) - (8)].sym)), (yyvsp[(2) - (8)].list)->n->right); 
 		(yyval.node)->type = functype((yyvsp[(2) - (8)].list)->n, (yyvsp[(6) - (8)].list), (yyvsp[(8) - (8)].list));
@@ -3900,7 +3901,7 @@ yyreduce:
     break;
 
   case 207:
-#line 1405 "go.y"
+#line 1406 "go.y"
     {
 		(yyvsp[(3) - (5)].list) = checkarglist((yyvsp[(3) - (5)].list), 1);
 		(yyval.node) = nod(OTFUNC, N, N);
@@ -3910,14 +3911,14 @@ yyreduce:
     break;
 
   case 208:
-#line 1413 "go.y"
+#line 1414 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
   case 209:
-#line 1417 "go.y"
+#line 1418 "go.y"
     {
 		(yyval.list) = (yyvsp[(2) - (3)].list);
 		if((yyval.list) == nil)
@@ -3926,21 +3927,21 @@ yyreduce:
     break;
 
   case 210:
-#line 1425 "go.y"
+#line 1426 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
   case 211:
-#line 1429 "go.y"
+#line 1430 "go.y"
     {
 		(yyval.list) = list1(nod(ODCLFIELD, N, (yyvsp[(1) - (1)].node)));
 	}
     break;
 
   case 212:
-#line 1433 "go.y"
+#line 1434 "go.y"
     {
 		(yyvsp[(2) - (3)].list) = checkarglist((yyvsp[(2) - (3)].list), 0);
 		(yyval.list) = (yyvsp[(2) - (3)].list);
@@ -3948,14 +3949,14 @@ yyreduce:
     break;
 
   case 213:
-#line 1440 "go.y"
+#line 1441 "go.y"
     {
 		closurehdr((yyvsp[(1) - (1)].node));
 	}
     break;
 
   case 214:
-#line 1446 "go.y"
+#line 1447 "go.y"
     {
 		(yyval.node) = closurebody((yyvsp[(3) - (4)].list));
 		fixlbrace((yyvsp[(2) - (4)].i));
@@ -3963,21 +3964,21 @@ yyreduce:
     break;
 
   case 215:
-#line 1451 "go.y"
+#line 1452 "go.y"
     {
 		(yyval.node) = closurebody(nil);
 	}
     break;
 
   case 216:
-#line 1462 "go.y"
+#line 1463 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
   case 217:
-#line 1466 "go.y"
+#line 1467 "go.y"
     {
 		(yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(2) - (3)].list));
 		if(nsyntaxerrors == 0)
@@ -3988,56 +3989,56 @@ yyreduce:
     break;
 
   case 219:
-#line 1477 "go.y"
+#line 1478 "go.y"
     {
 		(yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list));
 	}
     break;
 
   case 221:
-#line 1484 "go.y"
+#line 1485 "go.y"
     {
 		(yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list));
 	}
     break;
 
   case 222:
-#line 1490 "go.y"
+#line 1491 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
   case 223:
-#line 1494 "go.y"
+#line 1495 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 225:
-#line 1501 "go.y"
+#line 1502 "go.y"
     {
 		(yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list));
 	}
     break;
 
   case 226:
-#line 1507 "go.y"
+#line 1508 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
   case 227:
-#line 1511 "go.y"
+#line 1512 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 228:
-#line 1517 "go.y"
+#line 1518 "go.y"
     {
 		NodeList *l;
 
@@ -4063,7 +4064,7 @@ yyreduce:
     break;
 
   case 229:
-#line 1540 "go.y"
+#line 1541 "go.y"
     {
 		(yyvsp[(1) - (2)].node)->val = (yyvsp[(2) - (2)].val);
 		(yyval.list) = list1((yyvsp[(1) - (2)].node));
@@ -4071,7 +4072,7 @@ yyreduce:
     break;
 
   case 230:
-#line 1545 "go.y"
+#line 1546 "go.y"
     {
 		(yyvsp[(2) - (4)].node)->val = (yyvsp[(4) - (4)].val);
 		(yyval.list) = list1((yyvsp[(2) - (4)].node));
@@ -4080,7 +4081,7 @@ yyreduce:
     break;
 
   case 231:
-#line 1551 "go.y"
+#line 1552 "go.y"
     {
 		(yyvsp[(2) - (3)].node)->right = nod(OIND, (yyvsp[(2) - (3)].node)->right, N);
 		(yyvsp[(2) - (3)].node)->val = (yyvsp[(3) - (3)].val);
@@ -4089,7 +4090,7 @@ yyreduce:
     break;
 
   case 232:
-#line 1557 "go.y"
+#line 1558 "go.y"
     {
 		(yyvsp[(3) - (5)].node)->right = nod(OIND, (yyvsp[(3) - (5)].node)->right, N);
 		(yyvsp[(3) - (5)].node)->val = (yyvsp[(5) - (5)].val);
@@ -4099,7 +4100,7 @@ yyreduce:
     break;
 
   case 233:
-#line 1564 "go.y"
+#line 1565 "go.y"
     {
 		(yyvsp[(3) - (5)].node)->right = nod(OIND, (yyvsp[(3) - (5)].node)->right, N);
 		(yyvsp[(3) - (5)].node)->val = (yyvsp[(5) - (5)].val);
@@ -4109,7 +4110,7 @@ yyreduce:
     break;
 
   case 234:
-#line 1573 "go.y"
+#line 1574 "go.y"
     {
 		Node *n;
 
@@ -4121,7 +4122,7 @@ yyreduce:
     break;
 
   case 235:
-#line 1582 "go.y"
+#line 1583 "go.y"
     {
 		Pkg *pkg;
 
@@ -4137,14 +4138,14 @@ yyreduce:
     break;
 
   case 236:
-#line 1597 "go.y"
+#line 1598 "go.y"
     {
 		(yyval.node) = embedded((yyvsp[(1) - (1)].sym));
 	}
     break;
 
   case 237:
-#line 1603 "go.y"
+#line 1604 "go.y"
     {
 		(yyval.node) = nod(ODCLFIELD, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node));
 		ifacedcl((yyval.node));
@@ -4152,14 +4153,14 @@ yyreduce:
     break;
 
   case 238:
-#line 1608 "go.y"
+#line 1609 "go.y"
     {
 		(yyval.node) = nod(ODCLFIELD, N, oldname((yyvsp[(1) - (1)].sym)));
 	}
     break;
 
   case 239:
-#line 1612 "go.y"
+#line 1613 "go.y"
     {
 		(yyval.node) = nod(ODCLFIELD, N, oldname((yyvsp[(2) - (3)].sym)));
 		yyerror("cannot parenthesize embedded type");
@@ -4167,7 +4168,7 @@ yyreduce:
     break;
 
   case 240:
-#line 1619 "go.y"
+#line 1620 "go.y"
     {
 		// without func keyword
 		(yyvsp[(2) - (4)].list) = checkarglist((yyvsp[(2) - (4)].list), 1);
@@ -4178,7 +4179,7 @@ yyreduce:
     break;
 
   case 242:
-#line 1633 "go.y"
+#line 1634 "go.y"
     {
 		(yyval.node) = nod(ONONAME, N, N);
 		(yyval.node)->sym = (yyvsp[(1) - (2)].sym);
@@ -4187,7 +4188,7 @@ yyreduce:
     break;
 
   case 243:
-#line 1639 "go.y"
+#line 1640 "go.y"
     {
 		(yyval.node) = nod(ONONAME, N, N);
 		(yyval.node)->sym = (yyvsp[(1) - (2)].sym);
@@ -4196,56 +4197,56 @@ yyreduce:
     break;
 
   case 245:
-#line 1648 "go.y"
+#line 1649 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
   case 246:
-#line 1652 "go.y"
+#line 1653 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 247:
-#line 1657 "go.y"
+#line 1658 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
   case 248:
-#line 1661 "go.y"
+#line 1662 "go.y"
     {
 		(yyval.list) = (yyvsp[(1) - (2)].list);
 	}
     break;
 
   case 249:
-#line 1669 "go.y"
+#line 1670 "go.y"
     {
 		(yyval.node) = N;
 	}
     break;
 
   case 251:
-#line 1674 "go.y"
+#line 1675 "go.y"
     {
 		(yyval.node) = liststmt((yyvsp[(1) - (1)].list));
 	}
     break;
 
   case 253:
-#line 1679 "go.y"
+#line 1680 "go.y"
     {
 		(yyval.node) = N;
 	}
     break;
 
   case 259:
-#line 1690 "go.y"
+#line 1691 "go.y"
     {
 		(yyvsp[(1) - (2)].node) = nod(OLABEL, (yyvsp[(1) - (2)].node), N);
 		(yyvsp[(1) - (2)].node)->sym = dclstack;  // context, for goto restrictions
@@ -4253,7 +4254,7 @@ yyreduce:
     break;
 
   case 260:
-#line 1695 "go.y"
+#line 1696 "go.y"
     {
 		NodeList *l;
 
@@ -4266,7 +4267,7 @@ yyreduce:
     break;
 
   case 261:
-#line 1705 "go.y"
+#line 1706 "go.y"
     {
 		// will be converted to OFALL
 		(yyval.node) = nod(OXFALL, N, N);
@@ -4274,35 +4275,35 @@ yyreduce:
     break;
 
   case 262:
-#line 1710 "go.y"
+#line 1711 "go.y"
     {
 		(yyval.node) = nod(OBREAK, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
   case 263:
-#line 1714 "go.y"
+#line 1715 "go.y"
     {
 		(yyval.node) = nod(OCONTINUE, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
   case 264:
-#line 1718 "go.y"
+#line 1719 "go.y"
     {
 		(yyval.node) = nod(OPROC, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
   case 265:
-#line 1722 "go.y"
+#line 1723 "go.y"
     {
 		(yyval.node) = nod(ODEFER, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
   case 266:
-#line 1726 "go.y"
+#line 1727 "go.y"
     {
 		(yyval.node) = nod(OGOTO, (yyvsp[(2) - (2)].node), N);
 		(yyval.node)->sym = dclstack;  // context, for goto restrictions
@@ -4310,7 +4311,7 @@ yyreduce:
     break;
 
   case 267:
-#line 1731 "go.y"
+#line 1732 "go.y"
     {
 		(yyval.node) = nod(ORETURN, N, N);
 		(yyval.node)->list = (yyvsp[(2) - (2)].list);
@@ -4330,7 +4331,7 @@ yyreduce:
     break;
 
   case 268:
-#line 1750 "go.y"
+#line 1751 "go.y"
     {
 		(yyval.list) = nil;
 		if((yyvsp[(1) - (1)].node) != N)
@@ -4339,7 +4340,7 @@ yyreduce:
     break;
 
   case 269:
-#line 1756 "go.y"
+#line 1757 "go.y"
     {
 		(yyval.list) = (yyvsp[(1) - (3)].list);
 		if((yyvsp[(3) - (3)].node) != N)
@@ -4348,189 +4349,189 @@ yyreduce:
     break;
 
   case 270:
-#line 1764 "go.y"
+#line 1765 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
   case 271:
-#line 1768 "go.y"
+#line 1769 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 272:
-#line 1774 "go.y"
+#line 1775 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
   case 273:
-#line 1778 "go.y"
+#line 1779 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 274:
-#line 1784 "go.y"
+#line 1785 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
   case 275:
-#line 1788 "go.y"
+#line 1789 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 276:
-#line 1794 "go.y"
+#line 1795 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
   case 277:
-#line 1798 "go.y"
+#line 1799 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 278:
-#line 1807 "go.y"
+#line 1808 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
   case 279:
-#line 1811 "go.y"
+#line 1812 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
   case 280:
-#line 1815 "go.y"
+#line 1816 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 281:
-#line 1819 "go.y"
+#line 1820 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 282:
-#line 1824 "go.y"
+#line 1825 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
   case 283:
-#line 1828 "go.y"
+#line 1829 "go.y"
     {
 		(yyval.list) = (yyvsp[(1) - (2)].list);
 	}
     break;
 
   case 288:
-#line 1842 "go.y"
+#line 1843 "go.y"
     {
 		(yyval.node) = N;
 	}
     break;
 
   case 290:
-#line 1848 "go.y"
+#line 1849 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
   case 292:
-#line 1854 "go.y"
+#line 1855 "go.y"
     {
 		(yyval.node) = N;
 	}
     break;
 
   case 294:
-#line 1860 "go.y"
+#line 1861 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
   case 296:
-#line 1866 "go.y"
+#line 1867 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
   case 298:
-#line 1872 "go.y"
+#line 1873 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
   case 300:
-#line 1878 "go.y"
+#line 1879 "go.y"
     {
 		(yyval.val).ctype = CTxxx;
 	}
     break;
 
   case 302:
-#line 1888 "go.y"
+#line 1889 "go.y"
     {
 		importimport((yyvsp[(2) - (4)].sym), (yyvsp[(3) - (4)].val).u.sval);
 	}
     break;
 
   case 303:
-#line 1892 "go.y"
+#line 1893 "go.y"
     {
 		importvar((yyvsp[(2) - (4)].sym), (yyvsp[(3) - (4)].type));
 	}
     break;
 
   case 304:
-#line 1896 "go.y"
+#line 1897 "go.y"
     {
 		importconst((yyvsp[(2) - (5)].sym), types[TIDEAL], (yyvsp[(4) - (5)].node));
 	}
     break;
 
   case 305:
-#line 1900 "go.y"
+#line 1901 "go.y"
     {
 		importconst((yyvsp[(2) - (6)].sym), (yyvsp[(3) - (6)].type), (yyvsp[(5) - (6)].node));
 	}
     break;
 
   case 306:
-#line 1904 "go.y"
+#line 1905 "go.y"
     {
 		importtype((yyvsp[(2) - (4)].type), (yyvsp[(3) - (4)].type));
 	}
     break;
 
   case 307:
-#line 1908 "go.y"
+#line 1909 "go.y"
     {
 		if((yyvsp[(2) - (4)].node) == N) {
 			dclcontext = PEXTERN;  // since we skip the funcbody below
@@ -4551,7 +4552,7 @@ yyreduce:
     break;
 
   case 308:
-#line 1928 "go.y"
+#line 1929 "go.y"
     {
 		(yyval.sym) = (yyvsp[(1) - (1)].sym);
 		structpkg = (yyval.sym)->pkg;
@@ -4559,7 +4560,7 @@ yyreduce:
     break;
 
   case 309:
-#line 1935 "go.y"
+#line 1936 "go.y"
     {
 		(yyval.type) = pkgtype((yyvsp[(1) - (1)].sym));
 		importsym((yyvsp[(1) - (1)].sym), OTYPE);
@@ -4567,14 +4568,14 @@ yyreduce:
     break;
 
   case 315:
-#line 1955 "go.y"
+#line 1956 "go.y"
     {
 		(yyval.type) = pkgtype((yyvsp[(1) - (1)].sym));
 	}
     break;
 
   case 316:
-#line 1959 "go.y"
+#line 1960 "go.y"
     {
 		// predefined name like uint8
 		(yyvsp[(1) - (1)].sym) = pkglookup((yyvsp[(1) - (1)].sym)->name, builtinpkg);
@@ -4587,49 +4588,49 @@ yyreduce:
     break;
 
   case 317:
-#line 1969 "go.y"
+#line 1970 "go.y"
     {
 		(yyval.type) = aindex(N, (yyvsp[(3) - (3)].type));
 	}
     break;
 
   case 318:
-#line 1973 "go.y"
+#line 1974 "go.y"
     {
 		(yyval.type) = aindex(nodlit((yyvsp[(2) - (4)].val)), (yyvsp[(4) - (4)].type));
 	}
     break;
 
   case 319:
-#line 1977 "go.y"
+#line 1978 "go.y"
     {
 		(yyval.type) = maptype((yyvsp[(3) - (5)].type), (yyvsp[(5) - (5)].type));
 	}
     break;
 
   case 320:
-#line 1981 "go.y"
+#line 1982 "go.y"
     {
 		(yyval.type) = tostruct((yyvsp[(3) - (4)].list));
 	}
     break;
 
   case 321:
-#line 1985 "go.y"
+#line 1986 "go.y"
     {
 		(yyval.type) = tointerface((yyvsp[(3) - (4)].list));
 	}
     break;
 
   case 322:
-#line 1989 "go.y"
+#line 1990 "go.y"
     {
 		(yyval.type) = ptrto((yyvsp[(2) - (2)].type));
 	}
     break;
 
   case 323:
-#line 1993 "go.y"
+#line 1994 "go.y"
     {
 		(yyval.type) = typ(TCHAN);
 		(yyval.type)->type = (yyvsp[(2) - (2)].type);
@@ -4638,7 +4639,7 @@ yyreduce:
     break;
 
   case 324:
-#line 1999 "go.y"
+#line 2000 "go.y"
     {
 		(yyval.type) = typ(TCHAN);
 		(yyval.type)->type = (yyvsp[(3) - (4)].type);
@@ -4647,7 +4648,7 @@ yyreduce:
     break;
 
   case 325:
-#line 2005 "go.y"
+#line 2006 "go.y"
     {
 		(yyval.type) = typ(TCHAN);
 		(yyval.type)->type = (yyvsp[(3) - (3)].type);
@@ -4656,7 +4657,7 @@ yyreduce:
     break;
 
   case 326:
-#line 2013 "go.y"
+#line 2014 "go.y"
     {
 		(yyval.type) = typ(TCHAN);
 		(yyval.type)->type = (yyvsp[(3) - (3)].type);
@@ -4665,14 +4666,14 @@ yyreduce:
     break;
 
   case 327:
-#line 2021 "go.y"
+#line 2022 "go.y"
     {
 		(yyval.type) = functype(nil, (yyvsp[(3) - (5)].list), (yyvsp[(5) - (5)].list));
 	}
     break;
 
   case 328:
-#line 2027 "go.y"
+#line 2028 "go.y"
     {
 		(yyval.node) = nod(ODCLFIELD, N, typenod((yyvsp[(2) - (3)].type)));
 		if((yyvsp[(1) - (3)].sym))
@@ -4682,7 +4683,7 @@ yyreduce:
     break;
 
   case 329:
-#line 2034 "go.y"
+#line 2035 "go.y"
     {
 		Type *t;
 	
@@ -4699,7 +4700,7 @@ yyreduce:
     break;
 
   case 330:
-#line 2050 "go.y"
+#line 2051 "go.y"
     {
 		Sym *s;
 
@@ -4718,49 +4719,49 @@ yyreduce:
     break;
 
   case 331:
-#line 2068 "go.y"
+#line 2069 "go.y"
     {
 		(yyval.node) = nod(ODCLFIELD, newname((yyvsp[(1) - (5)].sym)), typenod(functype(fakethis(), (yyvsp[(3) - (5)].list), (yyvsp[(5) - (5)].list))));
 	}
     break;
 
   case 332:
-#line 2072 "go.y"
+#line 2073 "go.y"
     {
 		(yyval.node) = nod(ODCLFIELD, N, typenod((yyvsp[(1) - (1)].type)));
 	}
     break;
 
   case 333:
-#line 2077 "go.y"
+#line 2078 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
   case 335:
-#line 2084 "go.y"
+#line 2085 "go.y"
     {
 		(yyval.list) = (yyvsp[(2) - (3)].list);
 	}
     break;
 
   case 336:
-#line 2088 "go.y"
+#line 2089 "go.y"
     {
 		(yyval.list) = list1(nod(ODCLFIELD, N, typenod((yyvsp[(1) - (1)].type))));
 	}
     break;
 
   case 337:
-#line 2098 "go.y"
+#line 2099 "go.y"
     {
 		(yyval.node) = nodlit((yyvsp[(1) - (1)].val));
 	}
     break;
 
   case 338:
-#line 2102 "go.y"
+#line 2103 "go.y"
     {
 		(yyval.node) = nodlit((yyvsp[(2) - (2)].val));
 		switch((yyval.node)->val.ctype){
@@ -4778,7 +4779,7 @@ yyreduce:
     break;
 
   case 339:
-#line 2117 "go.y"
+#line 2118 "go.y"
     {
 		(yyval.node) = oldname(pkglookup((yyvsp[(1) - (1)].sym)->name, builtinpkg));
 		if((yyval.node)->op != OLITERAL)
@@ -4787,7 +4788,7 @@ yyreduce:
     break;
 
   case 341:
-#line 2126 "go.y"
+#line 2127 "go.y"
     {
 		if((yyvsp[(2) - (5)].node)->val.ctype == CTRUNE && (yyvsp[(4) - (5)].node)->val.ctype == CTINT) {
 			(yyval.node) = (yyvsp[(2) - (5)].node);
@@ -4801,42 +4802,42 @@ yyreduce:
     break;
 
   case 344:
-#line 2142 "go.y"
+#line 2143 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
   case 345:
-#line 2146 "go.y"
+#line 2147 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 346:
-#line 2152 "go.y"
+#line 2153 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
   case 347:
-#line 2156 "go.y"
+#line 2157 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 348:
-#line 2162 "go.y"
+#line 2163 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
   case 349:
-#line 2166 "go.y"
+#line 2167 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
@@ -4844,7 +4845,7 @@ yyreduce:
 
 
 /* Line 1267 of yacc.c.  */
-#line 4849 "y.tab.c"
+#line 4850 "y.tab.c"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -5058,7 +5059,7 @@ yyreturn:
 }
 
 
-#line 2170 "go.y"
+#line 2171 "go.y"
 
 
 static void
diff --git a/src/cmd/go/clean.go b/src/cmd/go/clean.go
index ba600d3..8345c9a 100644
--- a/src/cmd/go/clean.go
+++ b/src/cmd/go/clean.go
@@ -106,6 +106,8 @@ func clean(p *Package) {
 	if cleaned[p] {
 		return
 	}
+	cleaned[p] = true
+
 	if p.Dir == "" {
 		errorf("can't load package: %v", p.Error)
 		return
diff --git a/src/cmd/go/doc.go b/src/cmd/go/doc.go
index a8a9b66..3b22e0f 100644
--- a/src/cmd/go/doc.go
+++ b/src/cmd/go/doc.go
@@ -367,9 +367,10 @@ Compile and run Go program
 
 Usage:
 
-	go run [build flags] gofiles... [arguments...]
+	go run [build flags] [gofiles...] [arguments...]
 
 Run compiles and runs the main package comprising the named Go source files.
+If no files are named, it compiles and runs all non-test Go source files.
 
 For more about build flags, see 'go help build'.
 
@@ -708,17 +709,18 @@ control the execution of any test:
 	    Print memory allocation statistics for benchmarks.
 
 	-benchtime t
-		Run enough iterations of each benchmark to take t, specified
-		as a time.Duration (for example, -benchtime 1h30s).
-		The default is 1 second (1s).
+	    Run enough iterations of each benchmark to take t, specified
+	    as a time.Duration (for example, -benchtime 1h30s).
+	    The default is 1 second (1s).
 
 	-blockprofile block.out
 	    Write a goroutine blocking profile to the specified file
 	    when all tests are complete.
 
 	-blockprofilerate n
-	    Control the detail provided in goroutine blocking profiles by setting
-	    runtime.BlockProfileRate to n.  See 'godoc runtime BlockProfileRate'.
+	    Control the detail provided in goroutine blocking profiles by
+	    calling runtime.SetBlockProfileRate with n.
+	    See 'godoc runtime SetBlockProfileRate'.
 	    The profiler aims to sample, on average, one blocking event every
 	    n nanoseconds the program spends blocked.  By default,
 	    if -test.blockprofile is set without this flag, all blocking events
@@ -760,10 +762,11 @@ control the execution of any test:
 	    exhaustive tests.
 
 	-timeout t
-		If a test runs longer than t, panic.
+	    If a test runs longer than t, panic.
 
 	-v
-	    Verbose output: log all tests as they are run.
+	    Verbose output: log all tests as they are run. Also print all
+	    text from Log and Logf calls even if the test succeeds.
 
 The test binary, called pkg.test where pkg is the name of the
 directory containing the package sources, can be invoked directly
diff --git a/src/cmd/go/env.go b/src/cmd/go/env.go
index 6cab37b..00e03e9 100644
--- a/src/cmd/go/env.go
+++ b/src/cmd/go/env.go
@@ -42,6 +42,7 @@ func mkEnv() []envVar {
 		{"GOHOSTOS", runtime.GOOS},
 		{"GOOS", goos},
 		{"GOPATH", os.Getenv("GOPATH")},
+		{"GORACE", os.Getenv("GORACE")},
 		{"GOROOT", goroot},
 		{"GOTOOLDIR", toolDir},
 	}
diff --git a/src/cmd/go/mkdoc.sh b/src/cmd/go/mkdoc.sh
index 7768bae..12fd7ba 100755
--- a/src/cmd/go/mkdoc.sh
+++ b/src/cmd/go/mkdoc.sh
@@ -3,6 +3,7 @@
 # Use of this source code is governed by a BSD-style
 # license that can be found in the LICENSE file.
 
+go install # So the next line will produce updated documentation.
 go help documentation > doc.go
 gofmt -w doc.go
 
diff --git a/src/cmd/go/run.go b/src/cmd/go/run.go
index b505693..d8ba4db 100644
--- a/src/cmd/go/run.go
+++ b/src/cmd/go/run.go
@@ -8,14 +8,16 @@ import (
 	"fmt"
 	"os"
 	"os/exec"
+	"path/filepath"
 	"strings"
 )
 
 var cmdRun = &Command{
-	UsageLine: "run [build flags] gofiles... [arguments...]",
+	UsageLine: "run [build flags] [gofiles...] [arguments...]",
 	Short:     "compile and run Go program",
 	Long: `
 Run compiles and runs the main package comprising the named Go source files.
+If no files are named, it compiles and runs all non-test Go source files.
 
 For more about build flags, see 'go help build'.
 
@@ -44,7 +46,18 @@ func runRun(cmd *Command, args []string) {
 	}
 	files, cmdArgs := args[:i], args[i:]
 	if len(files) == 0 {
-		fatalf("go run: no go files listed")
+		allFiles, err := filepath.Glob("*.go")
+		if err != nil {
+			fatalf("go run: %s", err)
+		}
+		for _, file := range allFiles {
+			if !strings.HasSuffix(file, "_test.go") {
+				files = append(files, file)
+			}
+		}
+		if len(files) == 0 {
+			fatalf("go run: no go files found")
+		}
 	}
 	for _, file := range files {
 		if strings.HasSuffix(file, "_test.go") {
diff --git a/src/cmd/go/test.go b/src/cmd/go/test.go
index de69efe..58ebcc0 100644
--- a/src/cmd/go/test.go
+++ b/src/cmd/go/test.go
@@ -98,17 +98,18 @@ control the execution of any test:
 	    Print memory allocation statistics for benchmarks.
 
 	-benchtime t
-		Run enough iterations of each benchmark to take t, specified
-		as a time.Duration (for example, -benchtime 1h30s).
-		The default is 1 second (1s).
+	    Run enough iterations of each benchmark to take t, specified
+	    as a time.Duration (for example, -benchtime 1h30s).
+	    The default is 1 second (1s).
 
 	-blockprofile block.out
 	    Write a goroutine blocking profile to the specified file
 	    when all tests are complete.
 
 	-blockprofilerate n
-	    Control the detail provided in goroutine blocking profiles by setting
-	    runtime.BlockProfileRate to n.  See 'godoc runtime BlockProfileRate'.
+	    Control the detail provided in goroutine blocking profiles by
+	    calling runtime.SetBlockProfileRate with n.
+	    See 'godoc runtime SetBlockProfileRate'.
 	    The profiler aims to sample, on average, one blocking event every
 	    n nanoseconds the program spends blocked.  By default,
 	    if -test.blockprofile is set without this flag, all blocking events
@@ -150,10 +151,11 @@ control the execution of any test:
 	    exhaustive tests.
 
 	-timeout t
-		If a test runs longer than t, panic.
+	    If a test runs longer than t, panic.
 
 	-v
-	    Verbose output: log all tests as they are run.
+	    Verbose output: log all tests as they are run. Also print all
+	    text from Log and Logf calls even if the test succeeds.
 
 The test binary, called pkg.test where pkg is the name of the
 directory containing the package sources, can be invoked directly
diff --git a/src/cmd/godoc/doc.go b/src/cmd/godoc/doc.go
index e5f5324..1fa57a8 100644
--- a/src/cmd/godoc/doc.go
+++ b/src/cmd/godoc/doc.go
@@ -61,6 +61,8 @@ The flags are:
 		to the indexer (the indexer will never finish), a value of 1.0
 		means that index creation is running at full throttle (other
 		goroutines may get no time while the index is built)
+	-links=true:
+		link identifiers to their declarations
 	-write_index=false
 		write index to a file; the file name must be specified with
 		-index_files
diff --git a/src/cmd/godoc/format.go b/src/cmd/godoc/format.go
index 122ddc7..59a89c5 100644
--- a/src/cmd/godoc/format.go
+++ b/src/cmd/godoc/format.go
@@ -23,15 +23,21 @@ import (
 // ----------------------------------------------------------------------------
 // Implementation of FormatSelections
 
-// A Selection is a function returning offset pairs []int{a, b}
-// describing consecutive non-overlapping text segments [a, b).
-// If there are no more segments, a Selection must return nil.
+// A Segment describes a text segment [start, end).
+// The zero value of a Segment is a ready-to-use empty segment.
 //
-// TODO It's more efficient to return a pair (a, b int) instead
-//      of creating lots of slices. Need to determine how to
-//      indicate the end of a Selection.
+type Segment struct {
+	start, end int
+}
+
+func (seg *Segment) isEmpty() bool { return seg.start >= seg.end }
+
+// A Selection is an "iterator" function returning a text segment.
+// Repeated calls to a selection return consecutive, non-overlapping,
+// non-empty segments, followed by an infinite sequence of empty
+// segments. The first empty segment marks the end of the selection.
 //
-type Selection func() []int
+type Selection func() Segment
 
 // A LinkWriter writes some start or end "tag" to w for the text offset offs.
 // It is called by FormatSelections at the start or end of each link segment.
@@ -141,17 +147,17 @@ func FormatSelections(w io.Writer, text []byte, lw LinkWriter, links Selection,
 //
 type merger struct {
 	selections []Selection
-	segments   [][]int // segments[i] is the next segment of selections[i]
+	segments   []Segment // segments[i] is the next segment of selections[i]
 }
 
 const infinity int = 2e9
 
 func newMerger(selections []Selection) *merger {
-	segments := make([][]int, len(selections))
+	segments := make([]Segment, len(selections))
 	for i, sel := range selections {
-		segments[i] = []int{infinity, infinity}
+		segments[i] = Segment{infinity, infinity}
 		if sel != nil {
-			if seg := sel(); seg != nil {
+			if seg := sel(); !seg.isEmpty() {
 				segments[i] = seg
 			}
 		}
@@ -170,12 +176,12 @@ func (m *merger) next() (index, offs int, start bool) {
 	index = -1
 	for i, seg := range m.segments {
 		switch {
-		case seg[0] < offs:
-			offs = seg[0]
+		case seg.start < offs:
+			offs = seg.start
 			index = i
 			start = true
-		case seg[1] < offs:
-			offs = seg[1]
+		case seg.end < offs:
+			offs = seg.end
 			index = i
 			start = false
 		}
@@ -188,18 +194,17 @@ func (m *merger) next() (index, offs int, start bool) {
 	// either way it is ok to consume the start offset: set it
 	// to infinity so it won't be considered in the following
 	// next call
-	m.segments[index][0] = infinity
+	m.segments[index].start = infinity
 	if start {
 		return
 	}
 	// end offset found - consume it
-	m.segments[index][1] = infinity
+	m.segments[index].end = infinity
 	// advance to the next segment for that selection
 	seg := m.selections[index]()
-	if seg == nil {
-		return
+	if !seg.isEmpty() {
+		m.segments[index] = seg
 	}
-	m.segments[index] = seg
 	return
 }
 
@@ -209,7 +214,7 @@ func (m *merger) next() (index, offs int, start bool) {
 // lineSelection returns the line segments for text as a Selection.
 func lineSelection(text []byte) Selection {
 	i, j := 0, 0
-	return func() (seg []int) {
+	return func() (seg Segment) {
 		// find next newline, if any
 		for j < len(text) {
 			j++
@@ -219,30 +224,30 @@ func lineSelection(text []byte) Selection {
 		}
 		if i < j {
 			// text[i:j] constitutes a line
-			seg = []int{i, j}
+			seg = Segment{i, j}
 			i = j
 		}
 		return
 	}
 }
 
-// commentSelection returns the sequence of consecutive comments
-// in the Go src text as a Selection.
+// tokenSelection returns, as a selection, the sequence of
+// consecutive occurrences of token sel in the Go src text.
 //
-func commentSelection(src []byte) Selection {
+func tokenSelection(src []byte, sel token.Token) Selection {
 	var s scanner.Scanner
 	fset := token.NewFileSet()
 	file := fset.AddFile("", fset.Base(), len(src))
 	s.Init(file, src, nil, scanner.ScanComments)
-	return func() (seg []int) {
+	return func() (seg Segment) {
 		for {
 			pos, tok, lit := s.Scan()
 			if tok == token.EOF {
 				break
 			}
 			offs := file.Offset(pos)
-			if tok == token.COMMENT {
-				seg = []int{offs, offs + len(lit)}
+			if tok == sel {
+				seg = Segment{offs, offs + len(lit)}
 				break
 			}
 		}
@@ -251,13 +256,20 @@ func commentSelection(src []byte) Selection {
 }
 
 // makeSelection is a helper function to make a Selection from a slice of pairs.
+// Pairs describing empty segments are ignored.
+//
 func makeSelection(matches [][]int) Selection {
-	return func() (seg []int) {
-		if len(matches) > 0 {
-			seg = matches[0]
-			matches = matches[1:]
+	i := 0
+	return func() Segment {
+		for i < len(matches) {
+			m := matches[i]
+			i++
+			if m[0] < m[1] {
+				// non-empty segment
+				return Segment{m[0], m[1]}
+			}
 		}
-		return
+		return Segment{}
 	}
 }
 
@@ -338,7 +350,7 @@ func selectionTag(w io.Writer, text []byte, selections int) {
 func FormatText(w io.Writer, text []byte, line int, goSource bool, pattern string, selection Selection) {
 	var comments, highlights Selection
 	if goSource {
-		comments = commentSelection(text)
+		comments = tokenSelection(text, token.COMMENT)
 	}
 	if pattern != "" {
 		highlights = regexpSelection(text, pattern)
diff --git a/src/cmd/godoc/godoc.go b/src/cmd/godoc/godoc.go
index 5774321..26b0b97 100644
--- a/src/cmd/godoc/godoc.go
+++ b/src/cmd/godoc/godoc.go
@@ -66,6 +66,7 @@ var (
 	templateDir    = flag.String("templates", "", "directory containing alternate template files")
 	showPlayground = flag.Bool("play", false, "enable playground in web interface")
 	showExamples   = flag.Bool("ex", false, "show examples in command line mode")
+	declLinks      = flag.Bool("links", true, "link identifiers to their declarations")
 
 	// search index
 	indexEnabled = flag.Bool("index", false, "enable search index")
@@ -272,17 +273,23 @@ func infoSnippet_htmlFunc(info SpotInfo) string {
 	return `<span class="alert">no snippet text available</span>`
 }
 
-func nodeFunc(node interface{}, fset *token.FileSet) string {
+func nodeFunc(info *PageInfo, node interface{}) string {
 	var buf bytes.Buffer
-	writeNode(&buf, fset, node)
+	writeNode(&buf, info.FSet, node)
 	return buf.String()
 }
 
-func node_htmlFunc(node interface{}, fset *token.FileSet) string {
+func node_htmlFunc(info *PageInfo, node interface{}, linkify bool) string {
 	var buf1 bytes.Buffer
-	writeNode(&buf1, fset, node)
+	writeNode(&buf1, info.FSet, node)
+
 	var buf2 bytes.Buffer
-	FormatText(&buf2, buf1.Bytes(), -1, true, "", nil)
+	if n, _ := node.(ast.Node); n != nil && linkify && *declLinks {
+		LinkifyText(&buf2, buf1.Bytes(), n)
+	} else {
+		FormatText(&buf2, buf1.Bytes(), -1, true, "", nil)
+	}
+
 	return buf2.String()
 }
 
@@ -333,14 +340,14 @@ func stripExampleSuffix(name string) string {
 	return name
 }
 
-func example_textFunc(funcName string, examples []*doc.Example, fset *token.FileSet, indent string) string {
+func example_textFunc(info *PageInfo, funcName, indent string) string {
 	if !*showExamples {
 		return ""
 	}
 
 	var buf bytes.Buffer
 	first := true
-	for _, eg := range examples {
+	for _, eg := range info.Examples {
 		name := stripExampleSuffix(eg.Name)
 		if name != funcName {
 			continue
@@ -354,7 +361,7 @@ func example_textFunc(funcName string, examples []*doc.Example, fset *token.File
 		// print code
 		cnode := &printer.CommentedNode{Node: eg.Code, Comments: eg.Comments}
 		var buf1 bytes.Buffer
-		writeNode(&buf1, fset, cnode)
+		writeNode(&buf1, info.FSet, cnode)
 		code := buf1.String()
 		// Additional formatting if this is a function body.
 		if n := len(code); n >= 2 && code[0] == '{' && code[n-1] == '}' {
@@ -374,9 +381,9 @@ func example_textFunc(funcName string, examples []*doc.Example, fset *token.File
 	return buf.String()
 }
 
-func example_htmlFunc(funcName string, examples []*doc.Example, fset *token.FileSet) string {
+func example_htmlFunc(info *PageInfo, funcName string) string {
 	var buf bytes.Buffer
-	for _, eg := range examples {
+	for _, eg := range info.Examples {
 		name := stripExampleSuffix(eg.Name)
 
 		if name != funcName {
@@ -385,7 +392,7 @@ func example_htmlFunc(funcName string, examples []*doc.Example, fset *token.File
 
 		// print code
 		cnode := &printer.CommentedNode{Node: eg.Code, Comments: eg.Comments}
-		code := node_htmlFunc(cnode, fset)
+		code := node_htmlFunc(info, cnode, true)
 		out := eg.Output
 		wholeFile := true
 
@@ -407,7 +414,7 @@ func example_htmlFunc(funcName string, examples []*doc.Example, fset *token.File
 		play := ""
 		if eg.Play != nil && *showPlayground {
 			var buf bytes.Buffer
-			if err := format.Node(&buf, fset, eg.Play); err != nil {
+			if err := format.Node(&buf, info.FSet, eg.Play); err != nil {
 				log.Print(err)
 			} else {
 				play = buf.String()
@@ -472,19 +479,33 @@ func pkgLinkFunc(path string) string {
 	return pkgHandler.pattern[1:] + relpath // remove trailing '/' for relative URL
 }
 
-func posLink_urlFunc(node ast.Node, fset *token.FileSet) string {
+// n must be an ast.Node or a *doc.Note
+func posLink_urlFunc(info *PageInfo, n interface{}) string {
+	var pos, end token.Pos
+
+	switch n := n.(type) {
+	case ast.Node:
+		pos = n.Pos()
+		end = n.End()
+	case *doc.Note:
+		pos = n.Pos
+		end = n.End
+	default:
+		panic(fmt.Sprintf("wrong type for posLink_url template formatter: %T", n))
+	}
+
 	var relpath string
 	var line int
-	var low, high int // selection
+	var low, high int // selection offset range
 
-	if p := node.Pos(); p.IsValid() {
-		pos := fset.Position(p)
-		relpath = pos.Filename
-		line = pos.Line
-		low = pos.Offset
+	if pos.IsValid() {
+		p := info.FSet.Position(pos)
+		relpath = p.Filename
+		line = p.Line
+		low = p.Offset
 	}
-	if p := node.End(); p.IsValid() {
-		high = fset.Position(p).Offset
+	if end.IsValid() {
+		high = info.FSet.Position(end).Offset
 	}
 
 	var buf bytes.Buffer
@@ -521,7 +542,7 @@ var fmap = template.FuncMap{
 	"filename": filenameFunc,
 	"repeat":   strings.Repeat,
 
-	// accss to FileInfos (directory listings)
+	// access to FileInfos (directory listings)
 	"fileInfoName": fileInfoNameFunc,
 	"fileInfoTime": fileInfoTimeFunc,
 
@@ -1020,6 +1041,23 @@ func collectExamples(pkg *ast.Package, testfiles map[string]*ast.File) []*doc.Ex
 	return examples
 }
 
+// poorMansImporter returns a (dummy) package object named
+// by the last path component of the provided package path
+// (as is the convention for packages). This is sufficient
+// to resolve package identifiers without doing an actual
+// import. It never returns an error.
+//
+func poorMansImporter(imports map[string]*ast.Object, path string) (*ast.Object, error) {
+	pkg := imports[path]
+	if pkg == nil {
+		// note that strings.LastIndex returns -1 if there is no "/"
+		pkg = ast.NewObj(ast.Pkg, path[strings.LastIndex(path, "/")+1:])
+		pkg.Data = ast.NewScope(nil) // required by ast.NewPackage for dot-import
+		imports[path] = pkg
+	}
+	return pkg, nil
+}
+
 // getPageInfo returns the PageInfo for a package directory abspath. If the
 // parameter genAST is set, an AST containing only the package exports is
 // computed (PageInfo.PAst), otherwise package documentation (PageInfo.Doc)
@@ -1028,8 +1066,8 @@ func collectExamples(pkg *ast.Package, testfiles map[string]*ast.File) []*doc.Ex
 // directories, PageInfo.Dirs is nil. If an error occurred, PageInfo.Err is
 // set to the respective error but the error is not logged.
 //
-func (h *docServer) getPageInfo(abspath, relpath string, mode PageInfoMode) (info PageInfo) {
-	info.Dirname = abspath
+func (h *docServer) getPageInfo(abspath, relpath string, mode PageInfoMode) *PageInfo {
+	info := &PageInfo{Dirname: abspath}
 
 	// Restrict to the package files that would be used when building
 	// the package on this system.  This makes sure that if there are
@@ -1046,7 +1084,7 @@ func (h *docServer) getPageInfo(abspath, relpath string, mode PageInfoMode) (inf
 	// continue if there are no Go source files; we still want the directory info
 	if _, nogo := err.(*build.NoGoError); err != nil && !nogo {
 		info.Err = err
-		return
+		return info
 	}
 
 	// collect package files
@@ -1069,9 +1107,11 @@ func (h *docServer) getPageInfo(abspath, relpath string, mode PageInfoMode) (inf
 		files, err := parseFiles(fset, abspath, pkgfiles)
 		if err != nil {
 			info.Err = err
-			return
+			return info
 		}
-		pkg := &ast.Package{Name: pkgname, Files: files}
+
+		// ignore any errors - they are due to unresolved identifiers
+		pkg, _ := ast.NewPackage(fset, files, poorMansImporter, nil)
 
 		// extract package documentation
 		info.FSet = fset
@@ -1143,7 +1183,7 @@ func (h *docServer) getPageInfo(abspath, relpath string, mode PageInfoMode) (inf
 	info.DirTime = timestamp
 	info.DirFlat = mode&flatDir != 0
 
-	return
+	return info
 }
 
 func (h *docServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
@@ -1475,6 +1515,8 @@ func readIndex(filenames string) error {
 	matches, err := filepath.Glob(filenames)
 	if err != nil {
 		return err
+	} else if matches == nil {
+		return fmt.Errorf("no index files match %q", filenames)
 	}
 	sort.Strings(matches) // make sure files are in the right order
 	files := make([]io.Reader, 0, len(matches))
diff --git a/src/cmd/godoc/index.go b/src/cmd/godoc/index.go
index 91c5646..8198fca 100644
--- a/src/cmd/godoc/index.go
+++ b/src/cmd/godoc/index.go
@@ -651,8 +651,6 @@ func (x *Indexer) addFile(filename string, goFile bool) (file *token.File, ast *
 // makes sure that the important files are included and massively reduces the
 // number of files to index. The advantage over a blacklist is that unexpected
 // (non-blacklisted) files won't suddenly explode the index.
-//
-// TODO(gri): We may want to make this list customizable, perhaps via a flag.
 
 // Files are whitelisted if they have a file name or extension
 // present as key in whitelisted.
diff --git a/src/cmd/godoc/linkify.go b/src/cmd/godoc/linkify.go
new file mode 100644
index 0000000..5b48624
--- /dev/null
+++ b/src/cmd/godoc/linkify.go
@@ -0,0 +1,234 @@
+// Copyright 2013 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.
+
+// This file implements LinkifyText which introduces
+// links for identifiers pointing to their declarations.
+// The approach does not cover all cases because godoc
+// doesn't have complete type information, but it's
+// reasonably good for browsing.
+
+package main
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"io"
+	"strconv"
+)
+
+// LinkifyText HTML-escapes source text and writes it to w.
+// Identifiers that are in a "use" position (i.e., that are
+// not being declared), are wrapped with HTML links pointing
+// to the respective declaration, if possible. Comments are
+// formatted the same way as with FormatText.
+//
+func LinkifyText(w io.Writer, text []byte, n ast.Node) {
+	links := linksFor(n)
+
+	i := 0     // links index
+	prev := "" // prev HTML tag
+	linkWriter := func(w io.Writer, _ int, start bool) {
+		// end tag
+		if !start {
+			if prev != "" {
+				fmt.Fprintf(w, `</%s>`, prev)
+				prev = ""
+			}
+			return
+		}
+
+		// start tag
+		prev = ""
+		if i < len(links) {
+			switch info := links[i]; {
+			case info.path != "" && info.name == "":
+				// package path
+				fmt.Fprintf(w, `<a href="/pkg/%s/">`, info.path)
+				prev = "a"
+			case info.path != "" && info.name != "":
+				// qualified identifier
+				fmt.Fprintf(w, `<a href="/pkg/%s/#%s">`, info.path, info.name)
+				prev = "a"
+			case info.path == "" && info.name != "":
+				// local identifier
+				if info.mode == identVal {
+					fmt.Fprintf(w, `<span id="%s">`, info.name)
+					prev = "span"
+				} else {
+					fmt.Fprintf(w, `<a href="#%s">`, info.name)
+					prev = "a"
+				}
+			}
+			i++
+		}
+	}
+
+	idents := tokenSelection(text, token.IDENT)
+	comments := tokenSelection(text, token.COMMENT)
+	FormatSelections(w, text, linkWriter, idents, selectionTag, comments)
+}
+
+// A link describes the (HTML) link information for an identifier.
+// The zero value of a link represents "no link".
+//
+type link struct {
+	mode       identMode
+	path, name string // package path, identifier name
+}
+
+// linksFor returns the list of links for the identifiers used
+// by node in the same order as they appear in the source.
+//
+func linksFor(node ast.Node) (list []link) {
+	modes := identModesFor(node)
+
+	// NOTE: We are expecting ast.Inspect to call the
+	//       callback function in source text order.
+	ast.Inspect(node, func(node ast.Node) bool {
+		switch n := node.(type) {
+		case *ast.Ident:
+			m := modes[n]
+			info := link{mode: m}
+			switch m {
+			case identUse:
+				if n.Obj == nil && predeclared[n.Name] {
+					info.path = builtinPkgPath
+				}
+				info.name = n.Name
+			case identDef:
+				// any declaration expect const or var - empty link
+			case identVal:
+				// const or var declaration
+				info.name = n.Name
+			}
+			list = append(list, info)
+			return false
+		case *ast.SelectorExpr:
+			// Detect qualified identifiers of the form pkg.ident.
+			// If anything fails we return true and collect individual
+			// identifiers instead.
+			if x, _ := n.X.(*ast.Ident); x != nil {
+				// x must be a package for a qualified identifier
+				if obj := x.Obj; obj != nil && obj.Kind == ast.Pkg {
+					if spec, _ := obj.Decl.(*ast.ImportSpec); spec != nil {
+						// spec.Path.Value is the import path
+						if path, err := strconv.Unquote(spec.Path.Value); err == nil {
+							// Register two links, one for the package
+							// and one for the qualified identifier.
+							info := link{path: path}
+							list = append(list, info)
+							info.name = n.Sel.Name
+							list = append(list, info)
+							return false
+						}
+					}
+				}
+			}
+		}
+		return true
+	})
+
+	return
+}
+
+// The identMode describes how an identifier is "used" at its source location.
+type identMode int
+
+const (
+	identUse identMode = iota // identifier is used (must be zero value for identMode)
+	identDef                  // identifier is defined
+	identVal                  // identifier is defined in a const or var declaration
+)
+
+// identModesFor returns a map providing the identMode for each identifier used by node.
+func identModesFor(node ast.Node) map[*ast.Ident]identMode {
+	m := make(map[*ast.Ident]identMode)
+
+	ast.Inspect(node, func(node ast.Node) bool {
+		switch n := node.(type) {
+		case *ast.Field:
+			for _, n := range n.Names {
+				m[n] = identDef
+			}
+		case *ast.ImportSpec:
+			if name := n.Name; name != nil {
+				m[name] = identDef
+			}
+		case *ast.ValueSpec:
+			for _, n := range n.Names {
+				m[n] = identVal
+			}
+		case *ast.TypeSpec:
+			m[n.Name] = identDef
+		case *ast.FuncDecl:
+			m[n.Name] = identDef
+		case *ast.AssignStmt:
+			// Short variable declarations only show up if we apply
+			// this code to all source code (as opposed to exported
+			// declarations only).
+			if n.Tok == token.DEFINE {
+				// Some of the lhs variables may be re-declared,
+				// so technically they are not defs. We don't
+				// care for now.
+				for _, x := range n.Lhs {
+					// Each lhs expression should be an
+					// ident, but we are conservative and check.
+					if n, _ := x.(*ast.Ident); n != nil {
+						m[n] = identVal
+					}
+				}
+			}
+		}
+		return true
+	})
+
+	return m
+}
+
+// The predeclared map represents the set of all predeclared identifiers.
+// TODO(gri) This information is also encoded in similar maps in go/doc,
+//           but not exported. Consider exporting an accessor and using
+//           it instead.
+var predeclared = map[string]bool{
+	"bool":       true,
+	"byte":       true,
+	"complex64":  true,
+	"complex128": true,
+	"error":      true,
+	"float32":    true,
+	"float64":    true,
+	"int":        true,
+	"int8":       true,
+	"int16":      true,
+	"int32":      true,
+	"int64":      true,
+	"rune":       true,
+	"string":     true,
+	"uint":       true,
+	"uint8":      true,
+	"uint16":     true,
+	"uint32":     true,
+	"uint64":     true,
+	"uintptr":    true,
+	"true":       true,
+	"false":      true,
+	"iota":       true,
+	"nil":        true,
+	"append":     true,
+	"cap":        true,
+	"close":      true,
+	"complex":    true,
+	"copy":       true,
+	"delete":     true,
+	"imag":       true,
+	"len":        true,
+	"make":       true,
+	"new":        true,
+	"panic":      true,
+	"print":      true,
+	"println":    true,
+	"real":       true,
+	"recover":    true,
+}
diff --git a/src/cmd/godoc/main.go b/src/cmd/godoc/main.go
index 1344100..81e739d 100644
--- a/src/cmd/godoc/main.go
+++ b/src/cmd/godoc/main.go
@@ -374,26 +374,26 @@ func main() {
 	}
 
 	// first, try as package unless forced as command
-	var info PageInfo
+	var info *PageInfo
 	if !forceCmd {
 		info = pkgHandler.getPageInfo(abspath, relpath, mode)
 	}
 
 	// second, try as command unless the path is absolute
 	// (the go command invokes godoc w/ absolute paths; don't override)
-	var cinfo PageInfo
+	var cinfo *PageInfo
 	if !filepath.IsAbs(path) {
 		abspath = pathpkg.Join(cmdHandler.fsRoot, path)
 		cinfo = cmdHandler.getPageInfo(abspath, relpath, mode)
 	}
 
 	// determine what to use
-	if info.IsEmpty() {
-		if !cinfo.IsEmpty() {
+	if info == nil || info.IsEmpty() {
+		if cinfo != nil && !cinfo.IsEmpty() {
 			// only cinfo exists - switch to cinfo
 			info = cinfo
 		}
-	} else if !cinfo.IsEmpty() {
+	} else if cinfo != nil && !cinfo.IsEmpty() {
 		// both info and cinfo exist - use cinfo if info
 		// contains only subdirectory information
 		if info.PAst == nil && info.PDoc == nil {
@@ -403,15 +403,19 @@ func main() {
 		}
 	}
 
+	if info == nil {
+		log.Fatalf("%s: no such directory or package", flag.Arg(0))
+	}
 	if info.Err != nil {
 		log.Fatalf("%v", info.Err)
 	}
+
 	if info.PDoc != nil && info.PDoc.ImportPath == target {
 		// Replace virtual /target with actual argument from command line.
 		info.PDoc.ImportPath = flag.Arg(0)
 	}
 
-	// If we have more than one argument, use the remaining arguments for filtering
+	// If we have more than one argument, use the remaining arguments for filtering.
 	if flag.NArg() > 1 {
 		args := flag.Args()[1:]
 		rx := makeRx(args)
diff --git a/src/cmd/godoc/utils.go b/src/cmd/godoc/utils.go
index 7def015..0cdb7ff 100644
--- a/src/cmd/godoc/utils.go
+++ b/src/cmd/godoc/utils.go
@@ -56,8 +56,6 @@ func isText(s []byte) bool {
 	return true
 }
 
-// TODO(gri): Should have a mapping from extension to handler, eventually.
-
 // textExt[x] is true if the extension x indicates a text file, and false otherwise.
 var textExt = map[string]bool{
 	".css": false, // must be served raw
diff --git a/src/cmd/gofmt/gofmt_test.go b/src/cmd/gofmt/gofmt_test.go
index 202d0a5..75a322a 100644
--- a/src/cmd/gofmt/gofmt_test.go
+++ b/src/cmd/gofmt/gofmt_test.go
@@ -82,6 +82,9 @@ var tests = []struct {
 	{"testdata/rewrite3.input", "-r=x->x"},
 	{"testdata/rewrite4.input", "-r=(x)->x"},
 	{"testdata/rewrite5.input", "-r=x+x->2*x"},
+	{"testdata/rewrite6.input", "-r=fun(x)->Fun(x)"},
+	{"testdata/rewrite7.input", "-r=fun(x...)->Fun(x)"},
+	{"testdata/rewrite8.input", "-r=interface{}->int"},
 	{"testdata/stdin*.input", "-stdin"},
 	{"testdata/comments.input", ""},
 	{"testdata/import.input", ""},
diff --git a/src/cmd/gofmt/rewrite.go b/src/cmd/gofmt/rewrite.go
index dfabb61..66d2331 100644
--- a/src/cmd/gofmt/rewrite.go
+++ b/src/cmd/gofmt/rewrite.go
@@ -35,10 +35,10 @@ func initRewrite() {
 // It might make sense to expand this to allow statement patterns,
 // but there are problems with preserving formatting and also
 // with what a wildcard for a statement looks like.
-func parseExpr(s string, what string) ast.Expr {
+func parseExpr(s, what string) ast.Expr {
 	x, err := parser.ParseExpr(s)
 	if err != nil {
-		fmt.Fprintf(os.Stderr, "parsing %s %s: %s\n", what, s, err)
+		fmt.Fprintf(os.Stderr, "parsing %s %s at %s\n", what, s, err)
 		os.Exit(2)
 	}
 	return x
@@ -107,6 +107,7 @@ var (
 	identType     = reflect.TypeOf((*ast.Ident)(nil))
 	objectPtrType = reflect.TypeOf((*ast.Object)(nil))
 	positionType  = reflect.TypeOf(token.NoPos)
+	callExprType  = reflect.TypeOf((*ast.CallExpr)(nil))
 	scopePtrType  = reflect.TypeOf((*ast.Scope)(nil))
 )
 
@@ -192,8 +193,17 @@ func match(m map[string]reflect.Value, pattern, val reflect.Value) bool {
 		v := val.Interface().(*ast.Ident)
 		return p == nil && v == nil || p != nil && v != nil && p.Name == v.Name
 	case objectPtrType, positionType:
-		// object pointers and token positions don't need to match
+		// object pointers and token positions always match
 		return true
+	case callExprType:
+		// For calls, the Ellipsis fields (token.Position) must
+		// match since that is how f(x) and f(x...) are different.
+		// Check them here but fall through for the remaining fields.
+		p := pattern.Interface().(*ast.CallExpr)
+		v := val.Interface().(*ast.CallExpr)
+		if p.Ellipsis.IsValid() != v.Ellipsis.IsValid() {
+			return false
+		}
 	}
 
 	p := reflect.Indirect(pattern)
diff --git a/src/cmd/gofmt/testdata/rewrite6.golden b/src/cmd/gofmt/testdata/rewrite6.golden
new file mode 100644
index 0000000..e565dbd
--- /dev/null
+++ b/src/cmd/gofmt/testdata/rewrite6.golden
@@ -0,0 +1,15 @@
+// Copyright 2013 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.
+
+// Rewriting of calls must take the ... (ellipsis)
+// attribute for the last argument into account.
+
+package p
+
+func fun(x []int) {}
+
+func g(x []int) {
+	Fun(x)    // -r='fun(x)->Fun(x)' should rewrite this to Fun(x)
+	fun(x...) // -r='fun(x)->Fun(x)' should not rewrite this
+}
diff --git a/src/cmd/gofmt/testdata/rewrite6.input b/src/cmd/gofmt/testdata/rewrite6.input
new file mode 100644
index 0000000..8c088b3
--- /dev/null
+++ b/src/cmd/gofmt/testdata/rewrite6.input
@@ -0,0 +1,15 @@
+// Copyright 2013 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.
+
+// Rewriting of calls must take the ... (ellipsis)
+// attribute for the last argument into account.
+
+package p
+
+func fun(x []int) {}
+
+func g(x []int) {
+	fun(x)    // -r='fun(x)->Fun(x)' should rewrite this to Fun(x)
+	fun(x...) // -r='fun(x)->Fun(x)' should not rewrite this
+}
diff --git a/src/cmd/gofmt/testdata/rewrite7.golden b/src/cmd/gofmt/testdata/rewrite7.golden
new file mode 100644
index 0000000..29babad
--- /dev/null
+++ b/src/cmd/gofmt/testdata/rewrite7.golden
@@ -0,0 +1,15 @@
+// Copyright 2013 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.
+
+// Rewriting of calls must take the ... (ellipsis)
+// attribute for the last argument into account.
+
+package p
+
+func fun(x []int) {}
+
+func g(x []int) {
+	fun(x) // -r='fun(x...)->Fun(x)' should not rewrite this
+	Fun(x) // -r='fun(x...)->Fun(x)' should rewrite this to Fun(x)
+}
diff --git a/src/cmd/gofmt/testdata/rewrite7.input b/src/cmd/gofmt/testdata/rewrite7.input
new file mode 100644
index 0000000..073e2a3
--- /dev/null
+++ b/src/cmd/gofmt/testdata/rewrite7.input
@@ -0,0 +1,15 @@
+// Copyright 2013 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.
+
+// Rewriting of calls must take the ... (ellipsis)
+// attribute for the last argument into account.
+
+package p
+
+func fun(x []int) {}
+
+func g(x []int) {
+	fun(x)    // -r='fun(x...)->Fun(x)' should not rewrite this
+	fun(x...) // -r='fun(x...)->Fun(x)' should rewrite this to Fun(x)
+}
diff --git a/src/cmd/gofmt/testdata/rewrite8.golden b/src/cmd/gofmt/testdata/rewrite8.golden
new file mode 100644
index 0000000..cfc452b
--- /dev/null
+++ b/src/cmd/gofmt/testdata/rewrite8.golden
@@ -0,0 +1,10 @@
+// Copyright 2013 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.
+
+// Check that literal type expression rewrites are accepted.
+// Was issue 4406.
+
+package p
+
+type T int
diff --git a/src/cmd/gofmt/testdata/rewrite8.input b/src/cmd/gofmt/testdata/rewrite8.input
new file mode 100644
index 0000000..235efa9
--- /dev/null
+++ b/src/cmd/gofmt/testdata/rewrite8.input
@@ -0,0 +1,10 @@
+// Copyright 2013 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.
+
+// Check that literal type expression rewrites are accepted.
+// Was issue 4406.
+
+package p
+
+type T interface{}
diff --git a/src/cmd/ld/data.c b/src/cmd/ld/data.c
index b70d463..fa34aa3 100644
--- a/src/cmd/ld/data.c
+++ b/src/cmd/ld/data.c
@@ -172,7 +172,7 @@ relocsym(Sym *s)
 		if(r->sym != S && r->sym->type == SDYNIMPORT)
 			diag("unhandled relocation for %s (type %d rtype %d)", r->sym->name, r->sym->type, r->type);
 
-		if(r->sym != S && !r->sym->reachable)
+		if(r->sym != S && r->sym->type != STLSBSS && !r->sym->reachable)
 			diag("unreachable sym in relocation: %s %s", s->name, r->sym->name);
 
 		switch(r->type) {
@@ -181,6 +181,10 @@ relocsym(Sym *s)
 			if(linkmode == LinkExternal || archreloc(r, s, &o) < 0)
 				diag("unknown reloc %d", r->type);
 			break;
+		case D_TLS:
+			r->done = 0;
+			o = 0;
+			break;
 		case D_ADDR:
 			if(linkmode == LinkExternal && r->sym->type != SCONST) {
 				r->done = 0;
@@ -646,7 +650,7 @@ datblk(int32 addr, int32 size)
 					break;
 				}
 				Bprint(&bso, "\treloc %.8ux/%d %s %s+%#llx [%#llx]\n",
-					(uint)(sym->value+r->off), r->siz, typ, rsname, r->add, r->sym->value+r->add);
+					(uint)(sym->value+r->off), r->siz, typ, rsname, (vlong)r->add, (vlong)(r->sym->value+r->add));
 			}
 		}				
 	}
@@ -1193,11 +1197,7 @@ dodata(void)
 	sect->vaddr = datsize;
 	lookup("noptrbss", 0)->sect = sect;
 	lookup("enoptrbss", 0)->sect = sect;
-	for(; s != nil; s = s->next) {
-		if(s->type > SNOPTRBSS) {
-			cursym = s;
-			diag("unexpected symbol type %d", s->type);
-		}
+	for(; s != nil && s->type == SNOPTRBSS; s = s->next) {
 		datsize = aligndatsize(datsize, s);
 		s->sect = sect;
 		s->value = datsize;
@@ -1205,10 +1205,28 @@ dodata(void)
 	}
 	sect->len = datsize - sect->vaddr;
 	lookup("end", 0)->sect = sect;
+	
+	if(iself && linkmode == LinkExternal && s != nil && s->type == STLSBSS && HEADTYPE != Hopenbsd) {
+		sect = addsection(&segdata, ".tbss", 06);
+		sect->align = PtrSize;
+		sect->vaddr = 0;
+		datsize = 0;
+		for(; s != nil && s->type == STLSBSS; s = s->next) {
+			datsize = aligndatsize(datsize, s);
+			s->sect = sect;
+			s->value = datsize;
+			datsize += s->size;
+		}
+		sect->len = datsize;
+	}
+	
+	if(s != nil) {
+		cursym = nil;
+		diag("unexpected symbol type %d for %s", s->type, s->name);
+	}
 
 	/* we finished segdata, begin segtext */
 	s = datap;
-	datsize = 0;
 
 	/* read-only data */
 	sect = addsection(&segtext, ".rodata", 04);
diff --git a/src/cmd/ld/doc.go b/src/cmd/ld/doc.go
index bad4e54..874db41 100644
--- a/src/cmd/ld/doc.go
+++ b/src/cmd/ld/doc.go
@@ -71,5 +71,22 @@ Options new in this version:
 		NOTE: it only eliminates false positives caused by other function
 		calls, not false positives caused by dead temporaries stored in
 		the current function call.
+	-linkmode argument
+		Set the linkmode.  The argument must be one of
+		internal, external, or auto.  The default is auto.
+		This sets the linking mode as described in
+		../cgo/doc.go.
+	-tmpdir dir
+		Set the location to use for any temporary files.  The
+		default is a newly created directory that is removed
+		after the linker completes.  Temporary files are only
+		used in external linking mode.
+	-extld name
+		Set the name of the external linker to use in external
+		linking mode.  The default is "gcc".
+	-extldflags flags
+		Set space-separated trailing flags to pass to the
+		external linker in external linking mode.  The default
+		is to not pass any additional trailing flags.
 */
 package main
diff --git a/src/cmd/ld/dwarf.c b/src/cmd/ld/dwarf.c
index 4bf788e..436e1e6 100644
--- a/src/cmd/ld/dwarf.c
+++ b/src/cmd/ld/dwarf.c
@@ -1130,14 +1130,24 @@ mkinternaltypename(char *base, char *arg1, char *arg2)
 	return n;
 }
 
+// synthesizemaptypes is way too closely married to runtime/hashmap.c
+enum {
+	MaxKeySize = 128,
+	MaxValSize = 128,
+	BucketSize = 8,
+};
 
 static void
 synthesizemaptypes(DWDie *die)
 {
 
-	DWDie *hash, *dwh, *keytype, *valtype;
+	DWDie *hash, *bucket, *dwh, *dwhk, *dwhv, *dwhb, *keytype, *valtype, *fld;
+	int indirect_key, indirect_val;
+	int keysize, valsize;
+	DWAttr *a;
 
-	hash		= defgotype(lookup_or_diag("type.runtime.hmap"));
+	hash		= walktypedef(defgotype(lookup_or_diag("type.runtime.hmap")));
+	bucket		= walktypedef(defgotype(lookup_or_diag("type.runtime.bucket")));
 
 	if (hash == nil)
 		return;
@@ -1146,8 +1156,59 @@ synthesizemaptypes(DWDie *die)
 		if (die->abbrev != DW_ABRV_MAPTYPE)
 			continue;
 
-		keytype = (DWDie*) getattr(die, DW_AT_internal_key_type)->data;
-		valtype = (DWDie*) getattr(die, DW_AT_internal_val_type)->data;
+		keytype = walktypedef((DWDie*) getattr(die, DW_AT_internal_key_type)->data);
+		valtype = walktypedef((DWDie*) getattr(die, DW_AT_internal_val_type)->data);
+
+		// compute size info like hashmap.c does.
+		a = getattr(keytype, DW_AT_byte_size);
+		keysize = a ? a->value : PtrSize;  // We don't store size with Pointers
+		a = getattr(valtype, DW_AT_byte_size);
+		valsize = a ? a->value : PtrSize;
+		indirect_key = 0;
+		indirect_val = 0;
+		if(keysize > MaxKeySize) {
+			keysize = PtrSize;
+			indirect_key = 1;
+		}
+		if(valsize > MaxValSize) {
+			valsize = PtrSize;
+			indirect_val = 1;
+		}
+
+		// Construct type to represent an array of BucketSize keys
+		dwhk = newdie(&dwtypes, DW_ABRV_ARRAYTYPE,
+			      mkinternaltypename("[]key",
+						 getattr(keytype, DW_AT_name)->data, nil));
+		newattr(dwhk, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize * keysize, 0);
+		newrefattr(dwhk, DW_AT_type, indirect_key ? defptrto(keytype) : keytype);
+		fld = newdie(dwhk, DW_ABRV_ARRAYRANGE, "size");
+		newattr(fld, DW_AT_upper_bound, DW_CLS_CONSTANT, BucketSize, 0);
+		newrefattr(fld, DW_AT_type, find_or_diag(&dwtypes, "uintptr"));
+		
+		// Construct type to represent an array of BucketSize values
+		dwhv = newdie(&dwtypes, DW_ABRV_ARRAYTYPE, 
+			      mkinternaltypename("[]val",
+						 getattr(valtype, DW_AT_name)->data, nil));
+		newattr(dwhv, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize * valsize, 0);
+		newrefattr(dwhv, DW_AT_type, indirect_val ? defptrto(valtype) : valtype);
+		fld = newdie(dwhv, DW_ABRV_ARRAYRANGE, "size");
+		newattr(fld, DW_AT_upper_bound, DW_CLS_CONSTANT, BucketSize, 0);
+		newrefattr(fld, DW_AT_type, find_or_diag(&dwtypes, "uintptr"));
+
+		// Construct bucket<K,V>
+		dwhb = newdie(&dwtypes, DW_ABRV_STRUCTTYPE,
+			      mkinternaltypename("bucket",
+						 getattr(keytype, DW_AT_name)->data,
+						 getattr(valtype, DW_AT_name)->data));
+		copychildren(dwhb, bucket);
+		fld = newdie(dwhb, DW_ABRV_STRUCTFIELD, "keys");
+		newrefattr(fld, DW_AT_type, dwhk);
+		newmemberoffsetattr(fld, BucketSize + PtrSize);
+		fld = newdie(dwhb, DW_ABRV_STRUCTFIELD, "values");
+		newrefattr(fld, DW_AT_type, dwhv);
+		newmemberoffsetattr(fld, BucketSize + PtrSize + BucketSize * keysize);
+		newattr(dwhb, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize + PtrSize + BucketSize * keysize + BucketSize * valsize, 0);
+		substitutetype(dwhb, "overflow", defptrto(dwhb));
 
 		// Construct hash<K,V>
 		dwh = newdie(&dwtypes, DW_ABRV_STRUCTTYPE,
@@ -1155,9 +1216,12 @@ synthesizemaptypes(DWDie *die)
 				getattr(keytype, DW_AT_name)->data,
 				getattr(valtype, DW_AT_name)->data));
 		copychildren(dwh, hash);
+		substitutetype(dwh, "buckets", defptrto(dwhb));
+		substitutetype(dwh, "oldbuckets", defptrto(dwhb));
 		newattr(dwh, DW_AT_byte_size, DW_CLS_CONSTANT,
 			getattr(hash, DW_AT_byte_size)->value, nil);
 
+		// make map type a pointer to hash<K,V>
 		newrefattr(die, DW_AT_type, defptrto(dwh));
 	}
 }
diff --git a/src/cmd/ld/elf.c b/src/cmd/ld/elf.c
index f5cce9c..22bc64f 100644
--- a/src/cmd/ld/elf.c
+++ b/src/cmd/ld/elf.c
@@ -758,6 +758,10 @@ elfshbits(Section *sect)
 		sh->flags |= SHF_EXECINSTR;
 	if(sect->rwx & 2)
 		sh->flags |= SHF_WRITE;
+	if(strcmp(sect->name, ".tbss") == 0) {
+		sh->flags |= SHF_TLS;
+		sh->type = SHT_NOBITS;
+	}
 	if(linkmode != LinkExternal)
 		sh->addr = sect->vaddr;
 	sh->addralign = sect->align;
@@ -779,7 +783,7 @@ elfshreloc(Section *sect)
 	// Also nothing to relocate in .shstrtab.
 	if(sect->vaddr >= sect->seg->vaddr + sect->seg->filelen)
 		return nil;
-	if(strcmp(sect->name, ".shstrtab") == 0)
+	if(strcmp(sect->name, ".shstrtab") == 0 || strcmp(sect->name, ".tbss") == 0)
 		return nil;
 
 	if(thechar == '6') {
@@ -883,6 +887,8 @@ doelf(void)
 	addstring(shstrtab, ".data");
 	addstring(shstrtab, ".bss");
 	addstring(shstrtab, ".noptrbss");
+	if(linkmode == LinkExternal && HEADTYPE != Hopenbsd)
+		addstring(shstrtab, ".tbss");
 	if(HEADTYPE == Hnetbsd)
 		addstring(shstrtab, ".note.netbsd.ident");
 	if(HEADTYPE == Hopenbsd)
diff --git a/src/cmd/ld/go.c b/src/cmd/ld/go.c
index f933cbb..fa2ec4e 100644
--- a/src/cmd/ld/go.c
+++ b/src/cmd/ld/go.c
@@ -508,10 +508,6 @@ loadcgo(char *file, char *pkg, char *p, int n)
 			}
 
 			if(s->cgoexport == 0) {
-				if(strcmp(f[0], "cgo_export_static") == 0)
-					s->cgoexport |= CgoExportStatic;
-				else
-					s->cgoexport |= CgoExportDynamic;
 				s->extname = remote;
 				if(ndynexp%32 == 0)
 					dynexp = erealloc(dynexp, (ndynexp+32)*sizeof dynexp[0]);
@@ -521,6 +517,10 @@ loadcgo(char *file, char *pkg, char *p, int n)
 				nerrors++;
 				return;
 			}
+			if(strcmp(f[0], "cgo_export_static") == 0)
+				s->cgoexport |= CgoExportStatic;
+			else
+				s->cgoexport |= CgoExportDynamic;
 			if(local != f[1])
 				free(local);
 			continue;
diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c
index 18cae31..84777b1 100644
--- a/src/cmd/ld/lib.c
+++ b/src/cmd/ld/lib.c
@@ -31,6 +31,7 @@
 
 #include	"l.h"
 #include	"lib.h"
+#include	"../ld/elf.h"
 #include	"../../pkg/runtime/stack.h"
 
 #include	<ar.h>
@@ -608,7 +609,7 @@ void
 hostlink(void)
 {
 	char *p, **argv;
-	int i, w, n, argc, len;
+	int c, i, w, n, argc, len;
 	Hostobj *h;
 	Biobuf *f;
 	static char buf[64<<10];
@@ -616,11 +617,22 @@ hostlink(void)
 	if(linkmode != LinkExternal || nerrors > 0)
 		return;
 
-	argv = malloc((10+nhostobj+nldflag)*sizeof argv[0]);
+	c = 0;
+	p = extldflags;
+	while(p != nil) {
+		while(*p == ' ')
+			p++;
+		if(*p == '\0')
+			break;
+		c++;
+		p = strchr(p + 1, ' ');
+	}
+
+	argv = malloc((10+nhostobj+nldflag+c)*sizeof argv[0]);
 	argc = 0;
-	// TODO: Add command-line flag to override gcc path and specify additional leading options.
-	// TODO: Add command-line flag to specify additional trailing options.
-	argv[argc++] = "gcc";
+	if(extld == nil)
+		extld = "gcc";
+	argv[argc++] = extld;
 	switch(thechar){
 	case '8':
 		argv[argc++] = "-m32";
@@ -636,9 +648,12 @@ hostlink(void)
 	argv[argc++] = "-o";
 	argv[argc++] = outfile;
 	
+	if(rpath)
+		argv[argc++] = smprint("-Wl,-rpath,%s", rpath);
+
 	// Force global symbols to be exported for dlopen, etc.
-	// NOTE: May not work on OS X or Windows. We'll see.
-	argv[argc++] = "-rdynamic";
+	if(iself)
+		argv[argc++] = "-rdynamic";
 
 	// already wrote main object file
 	// copy host objects to temporary directory
@@ -675,6 +690,17 @@ hostlink(void)
 	argv[argc++] = smprint("%s/go.o", tmpdir);
 	for(i=0; i<nldflag; i++)
 		argv[argc++] = ldflag[i];
+
+	p = extldflags;
+	while(p != nil) {
+		while(*p == ' ')
+			*p++ = '\0';
+		if(*p == '\0')
+			break;
+		argv[argc++] = p;
+		p = strchr(p + 1, ' ');
+	}
+
 	argv[argc] = nil;
 
 	quotefmtinstall();
@@ -846,17 +872,16 @@ _lookup(char *symb, int v, int creat)
 	Sym *s;
 	char *p;
 	int32 h;
-	int l, c;
+	int c;
 
 	h = v;
 	for(p=symb; c = *p; p++)
 		h = h+h+h + c;
-	l = (p - symb) + 1;
 	// not if(h < 0) h = ~h, because gcc 4.3 -O2 miscompiles it.
 	h &= 0xffffff;
 	h %= NHASH;
 	for(s = hash[h]; s != S; s = s->hash)
-		if(memcmp(s->name, symb, l) == 0)
+		if(strcmp(s->name, symb) == 0)
 			return s;
 	if(!creat)
 		return nil;
@@ -1860,7 +1885,10 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
 		/* frame, locals, args, auto and param after */
 		put(nil, ".frame", 'm', (uint32)s->text->to.offset+PtrSize, 0, 0, 0);
 		put(nil, ".locals", 'm', s->locals, 0, 0, 0);
-		put(nil, ".args", 'm', s->args, 0, 0, 0);
+		if(s->text->textflag & NOSPLIT)
+			put(nil, ".args", 'm', ArgsSizeUnknown, 0, 0, 0);
+		else
+			put(nil, ".args", 'm', s->args, 0, 0, 0);
 
 		for(a=s->autom; a; a=a->link) {
 			// Emit a or p according to actual offset, even if label is wrong.
diff --git a/src/cmd/ld/lib.h b/src/cmd/ld/lib.h
index a5ca7d3..9bdfe95 100644
--- a/src/cmd/ld/lib.h
+++ b/src/cmd/ld/lib.h
@@ -52,6 +52,7 @@ enum
 	SWINDOWS,
 	SBSS,
 	SNOPTRBSS,
+	STLSBSS,
 
 	SXREF,
 	SMACHOSYMSTR,
@@ -70,6 +71,13 @@ enum
 	NHASH = 100003,
 };
 
+enum
+{
+	// This value is known to the garbage collector and should be kept in
+	// sync with runtime/pkg/runtime.h
+	ArgsSizeUnknown = 0x80000000
+};
+
 typedef struct Library Library;
 struct Library
 {
@@ -149,6 +157,8 @@ EXTERN	int flag_shared;
 EXTERN	char*	tracksym;
 EXTERN	char*	interpreter;
 EXTERN	char*	tmpdir;
+EXTERN	char*	extld;
+EXTERN	char*	extldflags;
 
 enum
 {
diff --git a/src/cmd/ld/symtab.c b/src/cmd/ld/symtab.c
index 698194f..d8a4645 100644
--- a/src/cmd/ld/symtab.c
+++ b/src/cmd/ld/symtab.c
@@ -152,6 +152,26 @@ asmelfsym(void)
 
 	elfbind = STB_LOCAL;
 	genasmsym(putelfsym);
+	
+	if(linkmode == LinkExternal && HEADTYPE != Hopenbsd) {
+		s = lookup("runtime.m", 0);
+		if(s->sect == nil) {
+			cursym = nil;
+			diag("missing section for %s", s->name);
+			errorexit();
+		}
+		putelfsyment(putelfstr(s->name), 0, PtrSize, (STB_LOCAL<<4)|STT_TLS, s->sect->elfsect->shnum, 0);
+		s->elfsym = numelfsym++;
+
+		s = lookup("runtime.g", 0);
+		if(s->sect == nil) {
+			cursym = nil;
+			diag("missing section for %s", s->name);
+			errorexit();
+		}
+		putelfsyment(putelfstr(s->name), PtrSize, PtrSize, (STB_LOCAL<<4)|STT_TLS, s->sect->elfsect->shnum, 0);
+		s->elfsym = numelfsym++;
+	}
 
 	elfbind = STB_GLOBAL;
 	elfglobalsymndx = numelfsym;
diff --git a/src/cmd/nm/nm.c b/src/cmd/nm/nm.c
index 6682390..aa056b8 100644
--- a/src/cmd/nm/nm.c
+++ b/src/cmd/nm/nm.c
@@ -275,11 +275,13 @@ psym(Sym *s, void* p)
 			return;
 		break;
 	case 'm':
+		if(!aflag || uflag || gflag)
+			return;
+		break;
 	case 'f':	/* we only see a 'z' when the following is true*/
 		if(!aflag || uflag || gflag)
 			return;
-		if (strcmp(s->name, ".frame"))
-			zenter(s);
+		zenter(s);
 		break;
 	case 'a':
 	case 'p':
diff --git a/src/cmd/vet/asmdecl.go b/src/cmd/vet/asmdecl.go
index 2cfaa93..c23514c 100644
--- a/src/cmd/vet/asmdecl.go
+++ b/src/cmd/vet/asmdecl.go
@@ -104,6 +104,7 @@ func asmCheck(pkg *Package) {
 		if !strings.HasSuffix(f.name, ".s") {
 			continue
 		}
+		Println("Checking file", f.name)
 
 		// Determine architecture from file name if possible.
 		var arch string
diff --git a/src/cmd/vet/test_asm1.s b/src/cmd/vet/test_asm1.s
index 2fe3196..8cd9eea 100644
--- a/src/cmd/vet/test_asm1.s
+++ b/src/cmd/vet/test_asm1.s
@@ -3,9 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // +build amd64
-// +build ignore
-
-package main
+// +build vet_test
 
 TEXT ·arg1(SB),0,$0-2
 	MOVB	x+0(FP), AX
diff --git a/src/cmd/vet/test_asm2.s b/src/cmd/vet/test_asm2.s
index 73a4ad4..d8679c5 100644
--- a/src/cmd/vet/test_asm2.s
+++ b/src/cmd/vet/test_asm2.s
@@ -3,9 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // +build 386
-// +build ignore
-
-package main
+// +build vet_test
 
 TEXT ·arg1(SB),0,$0-2
 	MOVB	x+0(FP), AX
diff --git a/src/cmd/vet/test_asm3.s b/src/cmd/vet/test_asm3.s
index 2c1a54f..bf98805 100644
--- a/src/cmd/vet/test_asm3.s
+++ b/src/cmd/vet/test_asm3.s
@@ -3,9 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // +build arm
-// +build ignore
-
-package main
+// +build vet_test
 
 TEXT ·arg1(SB),0,$0-2
 	MOVB	x+0(FP), AX
diff --git a/src/cmd/vet/test_deadcode.go b/src/cmd/vet/test_deadcode.go
index 3ded80c..d08e577 100644
--- a/src/cmd/vet/test_deadcode.go
+++ b/src/cmd/vet/test_deadcode.go
@@ -112,31 +112,31 @@ func _() int {
 func _() int {
 	print(1)
 	return 2
-	{
-	} // ERROR "unreachable code"
+	{ // ERROR "unreachable code"
+	}
 }
 
 func _() int {
 L:
 	print(1)
 	goto L
-	{
-	} // ERROR "unreachable code"
+	{ // ERROR "unreachable code"
+	}
 }
 
 func _() int {
 	print(1)
 	panic(2)
-	{
-	} // ERROR "unreachable code"
+	{ // ERROR "unreachable code"
+	}
 }
 
 func _() int {
 	{
 		print(1)
 		return 2
-		{
-		} // ERROR "unreachable code"
+		{ // ERROR "unreachable code"
+		}
 	}
 }
 
@@ -145,8 +145,8 @@ L:
 	{
 		print(1)
 		goto L
-		{
-		} // ERROR "unreachable code"
+		{ // ERROR "unreachable code"
+		}
 	}
 }
 
@@ -154,8 +154,8 @@ func _() int {
 	print(1)
 	{
 		panic(2)
-		{
-		} // ERROR "unreachable code"
+		{ // ERROR "unreachable code"
+		}
 	}
 }
 
@@ -164,8 +164,8 @@ func _() int {
 		print(1)
 		return 2
 	}
-	{
-	} // ERROR "unreachable code"
+	{ // ERROR "unreachable code"
+	}
 }
 
 func _() int {
@@ -174,8 +174,8 @@ L:
 		print(1)
 		goto L
 	}
-	{
-	} // ERROR "unreachable code"
+	{ // ERROR "unreachable code"
+	}
 }
 
 func _() int {
@@ -183,8 +183,8 @@ func _() int {
 	{
 		panic(2)
 	}
-	{
-	} // ERROR "unreachable code"
+	{ // ERROR "unreachable code"
+	}
 }
 
 func _() int {
@@ -991,31 +991,31 @@ func _() int {
 
 func _() int {
 	return 2
-	{
-	} // ERROR "unreachable code"
+	{ // ERROR "unreachable code"
+	}
 	println() // ok
 }
 
 func _() int {
 L:
 	goto L
-	{
-	} // ERROR "unreachable code"
+	{ // ERROR "unreachable code"
+	}
 	println() // ok
 }
 
 func _() int {
 	panic(2)
-	{
-	} // ERROR "unreachable code"
+	{ // ERROR "unreachable code"
+	}
 	println() // ok
 }
 
 func _() int {
 	{
 		return 2
-		{
-		} // ERROR "unreachable code"
+		{ // ERROR "unreachable code"
+		}
 	}
 	println() // ok
 }
@@ -1024,8 +1024,8 @@ func _() int {
 L:
 	{
 		goto L
-		{
-		} // ERROR "unreachable code"
+		{ // ERROR "unreachable code"
+		}
 	}
 	println() // ok
 }
@@ -1033,8 +1033,8 @@ L:
 func _() int {
 	{
 		panic(2)
-		{
-		} // ERROR "unreachable code"
+		{ // ERROR "unreachable code"
+		}
 	}
 	println() // ok
 }
@@ -1043,8 +1043,8 @@ func _() int {
 	{
 		return 2
 	}
-	{
-	} // ERROR "unreachable code"
+	{ // ERROR "unreachable code"
+	}
 	println() // ok
 }
 
@@ -1053,8 +1053,8 @@ L:
 	{
 		goto L
 	}
-	{
-	} // ERROR "unreachable code"
+	{ // ERROR "unreachable code"
+	}
 	println() // ok
 }
 
@@ -1062,8 +1062,8 @@ func _() int {
 	{
 		panic(2)
 	}
-	{
-	} // ERROR "unreachable code"
+	{ // ERROR "unreachable code"
+	}
 	println() // ok
 }
 
@@ -1165,31 +1165,31 @@ var _ = func() int {
 var _ = func() int {
 	print(1)
 	return 2
-	{
-	} // ERROR "unreachable code"
+	{ // ERROR "unreachable code"
+	}
 }
 
 var _ = func() int {
 L:
 	print(1)
 	goto L
-	{
-	} // ERROR "unreachable code"
+	{ // ERROR "unreachable code"
+	}
 }
 
 var _ = func() int {
 	print(1)
 	panic(2)
-	{
-	} // ERROR "unreachable code"
+	{ // ERROR "unreachable code"
+	}
 }
 
 var _ = func() int {
 	{
 		print(1)
 		return 2
-		{
-		} // ERROR "unreachable code"
+		{ // ERROR "unreachable code"
+		}
 	}
 }
 
@@ -1198,8 +1198,8 @@ L:
 	{
 		print(1)
 		goto L
-		{
-		} // ERROR "unreachable code"
+		{ // ERROR "unreachable code"
+		}
 	}
 }
 
@@ -1207,8 +1207,8 @@ var _ = func() int {
 	print(1)
 	{
 		panic(2)
-		{
-		} // ERROR "unreachable code"
+		{ // ERROR "unreachable code"
+		}
 	}
 }
 
@@ -1217,8 +1217,8 @@ var _ = func() int {
 		print(1)
 		return 2
 	}
-	{
-	} // ERROR "unreachable code"
+	{ // ERROR "unreachable code"
+	}
 }
 
 var _ = func() int {
@@ -1227,8 +1227,8 @@ L:
 		print(1)
 		goto L
 	}
-	{
-	} // ERROR "unreachable code"
+	{ // ERROR "unreachable code"
+	}
 }
 
 var _ = func() int {
@@ -1236,8 +1236,8 @@ var _ = func() int {
 	{
 		panic(2)
 	}
-	{
-	} // ERROR "unreachable code"
+	{ // ERROR "unreachable code"
+	}
 }
 
 var _ = func() int {
@@ -2044,31 +2044,31 @@ var _ = func() int {
 
 var _ = func() int {
 	return 2
-	{
-	} // ERROR "unreachable code"
+	{ // ERROR "unreachable code"
+	}
 	println() // ok
 }
 
 var _ = func() int {
 L:
 	goto L
-	{
-	} // ERROR "unreachable code"
+	{ // ERROR "unreachable code"
+	}
 	println() // ok
 }
 
 var _ = func() int {
 	panic(2)
-	{
-	} // ERROR "unreachable code"
+	{ // ERROR "unreachable code"
+	}
 	println() // ok
 }
 
 var _ = func() int {
 	{
 		return 2
-		{
-		} // ERROR "unreachable code"
+		{ // ERROR "unreachable code"
+		}
 	}
 	println() // ok
 }
@@ -2077,8 +2077,8 @@ var _ = func() int {
 L:
 	{
 		goto L
-		{
-		} // ERROR "unreachable code"
+		{ // ERROR "unreachable code"
+		}
 	}
 	println() // ok
 }
@@ -2086,8 +2086,8 @@ L:
 var _ = func() int {
 	{
 		panic(2)
-		{
-		} // ERROR "unreachable code"
+		{ // ERROR "unreachable code"
+		}
 	}
 	println() // ok
 }
@@ -2096,8 +2096,8 @@ var _ = func() int {
 	{
 		return 2
 	}
-	{
-	} // ERROR "unreachable code"
+	{ // ERROR "unreachable code"
+	}
 	println() // ok
 }
 
@@ -2106,8 +2106,8 @@ L:
 	{
 		goto L
 	}
-	{
-	} // ERROR "unreachable code"
+	{ // ERROR "unreachable code"
+	}
 	println() // ok
 }
 
@@ -2115,7 +2115,7 @@ var _ = func() int {
 	{
 		panic(2)
 	}
-	{
-	} // ERROR "unreachable code"
+	{ // ERROR "unreachable code"
+	}
 	println() // ok
 }
diff --git a/src/lib9/goos.c b/src/lib9/goos.c
index 3b00271..2d4a800 100644
--- a/src/lib9/goos.c
+++ b/src/lib9/goos.c
@@ -51,3 +51,9 @@ getgo386(void)
 {
 	return defgetenv("GO386", GO386);
 }
+
+char *
+getgoextlinkenabled(void)
+{
+	return GO_EXTLINK_ENABLED;
+}
diff --git a/src/lib9/utf/utf.h b/src/lib9/utf/utf.h
index 8a79828..72d01ed 100644
--- a/src/lib9/utf/utf.h
+++ b/src/lib9/utf/utf.h
@@ -16,8 +16,6 @@
 #ifndef _UTFH_
 #define _UTFH_ 1
 
-#include <stdint.h>
-
 typedef unsigned int Rune;	/* Code-point values in Unicode 4.0 are 21 bits wide.*/
 
 enum
diff --git a/src/libmach/sym.c b/src/libmach/sym.c
index 120328d..28c80d6 100644
--- a/src/libmach/sym.c
+++ b/src/libmach/sym.c
@@ -109,7 +109,7 @@ int
 syminit(int fd, Fhdr *fp)
 {
 	Sym *p;
-	int32 i, l, size;
+	int32 i, l, size, symsz;
 	vlong vl;
 	Biobuf b;
 	int svalsz, newformat, shift;
@@ -138,6 +138,7 @@ syminit(int fd, Fhdr *fp)
 	memset(buf, 0, sizeof buf);
 	Bread(&b, buf, sizeof buf);
 	newformat = 0;
+	symsz = fp->symsz;
 	if(memcmp(buf, "\xfd\xff\xff\xff\x00\x00\x00", 7) == 0) {
 		swav = leswav;
 		swal = leswal;
@@ -151,6 +152,7 @@ syminit(int fd, Fhdr *fp)
 		swav = leswav;
 		swal = leswal;
 		Bseek(&b, fp->symoff+6, 0);
+		symsz -= 6;
 	} else {
 		Bseek(&b, fp->symoff, 0);
 	}
@@ -161,11 +163,12 @@ syminit(int fd, Fhdr *fp)
 			werrstr("invalid word size %d bytes", svalsz);
 			return -1;
 		}
+		symsz -= 8;
 	}
 
 	nsym = 0;
 	size = 0;
-	for(p = symbols; size < fp->symsz; p++, nsym++) {
+	for(p = symbols; size < symsz; p++, nsym++) {
 		if(newformat) {
 			// Go 1.1 format. See comment at top of ../pkg/runtime/symtab.c.
 			if(Bread(&b, &c, 1) != 1)
diff --git a/src/make.bash b/src/make.bash
index 2d83b6f..8d0f6eb 100755
--- a/src/make.bash
+++ b/src/make.bash
@@ -30,6 +30,11 @@
 # to include all cgo related files, .c and .go file with "cgo"
 # build directive, in the build. Set it to 0 to ignore them.
 #
+# GO_EXTLINK_ENABLED: Set to 1 to invoke the host linker when building
+# packages that use cgo.  Set to 0 to do all linking internally.  This
+# controls the default behavior of the linker's -linkmode option.  The
+# default value depends on the system.
+#
 # CC: Command line to run to get at host C compiler.
 # Default is "gcc". Also supported: "clang".
 
diff --git a/src/make.bat b/src/make.bat
index be1c8f5..c1f171d 100644
--- a/src/make.bat
+++ b/src/make.bat
@@ -109,8 +109,8 @@ if x%1==x--no-banner goto nobanner
 goto end
 
 :copydist
-mkdir %GOTOOLDIR% 2>NUL
-copy cmd\dist\dist.exe %GOTOOLDIR%\
+mkdir "%GOTOOLDIR%" 2>NUL
+copy cmd\dist\dist.exe "%GOTOOLDIR%\"
 goto end
 
 :fail
diff --git a/src/pkg/bufio/scan.go b/src/pkg/bufio/scan.go
index d94f7f9..486853e 100644
--- a/src/pkg/bufio/scan.go
+++ b/src/pkg/bufio/scan.go
@@ -16,7 +16,7 @@ import (
 // the Scan method will step through the 'tokens' of a file, skipping
 // the bytes between the tokens. The specification of a token is
 // defined by a split function of type SplitFunc; the default split
-// function breaks the input into lines with newlines stripped. Split
+// function breaks the input into lines with line termination stripped. Split
 // functions are defined in this package for scanning a file into
 // lines, bytes, UTF-8-encoded runes, and space-delimited words. The
 // client may instead provide a custom split function.
@@ -70,6 +70,7 @@ const (
 )
 
 // NewScanner returns a new Scanner to read from r.
+// The split function defaults to ScanLines.
 func NewScanner(r io.Reader) *Scanner {
 	return &Scanner{
 		r:            r,
@@ -257,7 +258,7 @@ func dropCR(data []byte) []byte {
 // ScanLines is a split function for a Scanner that returns each line of
 // text, stripped of any trailing end-of-line marker. The returned line may
 // be empty. The end-of-line marker is one optional carriage return followed
-// by one mandatory newline. In regular expression notation, it is `\r?\n'.
+// by one mandatory newline. In regular expression notation, it is `\r?\n`.
 // The last non-empty line of input will be returned even if it has no
 // newline.
 func ScanLines(data []byte, atEOF bool) (advance int, token []byte, err error) {
diff --git a/src/pkg/builtin/builtin.go b/src/pkg/builtin/builtin.go
index 7b5e9ab..d3c1a5c 100644
--- a/src/pkg/builtin/builtin.go
+++ b/src/pkg/builtin/builtin.go
@@ -85,6 +85,15 @@ type byte byte
 // used, by convention, to distinguish character values from integer values.
 type rune rune
 
+// iota is a predeclared identifier representing the untyped integer ordinal
+// number of the current const specification in a (usually parenthesized)
+// const declaration. It is zero-indexed.
+const iota = 0 // Untyped int.
+
+// nil is a predeclared identifier representing the zero value for a
+// pointer, channel, func, interface, map, or slice type.
+var nil Type // Type must be a pointer, channel, func, interface, map, or slice type
+
 // Type is here for the purposes of documentation only. It is a stand-in
 // for any Go type, but represents the same type for any given function
 // invocation.
diff --git a/src/pkg/bytes/asm_386.s b/src/pkg/bytes/asm_386.s
index 997738f..27cd4e7 100644
--- a/src/pkg/bytes/asm_386.s
+++ b/src/pkg/bytes/asm_386.s
@@ -15,19 +15,3 @@ TEXT ·IndexByte(SB),7,$0
 	SUBL	$1, DI
 	MOVL	DI, ret+16(FP)
 	RET
-
-TEXT ·Equal(SB),7,$0
-	MOVL	a_len+4(FP), BX
-	MOVL	b_len+16(FP), CX
-	MOVL	$0, AX
-	CMPL	BX, CX
-	JNE	eqret
-	MOVL	a+0(FP), SI
-	MOVL	b+12(FP), DI
-	CLD
-	REP; CMPSB
-	JNE eqret
-	MOVL	$1, AX
-eqret:
-	MOVB	AX, ret+24(FP)
-	RET
diff --git a/src/pkg/bytes/asm_amd64.s b/src/pkg/bytes/asm_amd64.s
index b8f9f1b..b84957b 100644
--- a/src/pkg/bytes/asm_amd64.s
+++ b/src/pkg/bytes/asm_amd64.s
@@ -89,20 +89,3 @@ success:
 	SUBL $1, DI
 	MOVQ DI, ret+32(FP)
 	RET
-
-TEXT ·Equal(SB),7,$0
-	MOVQ	a_len+8(FP), BX
-	MOVQ	b_len+32(FP), CX
-	MOVL	$0, AX
-	CMPQ	BX, CX
-	JNE	eqret
-	MOVQ	a+0(FP), SI
-	MOVQ	b+24(FP), DI
-	CLD
-	REP; CMPSB
-	MOVL	$1, DX
-	CMOVLEQ	DX, AX
-eqret:
-	MOVB	AX, ret+48(FP)
-	RET
-
diff --git a/src/pkg/bytes/buffer.go b/src/pkg/bytes/buffer.go
index 85c1577..46ca1d5 100644
--- a/src/pkg/bytes/buffer.go
+++ b/src/pkg/bytes/buffer.go
@@ -87,6 +87,13 @@ func (b *Buffer) grow(n int) int {
 		var buf []byte
 		if b.buf == nil && n <= len(b.bootstrap) {
 			buf = b.bootstrap[0:]
+		} else if m+n <= cap(b.buf)/2 {
+			// We can slide things down instead of allocating a new
+			// slice. We only need m+n <= cap(b.buf) to slide, but
+			// we instead let capacity get twice as large so we
+			// don't spend all our time copying.
+			copy(b.buf[:], b.buf[b.off:])
+			buf = b.buf[:m]
 		} else {
 			// not enough space anywhere
 			buf = makeSlice(2*cap(b.buf) + n)
@@ -112,20 +119,18 @@ func (b *Buffer) Grow(n int) {
 	b.buf = b.buf[0:m]
 }
 
-// Write appends the contents of p to the buffer.  The return
-// value n is the length of p; err is always nil.
-// If the buffer becomes too large, Write will panic with
-// ErrTooLarge.
+// Write appends the contents of p to the buffer, growing the buffer as
+// needed. The return value n is the length of p; err is always nil. If the
+// buffer becomes too large, Write will panic with ErrTooLarge.
 func (b *Buffer) Write(p []byte) (n int, err error) {
 	b.lastRead = opInvalid
 	m := b.grow(len(p))
 	return copy(b.buf[m:], p), nil
 }
 
-// WriteString appends the contents of s to the buffer.  The return
-// value n is the length of s; err is always nil.
-// If the buffer becomes too large, WriteString will panic with
-// ErrTooLarge.
+// WriteString appends the contents of s to the buffer, growing the buffer as
+// needed. The return value n is the length of s; err is always nil. If the
+// buffer becomes too large, WriteString will panic with ErrTooLarge.
 func (b *Buffer) WriteString(s string) (n int, err error) {
 	b.lastRead = opInvalid
 	m := b.grow(len(s))
@@ -138,12 +143,10 @@ func (b *Buffer) WriteString(s string) (n int, err error) {
 // underlying buffer.
 const MinRead = 512
 
-// ReadFrom reads data from r until EOF and appends it to the buffer.
-// The return value n is the number of bytes read.
-// Any error except io.EOF encountered during the read
-// is also returned.
-// If the buffer becomes too large, ReadFrom will panic with
-// ErrTooLarge.
+// ReadFrom reads data from r until EOF and appends it to the buffer, growing
+// the buffer as needed. The return value n is the number of bytes read. Any
+// error except io.EOF encountered during the read is also returned. If the
+// buffer becomes too large, ReadFrom will panic with ErrTooLarge.
 func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error) {
 	b.lastRead = opInvalid
 	// If buffer is empty, reset to recover space.
@@ -188,10 +191,10 @@ func makeSlice(n int) []byte {
 	return make([]byte, n)
 }
 
-// WriteTo writes data to w until the buffer is drained or an error
-// occurs. The return value n is the number of bytes written; it always
-// fits into an int, but it is int64 to match the io.WriterTo interface.
-// Any error encountered during the write is also returned.
+// WriteTo writes data to w until the buffer is drained or an error occurs.
+// The return value n is the number of bytes written; it always fits into an
+// int, but it is int64 to match the io.WriterTo interface. Any error
+// encountered during the write is also returned.
 func (b *Buffer) WriteTo(w io.Writer) (n int64, err error) {
 	b.lastRead = opInvalid
 	if b.off < len(b.buf) {
@@ -216,10 +219,9 @@ func (b *Buffer) WriteTo(w io.Writer) (n int64, err error) {
 	return
 }
 
-// WriteByte appends the byte c to the buffer.
-// The returned error is always nil, but is included
-// to match bufio.Writer's WriteByte.
-// If the buffer becomes too large, WriteByte will panic with
+// WriteByte appends the byte c to the buffer, growing the buffer as needed.
+// The returned error is always nil, but is included to match bufio.Writer's
+// WriteByte. If the buffer becomes too large, WriteByte will panic with
 // ErrTooLarge.
 func (b *Buffer) WriteByte(c byte) error {
 	b.lastRead = opInvalid
@@ -228,12 +230,10 @@ func (b *Buffer) WriteByte(c byte) error {
 	return nil
 }
 
-// WriteRune appends the UTF-8 encoding of Unicode
-// code point r to the buffer, returning its length and
-// an error, which is always nil but is included
-// to match bufio.Writer's WriteRune.
-// If the buffer becomes too large, WriteRune will panic with
-// ErrTooLarge.
+// WriteRune appends the UTF-8 encoding of Unicode code point r to the
+// buffer, returning its length and an error, which is always nil but is
+// included to match bufio.Writer's WriteRune. The buffer is grown as needed;
+// if it becomes too large, WriteRune will panic with ErrTooLarge.
 func (b *Buffer) WriteRune(r rune) (n int, err error) {
 	if r < utf8.RuneSelf {
 		b.WriteByte(byte(r))
diff --git a/src/pkg/bytes/buffer_test.go b/src/pkg/bytes/buffer_test.go
index f9fb262..75145b0 100644
--- a/src/pkg/bytes/buffer_test.go
+++ b/src/pkg/bytes/buffer_test.go
@@ -475,3 +475,53 @@ func TestUnreadByte(t *testing.T) {
 		t.Errorf("ReadByte = %q; want %q", c, 'm')
 	}
 }
+
+// Tests that we occasionally compact. Issue 5154.
+func TestBufferGrowth(t *testing.T) {
+	var b Buffer
+	buf := make([]byte, 1024)
+	b.Write(buf[0:1])
+	var cap0 int
+	for i := 0; i < 5<<10; i++ {
+		b.Write(buf)
+		b.Read(buf)
+		if i == 0 {
+			cap0 = b.Cap()
+		}
+	}
+	cap1 := b.Cap()
+	// (*Buffer).grow allows for 2x capacity slop before sliding,
+	// so set our error threshold at 3x.
+	if cap1 > cap0*3 {
+		t.Errorf("buffer cap = %d; too big (grew from %d)", cap1, cap0)
+	}
+}
+
+// From Issue 5154.
+func BenchmarkBufferNotEmptyWriteRead(b *testing.B) {
+	buf := make([]byte, 1024)
+	for i := 0; i < b.N; i++ {
+		var b Buffer
+		b.Write(buf[0:1])
+		for i := 0; i < 5<<10; i++ {
+			b.Write(buf)
+			b.Read(buf)
+		}
+	}
+}
+
+// Check that we don't compact too often. From Issue 5154.
+func BenchmarkBufferFullSmallReads(b *testing.B) {
+	buf := make([]byte, 1024)
+	for i := 0; i < b.N; i++ {
+		var b Buffer
+		b.Write(buf)
+		for b.Len()+20 < b.Cap() {
+			b.Write(buf[:10])
+		}
+		for i := 0; i < 5<<10; i++ {
+			b.Read(buf[:1])
+			b.Write(buf[:1])
+		}
+	}
+}
diff --git a/src/pkg/bytes/bytes_decl.go b/src/pkg/bytes/bytes_decl.go
index ce78be4..fbf9282 100644
--- a/src/pkg/bytes/bytes_decl.go
+++ b/src/pkg/bytes/bytes_decl.go
@@ -13,4 +13,4 @@ func IndexByte(s []byte, c byte) int // asm_$GOARCH.s
 
 // Equal returns a boolean reporting whether a == b.
 // A nil argument is equivalent to an empty slice.
-func Equal(a, b []byte) bool // asm_$GOARCH.s
+func Equal(a, b []byte) bool // asm_arm.s or ../runtime/asm_{386,amd64}.s
diff --git a/src/pkg/bytes/bytes_test.go b/src/pkg/bytes/bytes_test.go
index 1d6274c..d296224 100644
--- a/src/pkg/bytes/bytes_test.go
+++ b/src/pkg/bytes/bytes_test.go
@@ -61,6 +61,10 @@ var compareTests = []struct {
 	{[]byte("ab"), []byte("x"), -1},
 	{[]byte("x"), []byte("a"), 1},
 	{[]byte("b"), []byte("x"), -1},
+	// test runtime·memeq's chunked implementation
+	{[]byte("abcdefgh"), []byte("abcdefgh"), 0},
+	{[]byte("abcdefghi"), []byte("abcdefghi"), 0},
+	{[]byte("abcdefghi"), []byte("abcdefghj"), -1},
 	// nil tests
 	{nil, nil, 0},
 	{[]byte(""), nil, 0},
@@ -86,6 +90,58 @@ func TestCompare(t *testing.T) {
 	}
 }
 
+func TestEqual(t *testing.T) {
+	var size = 128
+	if testing.Short() {
+		size = 32
+	}
+	a := make([]byte, size)
+	b := make([]byte, size)
+	b_init := make([]byte, size)
+	// randomish but deterministic data
+	for i := 0; i < size; i++ {
+		a[i] = byte(17 * i)
+		b_init[i] = byte(23*i + 100)
+	}
+
+	for len := 0; len <= size; len++ {
+		for x := 0; x <= size-len; x++ {
+			for y := 0; y <= size-len; y++ {
+				copy(b, b_init)
+				copy(b[y:y+len], a[x:x+len])
+				if !Equal(a[x:x+len], b[y:y+len]) || !Equal(b[y:y+len], a[x:x+len]) {
+					t.Errorf("Equal(%d, %d, %d) = false", len, x, y)
+				}
+			}
+		}
+	}
+}
+
+// make sure Equal returns false for minimally different strings.  The data
+// is all zeros except for a single one in one location.
+func TestNotEqual(t *testing.T) {
+	var size = 128
+	if testing.Short() {
+		size = 32
+	}
+	a := make([]byte, size)
+	b := make([]byte, size)
+
+	for len := 0; len <= size; len++ {
+		for x := 0; x <= size-len; x++ {
+			for y := 0; y <= size-len; y++ {
+				for diffpos := x; diffpos < x+len; diffpos++ {
+					a[diffpos] = 1
+					if Equal(a[x:x+len], b[y:y+len]) || Equal(b[y:y+len], a[x:x+len]) {
+						t.Errorf("NotEqual(%d, %d, %d, %d) = true", len, x, y, diffpos)
+					}
+					a[diffpos] = 0
+				}
+			}
+		}
+	}
+}
+
 var indexTests = []BinOpTest{
 	{"", "", 0},
 	{"", "a", -1},
@@ -303,10 +359,30 @@ func bmIndexByte(b *testing.B, index func([]byte, byte) int, n int) {
 	buf[n-1] = '\x00'
 }
 
+func BenchmarkEqual0(b *testing.B) {
+	var buf [4]byte
+	buf1 := buf[0:0]
+	buf2 := buf[1:1]
+	for i := 0; i < b.N; i++ {
+		eq := Equal(buf1, buf2)
+		if !eq {
+			b.Fatal("bad equal")
+		}
+	}
+}
+
+func BenchmarkEqual1(b *testing.B)           { bmEqual(b, Equal, 1) }
+func BenchmarkEqual6(b *testing.B)           { bmEqual(b, Equal, 6) }
+func BenchmarkEqual9(b *testing.B)           { bmEqual(b, Equal, 9) }
+func BenchmarkEqual15(b *testing.B)          { bmEqual(b, Equal, 15) }
+func BenchmarkEqual16(b *testing.B)          { bmEqual(b, Equal, 16) }
+func BenchmarkEqual20(b *testing.B)          { bmEqual(b, Equal, 20) }
 func BenchmarkEqual32(b *testing.B)          { bmEqual(b, Equal, 32) }
 func BenchmarkEqual4K(b *testing.B)          { bmEqual(b, Equal, 4<<10) }
 func BenchmarkEqual4M(b *testing.B)          { bmEqual(b, Equal, 4<<20) }
 func BenchmarkEqual64M(b *testing.B)         { bmEqual(b, Equal, 64<<20) }
+func BenchmarkEqualPort1(b *testing.B)       { bmEqual(b, EqualPortable, 1) }
+func BenchmarkEqualPort6(b *testing.B)       { bmEqual(b, EqualPortable, 6) }
 func BenchmarkEqualPort32(b *testing.B)      { bmEqual(b, EqualPortable, 32) }
 func BenchmarkEqualPort4K(b *testing.B)      { bmEqual(b, EqualPortable, 4<<10) }
 func BenchmarkEqualPortable4M(b *testing.B)  { bmEqual(b, EqualPortable, 4<<20) }
diff --git a/src/pkg/bytes/equal_test.go b/src/pkg/bytes/equal_test.go
new file mode 100644
index 0000000..1bf19a7
--- /dev/null
+++ b/src/pkg/bytes/equal_test.go
@@ -0,0 +1,47 @@
+// Copyright 2013 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.
+//
+// +build linux
+
+package bytes_test
+
+import (
+	. "bytes"
+	"syscall"
+	"testing"
+	"unsafe"
+)
+
+// This file tests the situation where memeq is checking
+// data very near to a page boundary.  We want to make sure
+// equal does not read across the boundary and cause a page
+// fault where it shouldn't.
+
+// This test runs only on linux.  The code being tested is
+// not OS-specific, so it does not need to be tested on all
+// operating systems.
+
+func TestEqualNearPageBoundary(t *testing.T) {
+	pagesize := syscall.Getpagesize()
+	b := make([]byte, 4*pagesize)
+	i := pagesize
+	for ; uintptr(unsafe.Pointer(&b[i]))%uintptr(pagesize) != 0; i++ {
+	}
+	syscall.Mprotect(b[i-pagesize:i], 0)
+	syscall.Mprotect(b[i+pagesize:i+2*pagesize], 0)
+	defer syscall.Mprotect(b[i-pagesize:i], syscall.PROT_READ|syscall.PROT_WRITE)
+	defer syscall.Mprotect(b[i+pagesize:i+2*pagesize], syscall.PROT_READ|syscall.PROT_WRITE)
+
+	// both of these should fault
+	//pagesize += int(b[i-1])
+	//pagesize += int(b[i+pagesize])
+
+	for j := 0; j < pagesize; j++ {
+		b[i+j] = 'A'
+	}
+	for j := 0; j <= pagesize; j++ {
+		Equal(b[i:i+j], b[i+pagesize-j:i+pagesize])
+		Equal(b[i+pagesize-j:i+pagesize], b[i:i+j])
+	}
+}
diff --git a/src/pkg/bytes/export_test.go b/src/pkg/bytes/export_test.go
index f61523e..3b915d5 100644
--- a/src/pkg/bytes/export_test.go
+++ b/src/pkg/bytes/export_test.go
@@ -7,3 +7,7 @@ package bytes
 // Export func for testing
 var IndexBytePortable = indexBytePortable
 var EqualPortable = equalPortable
+
+func (b *Buffer) Cap() int {
+	return cap(b.buf)
+}
diff --git a/src/pkg/compress/gzip/gzip.go b/src/pkg/compress/gzip/gzip.go
index 3035dff..45558b7 100644
--- a/src/pkg/compress/gzip/gzip.go
+++ b/src/pkg/compress/gzip/gzip.go
@@ -28,7 +28,7 @@ type Writer struct {
 	Header
 	w          io.Writer
 	level      int
-	compressor io.WriteCloser
+	compressor *flate.Writer
 	digest     hash.Hash32
 	size       uint32
 	closed     bool
@@ -191,6 +191,28 @@ func (z *Writer) Write(p []byte) (int, error) {
 	return n, z.err
 }
 
+// Flush flushes any pending compressed data to the underlying writer.
+//
+// It is useful mainly in compressed network protocols, to ensure that
+// a remote reader has enough data to reconstruct a packet. Flush does
+// not return until the data has been written. If the underlying
+// writer returns an error, Flush returns that error.
+//
+// In the terminology of the zlib library, Flush is equivalent to Z_SYNC_FLUSH.
+func (z *Writer) Flush() error {
+	if z.err != nil {
+		return z.err
+	}
+	if z.closed {
+		return nil
+	}
+	if z.compressor == nil {
+		z.Write(nil)
+	}
+	z.err = z.compressor.Flush()
+	return z.err
+}
+
 // Close closes the Writer. It does not close the underlying io.Writer.
 func (z *Writer) Close() error {
 	if z.err != nil {
diff --git a/src/pkg/compress/gzip/gzip_test.go b/src/pkg/compress/gzip/gzip_test.go
index 6f7b593..4d1af94 100644
--- a/src/pkg/compress/gzip/gzip_test.go
+++ b/src/pkg/compress/gzip/gzip_test.go
@@ -157,3 +157,43 @@ func TestLatin1RoundTrip(t *testing.T) {
 		}
 	}
 }
+
+func TestWriterFlush(t *testing.T) {
+	buf := new(bytes.Buffer)
+
+	w := NewWriter(buf)
+	w.Comment = "comment"
+	w.Extra = []byte("extra")
+	w.ModTime = time.Unix(1e8, 0)
+	w.Name = "name"
+
+	n0 := buf.Len()
+	if n0 != 0 {
+		t.Fatalf("buffer size = %d before writes; want 0", n0)
+	}
+
+	if err := w.Flush(); err != nil {
+		t.Fatal(err)
+	}
+
+	n1 := buf.Len()
+	if n1 == 0 {
+		t.Fatal("no data after first flush")
+	}
+
+	w.Write([]byte("x"))
+
+	n2 := buf.Len()
+	if n1 != n2 {
+		t.Fatalf("after writing a single byte, size changed from %d to %d; want no change", n1, n2)
+	}
+
+	if err := w.Flush(); err != nil {
+		t.Fatal(err)
+	}
+
+	n3 := buf.Len()
+	if n2 == n3 {
+		t.Fatal("Flush didn't flush any data")
+	}
+}
diff --git a/src/pkg/crypto/rsa/rsa.go b/src/pkg/crypto/rsa/rsa.go
index 35a5f7c..f56fb37 100644
--- a/src/pkg/crypto/rsa/rsa.go
+++ b/src/pkg/crypto/rsa/rsa.go
@@ -203,7 +203,9 @@ NextSetOfPrimes:
 		g.GCD(priv.D, y, e, totient)
 
 		if g.Cmp(bigOne) == 0 {
-			priv.D.Add(priv.D, totient)
+			if priv.D.Sign() < 0 {
+				priv.D.Add(priv.D, totient)
+			}
 			priv.Primes = primes
 			priv.N = n
 
diff --git a/src/pkg/crypto/rsa/rsa_test.go b/src/pkg/crypto/rsa/rsa_test.go
index f08cfe7..ffd96e6 100644
--- a/src/pkg/crypto/rsa/rsa_test.go
+++ b/src/pkg/crypto/rsa/rsa_test.go
@@ -93,6 +93,9 @@ func testKeyBasics(t *testing.T, priv *PrivateKey) {
 	if err := priv.Validate(); err != nil {
 		t.Errorf("Validate() failed: %s", err)
 	}
+	if priv.D.Cmp(priv.N) > 0 {
+		t.Errorf("private exponent too large")
+	}
 
 	pub := &priv.PublicKey
 	m := big.NewInt(42)
diff --git a/src/pkg/database/sql/convert.go b/src/pkg/database/sql/convert.go
index 5530a5d..c04adde 100644
--- a/src/pkg/database/sql/convert.go
+++ b/src/pkg/database/sql/convert.go
@@ -112,15 +112,13 @@ func convertAssign(dest, src interface{}) error {
 			if d == nil {
 				return errNilPtr
 			}
-			bcopy := make([]byte, len(s))
-			copy(bcopy, s)
-			*d = bcopy
+			*d = cloneBytes(s)
 			return nil
 		case *[]byte:
 			if d == nil {
 				return errNilPtr
 			}
-			*d = s
+			*d = cloneBytes(s)
 			return nil
 		case *RawBytes:
 			if d == nil {
@@ -131,6 +129,12 @@ func convertAssign(dest, src interface{}) error {
 		}
 	case nil:
 		switch d := dest.(type) {
+		case *interface{}:
+			if d == nil {
+				return errNilPtr
+			}
+			*d = nil
+			return nil
 		case *[]byte:
 			if d == nil {
 				return errNilPtr
@@ -250,6 +254,16 @@ func convertAssign(dest, src interface{}) error {
 	return fmt.Errorf("unsupported driver -> Scan pair: %T -> %T", src, dest)
 }
 
+func cloneBytes(b []byte) []byte {
+	if b == nil {
+		return nil
+	} else {
+		c := make([]byte, len(b))
+		copy(c, b)
+		return c
+	}
+}
+
 func asString(src interface{}) string {
 	switch v := src.(type) {
 	case string:
diff --git a/src/pkg/database/sql/convert_test.go b/src/pkg/database/sql/convert_test.go
index 6aedeb0..950e24f 100644
--- a/src/pkg/database/sql/convert_test.go
+++ b/src/pkg/database/sql/convert_test.go
@@ -143,6 +143,7 @@ var conversionTests = []conversionTest{
 	{s: []byte("byteslice"), d: &scaniface, wantiface: []byte("byteslice")},
 	{s: true, d: &scaniface, wantiface: true},
 	{s: nil, d: &scaniface},
+	{s: []byte(nil), d: &scaniface, wantiface: []byte(nil)},
 }
 
 func intPtrValue(intptr interface{}) interface{} {
@@ -221,7 +222,7 @@ func TestConversions(t *testing.T) {
 			}
 			if srcBytes, ok := ct.s.([]byte); ok {
 				dstBytes := (*ifptr).([]byte)
-				if &dstBytes[0] == &srcBytes[0] {
+				if len(srcBytes) > 0 && &dstBytes[0] == &srcBytes[0] {
 					errf("copy into interface{} didn't copy []byte data")
 				}
 			}
diff --git a/src/pkg/database/sql/fakedb_test.go b/src/pkg/database/sql/fakedb_test.go
index 55597f7..24c255f 100644
--- a/src/pkg/database/sql/fakedb_test.go
+++ b/src/pkg/database/sql/fakedb_test.go
@@ -229,7 +229,26 @@ func (c *fakeConn) Begin() (driver.Tx, error) {
 	return c.currTx, nil
 }
 
-func (c *fakeConn) Close() error {
+var hookPostCloseConn struct {
+	sync.Mutex
+	fn func(*fakeConn, error)
+}
+
+func setHookpostCloseConn(fn func(*fakeConn, error)) {
+	hookPostCloseConn.Lock()
+	defer hookPostCloseConn.Unlock()
+	hookPostCloseConn.fn = fn
+}
+
+func (c *fakeConn) Close() (err error) {
+	defer func() {
+		hookPostCloseConn.Lock()
+		fn := hookPostCloseConn.fn
+		hookPostCloseConn.Unlock()
+		if fn != nil {
+			fn(c, err)
+		}
+	}()
 	if c.currTx != nil {
 		return errors.New("can't close fakeConn; in a Transaction")
 	}
diff --git a/src/pkg/database/sql/sql.go b/src/pkg/database/sql/sql.go
index bc92ecd..bd450c7 100644
--- a/src/pkg/database/sql/sql.go
+++ b/src/pkg/database/sql/sql.go
@@ -4,6 +4,9 @@
 
 // Package sql provides a generic interface around SQL (or SQL-like)
 // databases.
+//
+// The sql package must be used in conjunction with a database driver.
+// See http://golang.org/s/sqldrivers for a list of drivers.
 package sql
 
 import (
@@ -189,14 +192,12 @@ type DB struct {
 	driver driver.Driver
 	dsn    string
 
-	mu        sync.Mutex           // protects following fields
-	outConn   map[*driverConn]bool // whether the conn is in use
-	freeConn  []*driverConn
-	closed    bool
-	dep       map[finalCloser]depSet
-	onConnPut map[*driverConn][]func() // code (with mu held) run when conn is next returned
-	lastPut   map[*driverConn]string   // stacktrace of last conn's put; debug only
-	maxIdle   int                      // zero means defaultMaxIdleConns; negative means 0
+	mu       sync.Mutex // protects following fields
+	freeConn []*driverConn
+	closed   bool
+	dep      map[finalCloser]depSet
+	lastPut  map[*driverConn]string // stacktrace of last conn's put; debug only
+	maxIdle  int                    // zero means defaultMaxIdleConns; negative means 0
 }
 
 // driverConn wraps a driver.Conn with a mutex, to
@@ -204,8 +205,46 @@ type DB struct {
 // interfaces returned via that Conn, such as calls on Tx, Stmt,
 // Result, Rows)
 type driverConn struct {
-	sync.Mutex
-	ci driver.Conn
+	db *DB
+
+	sync.Mutex // guards following
+	ci         driver.Conn
+	closed     bool
+
+	// guarded by db.mu
+	inUse bool
+	onPut []func() // code (with db.mu held) run when conn is next returned
+}
+
+// the dc.db's Mutex is held.
+func (dc *driverConn) closeDBLocked() error {
+	dc.Lock()
+	if dc.closed {
+		dc.Unlock()
+		return errors.New("sql: duplicate driverConn close")
+	}
+	dc.closed = true
+	dc.Unlock() // not defer; removeDep finalClose calls may need to lock
+	return dc.db.removeDepLocked(dc, dc)()
+}
+
+func (dc *driverConn) Close() error {
+	dc.Lock()
+	if dc.closed {
+		dc.Unlock()
+		return errors.New("sql: duplicate driverConn close")
+	}
+	dc.closed = true
+	dc.Unlock() // not defer; removeDep finalClose calls may need to lock
+	return dc.db.removeDep(dc, dc)
+}
+
+func (dc *driverConn) finalClose() error {
+	dc.Lock()
+	err := dc.ci.Close()
+	dc.ci = nil
+	dc.Unlock()
+	return err
 }
 
 // driverStmt associates a driver.Stmt with the
@@ -238,6 +277,10 @@ func (db *DB) addDep(x finalCloser, dep interface{}) {
 	//println(fmt.Sprintf("addDep(%T %p, %T %p)", x, x, dep, dep))
 	db.mu.Lock()
 	defer db.mu.Unlock()
+	db.addDepLocked(x, dep)
+}
+
+func (db *DB) addDepLocked(x finalCloser, dep interface{}) {
 	if db.dep == nil {
 		db.dep = make(map[finalCloser]depSet)
 	}
@@ -254,10 +297,16 @@ func (db *DB) addDep(x finalCloser, dep interface{}) {
 // If x no longer has any dependencies, its finalClose method will be
 // called and its error value will be returned.
 func (db *DB) removeDep(x finalCloser, dep interface{}) error {
+	db.mu.Lock()
+	fn := db.removeDepLocked(x, dep)
+	db.mu.Unlock()
+	return fn()
+}
+
+func (db *DB) removeDepLocked(x finalCloser, dep interface{}) func() error {
 	//println(fmt.Sprintf("removeDep(%T %p, %T %p)", x, x, dep, dep))
 	done := false
 
-	db.mu.Lock()
 	xdep := db.dep[x]
 	if xdep != nil {
 		delete(xdep, dep)
@@ -266,13 +315,14 @@ func (db *DB) removeDep(x finalCloser, dep interface{}) error {
 			done = true
 		}
 	}
-	db.mu.Unlock()
 
 	if !done {
-		return nil
+		return func() error { return nil }
+	}
+	return func() error {
+		//println(fmt.Sprintf("calling final close on %T %v (%#v)", x, x, x))
+		return x.finalClose()
 	}
-	//println(fmt.Sprintf("calling final close on %T %v (%#v)", x, x, x))
-	return x.finalClose()
 }
 
 // Open opens a database specified by its database driver name and a
@@ -280,7 +330,9 @@ func (db *DB) removeDep(x finalCloser, dep interface{}) error {
 // database name and connection information.
 //
 // Most users will open a database via a driver-specific connection
-// helper function that returns a *DB.
+// helper function that returns a *DB. No database drivers are included
+// in the Go standard library. See http://golang.org/s/sqldrivers for
+// a list of third-party drivers.
 //
 // Open may just validate its arguments without creating a connection
 // to the database. To verify that the data source name is valid, call
@@ -291,11 +343,9 @@ func Open(driverName, dataSourceName string) (*DB, error) {
 		return nil, fmt.Errorf("sql: unknown driver %q (forgotten import?)", driverName)
 	}
 	db := &DB{
-		driver:    driveri,
-		dsn:       dataSourceName,
-		outConn:   make(map[*driverConn]bool),
-		lastPut:   make(map[*driverConn]string),
-		onConnPut: make(map[*driverConn][]func()),
+		driver:  driveri,
+		dsn:     dataSourceName,
+		lastPut: make(map[*driverConn]string),
 	}
 	return db, nil
 }
@@ -320,9 +370,7 @@ func (db *DB) Close() error {
 	defer db.mu.Unlock()
 	var err error
 	for _, dc := range db.freeConn {
-		dc.Lock()
-		err1 := dc.ci.Close()
-		dc.Unlock()
+		err1 := dc.closeDBLocked()
 		if err1 != nil {
 			err = err1
 		}
@@ -365,11 +413,7 @@ func (db *DB) SetMaxIdleConns(n int) {
 		dc := db.freeConn[nfree-1]
 		db.freeConn[nfree-1] = nil
 		db.freeConn = db.freeConn[:nfree-1]
-		go func() {
-			dc.Lock()
-			dc.ci.Close()
-			dc.Unlock()
-		}()
+		go dc.Close()
 	}
 }
 
@@ -383,7 +427,7 @@ func (db *DB) conn() (*driverConn, error) {
 	if n := len(db.freeConn); n > 0 {
 		conn := db.freeConn[n-1]
 		db.freeConn = db.freeConn[:n-1]
-		db.outConn[conn] = true
+		conn.inUse = true
 		db.mu.Unlock()
 		return conn, nil
 	}
@@ -393,9 +437,13 @@ func (db *DB) conn() (*driverConn, error) {
 	if err != nil {
 		return nil, err
 	}
-	dc := &driverConn{ci: ci}
+	dc := &driverConn{
+		db: db,
+		ci: ci,
+	}
 	db.mu.Lock()
-	db.outConn[dc] = true
+	db.addDepLocked(dc, dc)
+	dc.inUse = true
 	db.mu.Unlock()
 	return dc, nil
 }
@@ -408,7 +456,7 @@ func (db *DB) conn() (*driverConn, error) {
 func (db *DB) connIfFree(wanted *driverConn) (conn *driverConn, ok bool) {
 	db.mu.Lock()
 	defer db.mu.Unlock()
-	if db.outConn[wanted] {
+	if wanted.inUse {
 		return conn, false
 	}
 	for i, conn := range db.freeConn {
@@ -417,7 +465,7 @@ func (db *DB) connIfFree(wanted *driverConn) (conn *driverConn, ok bool) {
 		}
 		db.freeConn[i] = db.freeConn[len(db.freeConn)-1]
 		db.freeConn = db.freeConn[:len(db.freeConn)-1]
-		db.outConn[wanted] = true
+		wanted.inUse = true
 		return wanted, true
 	}
 	return nil, false
@@ -432,8 +480,8 @@ var putConnHook func(*DB, *driverConn)
 func (db *DB) noteUnusedDriverStatement(c *driverConn, si driver.Stmt) {
 	db.mu.Lock()
 	defer db.mu.Unlock()
-	if db.outConn[c] {
-		db.onConnPut[c] = append(db.onConnPut[c], func() {
+	if c.inUse {
+		c.onPut = append(c.onPut, func() {
 			si.Close()
 		})
 	} else {
@@ -449,7 +497,7 @@ const debugGetPut = false
 // err is optionally the last error that occurred on this connection.
 func (db *DB) putConn(dc *driverConn, err error) {
 	db.mu.Lock()
-	if !db.outConn[dc] {
+	if !dc.inUse {
 		if debugGetPut {
 			fmt.Printf("putConn(%v) DUPLICATE was: %s\n\nPREVIOUS was: %s", dc, stack(), db.lastPut[dc])
 		}
@@ -458,14 +506,12 @@ func (db *DB) putConn(dc *driverConn, err error) {
 	if debugGetPut {
 		db.lastPut[dc] = stack()
 	}
-	delete(db.outConn, dc)
+	dc.inUse = false
 
-	if fns, ok := db.onConnPut[dc]; ok {
-		for _, fn := range fns {
-			fn()
-		}
-		delete(db.onConnPut, dc)
+	for _, fn := range dc.onPut {
+		fn()
 	}
+	dc.onPut = nil
 
 	if err == driver.ErrBadConn {
 		// Don't reuse bad connections.
@@ -484,9 +530,7 @@ func (db *DB) putConn(dc *driverConn, err error) {
 	// statements which are still active?
 	db.mu.Unlock()
 
-	dc.Lock()
-	dc.ci.Close()
-	dc.Unlock()
+	dc.Close()
 }
 
 // Prepare creates a prepared statement for later queries or executions.
@@ -528,6 +572,7 @@ func (db *DB) prepare(query string) (*Stmt, error) {
 		css:   []connStmt{{dc, si}},
 	}
 	db.addDep(stmt, stmt)
+	db.addDep(dc, stmt)
 	db.putConn(dc, nil)
 	return stmt, nil
 }
@@ -1031,6 +1076,7 @@ func (s *Stmt) connStmt() (ci *driverConn, releaseConn func(error), si driver.St
 			if err != nil {
 				return nil, nil, nil, err
 			}
+			s.db.addDep(dc, s)
 			s.mu.Lock()
 			cs = connStmt{dc, si}
 			s.css = append(s.css, cs)
@@ -1149,6 +1195,7 @@ func (s *Stmt) Close() error {
 func (s *Stmt) finalClose() error {
 	for _, v := range s.css {
 		s.db.noteUnusedDriverStatement(v.dc, v.si)
+		s.db.removeDep(v.dc, s)
 	}
 	s.css = nil
 	return nil
@@ -1252,24 +1299,6 @@ func (rs *Rows) Scan(dest ...interface{}) error {
 			return fmt.Errorf("sql: Scan error on column index %d: %v", i, err)
 		}
 	}
-	for _, dp := range dest {
-		b, ok := dp.(*[]byte)
-		if !ok {
-			continue
-		}
-		if *b == nil {
-			// If the []byte is now nil (for a NULL value),
-			// don't fall through to below which would
-			// turn it into a non-nil 0-length byte slice
-			continue
-		}
-		if _, ok = dp.(*RawBytes); ok {
-			continue
-		}
-		clone := make([]byte, len(*b))
-		copy(clone, *b)
-		*b = clone
-	}
 	return nil
 }
 
diff --git a/src/pkg/database/sql/sql_test.go b/src/pkg/database/sql/sql_test.go
index 2a9592e..6b91783 100644
--- a/src/pkg/database/sql/sql_test.go
+++ b/src/pkg/database/sql/sql_test.go
@@ -7,7 +7,9 @@ package sql
 import (
 	"fmt"
 	"reflect"
+	"runtime"
 	"strings"
+	"sync"
 	"testing"
 	"time"
 )
@@ -36,7 +38,14 @@ const fakeDBName = "foo"
 
 var chrisBirthday = time.Unix(123456789, 0)
 
-func newTestDB(t *testing.T, name string) *DB {
+type testOrBench interface {
+	Fatalf(string, ...interface{})
+	Errorf(string, ...interface{})
+	Fatal(...interface{})
+	Error(...interface{})
+}
+
+func newTestDB(t testOrBench, name string) *DB {
 	db, err := Open("test", fakeDBName)
 	if err != nil {
 		t.Fatalf("Open: %v", err)
@@ -53,18 +62,24 @@ func newTestDB(t *testing.T, name string) *DB {
 	return db
 }
 
-func exec(t *testing.T, db *DB, query string, args ...interface{}) {
+func exec(t testOrBench, db *DB, query string, args ...interface{}) {
 	_, err := db.Exec(query, args...)
 	if err != nil {
 		t.Fatalf("Exec of %q: %v", query, err)
 	}
 }
 
-func closeDB(t *testing.T, db *DB) {
+func closeDB(t testOrBench, db *DB) {
 	if e := recover(); e != nil {
 		fmt.Printf("Panic: %v\n", e)
 		panic(e)
 	}
+	defer setHookpostCloseConn(nil)
+	setHookpostCloseConn(func(_ *fakeConn, err error) {
+		if err != nil {
+			t.Errorf("Error closing fakeConn: %v", err)
+		}
+	})
 	err := db.Close()
 	if err != nil {
 		t.Fatalf("error closing DB: %v", err)
@@ -790,3 +805,111 @@ func TestMaxIdleConns(t *testing.T) {
 		t.Errorf("freeConns = %d; want 0", got)
 	}
 }
+
+// golang.org/issue/5046
+func TestCloseConnBeforeStmts(t *testing.T) {
+	defer setHookpostCloseConn(nil)
+	setHookpostCloseConn(func(_ *fakeConn, err error) {
+		if err != nil {
+			t.Errorf("Error closing fakeConn: %v", err)
+		}
+	})
+
+	db := newTestDB(t, "people")
+
+	stmt, err := db.Prepare("SELECT|people|name|")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if len(db.freeConn) != 1 {
+		t.Fatalf("expected 1 freeConn; got %d", len(db.freeConn))
+	}
+	dc := db.freeConn[0]
+	if dc.closed {
+		t.Errorf("conn shouldn't be closed")
+	}
+
+	err = db.Close()
+	if err != nil {
+		t.Errorf("db Close = %v", err)
+	}
+	if !dc.closed {
+		t.Errorf("after db.Close, driverConn should be closed")
+	}
+	if dc.ci == nil {
+		t.Errorf("after db.Close, driverConn should still have its Conn interface")
+	}
+
+	err = stmt.Close()
+	if err != nil {
+		t.Errorf("Stmt close = %v", err)
+	}
+
+	if !dc.closed {
+		t.Errorf("conn should be closed")
+	}
+	if dc.ci != nil {
+		t.Errorf("after Stmt Close, driverConn's Conn interface should be nil")
+	}
+}
+
+func manyConcurrentQueries(t testOrBench) {
+	maxProcs, numReqs := 16, 500
+	if testing.Short() {
+		maxProcs, numReqs = 4, 50
+	}
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs))
+
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+
+	stmt, err := db.Prepare("SELECT|people|name|")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	var wg sync.WaitGroup
+	wg.Add(numReqs)
+
+	reqs := make(chan bool)
+	defer close(reqs)
+
+	for i := 0; i < maxProcs*2; i++ {
+		go func() {
+			for _ = range reqs {
+				rows, err := stmt.Query()
+				if err != nil {
+					t.Errorf("error on query:  %v", err)
+					wg.Done()
+					continue
+				}
+
+				var name string
+				for rows.Next() {
+					rows.Scan(&name)
+				}
+				rows.Close()
+
+				wg.Done()
+			}
+		}()
+	}
+
+	for i := 0; i < numReqs; i++ {
+		reqs <- true
+	}
+
+	wg.Wait()
+}
+
+func TestConcurrency(t *testing.T) {
+	manyConcurrentQueries(t)
+}
+
+func BenchmarkConcurrency(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		manyConcurrentQueries(b)
+	}
+}
diff --git a/src/pkg/go/build/build.go b/src/pkg/go/build/build.go
index dc3669c..cc89afb 100644
--- a/src/pkg/go/build/build.go
+++ b/src/pkg/go/build/build.go
@@ -301,7 +301,13 @@ func defaultContext() Context {
 	case "0":
 		c.CgoEnabled = false
 	default:
-		c.CgoEnabled = cgoEnabled[c.GOOS+"/"+c.GOARCH]
+		// golang.org/issue/5141
+		// cgo should be disabled for cross compilation builds
+		if runtime.GOARCH == c.GOARCH && runtime.GOOS == c.GOOS {
+			c.CgoEnabled = cgoEnabled[c.GOOS+"/"+c.GOARCH]
+			break
+		}
+		c.CgoEnabled = false
 	}
 
 	return c
diff --git a/src/pkg/go/doc/doc.go b/src/pkg/go/doc/doc.go
index 96d867c..4264940 100644
--- a/src/pkg/go/doc/doc.go
+++ b/src/pkg/go/doc/doc.go
@@ -64,14 +64,14 @@ type Func struct {
 	Level int    // embedding level; 0 means not embedded
 }
 
-// A Note represents marked comments starting with "MARKER(uid): note body".
+// A Note represents a marked comment starting with "MARKER(uid): note body".
 // Any note with a marker of 2 or more upper case [A-Z] letters and a uid of
 // at least one character is recognized. The ":" following the uid is optional.
 // Notes are collected in the Package.Notes map indexed by the notes marker.
 type Note struct {
-	Pos  token.Pos // position of the comment containing the marker
-	UID  string    // uid found with the marker
-	Body string    // note body text
+	Pos, End token.Pos // position range of the comment containing the marker
+	UID      string    // uid found with the marker
+	Body     string    // note body text
 }
 
 // Mode values control the operation of New.
diff --git a/src/pkg/go/doc/reader.go b/src/pkg/go/doc/reader.go
index 7e1422d..4fa6fd9 100644
--- a/src/pkg/go/doc/reader.go
+++ b/src/pkg/go/doc/reader.go
@@ -419,6 +419,7 @@ func (r *reader) readNote(list []*ast.Comment) {
 			marker := text[m[2]:m[3]]
 			r.notes[marker] = append(r.notes[marker], &Note{
 				Pos:  list[0].Pos(),
+				End:  list[len(list)-1].End(),
 				UID:  text[m[4]:m[5]],
 				Body: body,
 			})
diff --git a/src/pkg/go/parser/interface.go b/src/pkg/go/parser/interface.go
index 39affdd..149257c 100644
--- a/src/pkg/go/parser/interface.go
+++ b/src/pkg/go/parser/interface.go
@@ -162,16 +162,27 @@ func ParseDir(fset *token.FileSet, path string, filter func(os.FileInfo) bool, m
 }
 
 // ParseExpr is a convenience function for obtaining the AST of an expression x.
-// The position information recorded in the AST is undefined.
+// The position information recorded in the AST is undefined. The filename used
+// in error messages is the empty string.
 //
 func ParseExpr(x string) (ast.Expr, error) {
-	// parse x within the context of a complete package for correct scopes;
-	// use //line directive for correct positions in error messages and put
-	// x alone on a separate line (handles line comments), followed by a ';'
-	// to force an error if the expression is incomplete
-	file, err := ParseFile(token.NewFileSet(), "", "package p;func _(){_=\n//line :1\n"+x+"\n;}", 0)
-	if err != nil {
-		return nil, err
+	var p parser
+	p.init(token.NewFileSet(), "", []byte(x), 0)
+
+	// Set up pkg-level scopes to avoid nil-pointer errors.
+	// This is not needed for a correct expression x as the
+	// parser will be ok with a nil topScope, but be cautious
+	// in case of an erroneous x.
+	p.openScope()
+	p.pkgScope = p.topScope
+	e := p.parseRhsOrType()
+	p.closeScope()
+	assert(p.topScope == nil, "unbalanced scopes")
+
+	if p.errors.Len() > 0 {
+		p.errors.Sort()
+		return nil, p.errors.Err()
 	}
-	return file.Decls[0].(*ast.FuncDecl).Body.List[0].(*ast.AssignStmt).Rhs[0], nil
+
+	return e, nil
 }
diff --git a/src/pkg/go/parser/parser_test.go b/src/pkg/go/parser/parser_test.go
index 1960377..48813d1 100644
--- a/src/pkg/go/parser/parser_test.go
+++ b/src/pkg/go/parser/parser_test.go
@@ -68,7 +68,7 @@ func TestParseDir(t *testing.T) {
 
 func TestParseExpr(t *testing.T) {
 	// just kicking the tires:
-	// a valid expression
+	// a valid arithmetic expression
 	src := "a + b"
 	x, err := ParseExpr(src)
 	if err != nil {
@@ -79,6 +79,17 @@ func TestParseExpr(t *testing.T) {
 		t.Errorf("ParseExpr(%s): got %T, expected *ast.BinaryExpr", src, x)
 	}
 
+	// a valid type expression
+	src = "struct{x *int}"
+	x, err = ParseExpr(src)
+	if err != nil {
+		t.Fatalf("ParseExpr(%s): %v", src, err)
+	}
+	// sanity check
+	if _, ok := x.(*ast.StructType); !ok {
+		t.Errorf("ParseExpr(%s): got %T, expected *ast.StructType", src, x)
+	}
+
 	// an invalid expression
 	src = "a + *"
 	_, err = ParseExpr(src)
diff --git a/src/pkg/go/printer/printer.go b/src/pkg/go/printer/printer.go
index 3c8d23e..e06d2ed 100644
--- a/src/pkg/go/printer/printer.go
+++ b/src/pkg/go/printer/printer.go
@@ -395,35 +395,6 @@ func (p *printer) writeCommentPrefix(pos, next token.Position, prev, comment *as
 	}
 }
 
-// Split comment text into lines
-// (using strings.Split(text, "\n") is significantly slower for
-// this specific purpose, as measured with: go test -bench=Print)
-//
-func split(text string) []string {
-	// count lines (comment text never ends in a newline)
-	n := 1
-	for i := 0; i < len(text); i++ {
-		if text[i] == '\n' {
-			n++
-		}
-	}
-
-	// split
-	lines := make([]string, n)
-	n = 0
-	i := 0
-	for j := 0; j < len(text); j++ {
-		if text[j] == '\n' {
-			lines[n] = text[i:j] // exclude newline
-			i = j + 1            // discard newline
-			n++
-		}
-	}
-	lines[n] = text[i:]
-
-	return lines
-}
-
 // Returns true if s contains only white space
 // (only tabs and blanks can appear in the printer's context).
 //
@@ -616,7 +587,7 @@ func (p *printer) writeComment(comment *ast.Comment) {
 
 	// for /*-style comments, print line by line and let the
 	// write function take care of the proper indentation
-	lines := split(text)
+	lines := strings.Split(text, "\n")
 
 	// The comment started in the first column but is going
 	// to be indented. For an idempotent result, add indentation
diff --git a/src/pkg/image/gif/reader_test.go b/src/pkg/image/gif/reader_test.go
index a035ef1..dcc6c6d 100644
--- a/src/pkg/image/gif/reader_test.go
+++ b/src/pkg/image/gif/reader_test.go
@@ -114,22 +114,25 @@ func try(t *testing.T, b []byte, want string) {
 }
 
 func TestBounds(t *testing.T) {
+	// make a local copy of testGIF
+	gif := make([]byte, len(testGIF))
+	copy(gif, testGIF)
 	// Make the bounds too big, just by one.
-	testGIF[32] = 2
+	gif[32] = 2
 	want := "gif: frame bounds larger than image bounds"
-	try(t, testGIF, want)
+	try(t, gif, want)
 
 	// Make the bounds too small; does not trigger bounds
 	// check, but now there's too much data.
-	testGIF[32] = 0
+	gif[32] = 0
 	want = "gif: too much image data"
-	try(t, testGIF, want)
-	testGIF[32] = 1
+	try(t, gif, want)
+	gif[32] = 1
 
 	// Make the bounds really big, expect an error.
 	want = "gif: frame bounds larger than image bounds"
 	for i := 0; i < 4; i++ {
-		testGIF[32+i] = 0xff
+		gif[32+i] = 0xff
 	}
-	try(t, testGIF, want)
+	try(t, gif, want)
 }
diff --git a/src/pkg/math/big/int.go b/src/pkg/math/big/int.go
index fd7f005..d1b5602 100644
--- a/src/pkg/math/big/int.go
+++ b/src/pkg/math/big/int.go
@@ -53,7 +53,7 @@ func (z *Int) SetInt64(x int64) *Int {
 
 // SetUint64 sets z to x and returns z.
 func (z *Int) SetUint64(x uint64) *Int {
-	z.abs = z.abs.setUint64(uint64(x))
+	z.abs = z.abs.setUint64(x)
 	z.neg = false
 	return z
 }
@@ -513,13 +513,7 @@ func (z *Int) Scan(s fmt.ScanState, ch rune) error {
 // Int64 returns the int64 representation of x.
 // If x cannot be represented in an int64, the result is undefined.
 func (x *Int) Int64() int64 {
-	if len(x.abs) == 0 {
-		return 0
-	}
-	v := int64(x.abs[0])
-	if _W == 32 && len(x.abs) > 1 {
-		v |= int64(x.abs[1]) << 32
-	}
+	v := int64(x.Uint64())
 	if x.neg {
 		v = -v
 	}
@@ -527,7 +521,7 @@ func (x *Int) Int64() int64 {
 }
 
 // Uint64 returns the uint64 representation of x.
-// If x cannot be represented in an uint64, the result is undefined.
+// If x cannot be represented in a uint64, the result is undefined.
 func (x *Int) Uint64() uint64 {
 	if len(x.abs) == 0 {
 		return 0
diff --git a/src/pkg/math/big/rat.go b/src/pkg/math/big/rat.go
index 3e6473d..75d044f 100644
--- a/src/pkg/math/big/rat.go
+++ b/src/pkg/math/big/rat.go
@@ -163,16 +163,16 @@ func quotToFloat(a, b nat) (f float64, exact bool) {
 	return
 }
 
-// Float64 returns the nearest float64 value to z.
-// If z is exactly representable as a float64, Float64 returns exact=true.
-// If z is negative, so too is f, even if f==0.
-func (z *Rat) Float64() (f float64, exact bool) {
-	b := z.b.abs
+// Float64 returns the nearest float64 value for x and a bool indicating
+// whether f represents x exactly. The sign of f always matches the sign
+// of x, even if f == 0.
+func (x *Rat) Float64() (f float64, exact bool) {
+	b := x.b.abs
 	if len(b) == 0 {
 		b = b.set(natOne) // materialize denominator
 	}
-	f, exact = quotToFloat(z.a.abs, b)
-	if z.a.neg {
+	f, exact = quotToFloat(x.a.abs, b)
+	if x.a.neg {
 		f = -f
 	}
 	return
diff --git a/src/pkg/math/big/rat_test.go b/src/pkg/math/big/rat_test.go
index 462dfb7..1c2c642 100644
--- a/src/pkg/math/big/rat_test.go
+++ b/src/pkg/math/big/rat_test.go
@@ -503,9 +503,7 @@ func TestIssue3521(t *testing.T) {
 // Test inputs to Rat.SetString.  The prefix "long:" causes the test
 // to be skipped in --test.short mode.  (The threshold is about 500us.)
 var float64inputs = []string{
-	//
 	// Constants plundered from strconv/testfp.txt.
-	//
 
 	// Table 1: Stress Inputs for Conversion to 53-bit Binary, < 1/2 ULP
 	"5e+125",
@@ -583,9 +581,7 @@ var float64inputs = []string{
 	"75224575729e-45",
 	"459926601011e+15",
 
-	//
 	// Constants plundered from strconv/atof_test.go.
-	//
 
 	"0",
 	"1",
@@ -734,7 +730,7 @@ func TestFloat64SpecialCases(t *testing.T) {
 			case f == 0 && r.Num().BitLen() == 0:
 				// Ok: Rat(0) is equivalent to both +/- float64(0).
 			default:
-				t.Errorf("strconv.ParseFloat(%q) = %g (%b), want %g (%b); delta=%g", input, e, e, f, f, f-e)
+				t.Errorf("strconv.ParseFloat(%q) = %g (%b), want %g (%b); delta = %g", input, e, e, f, f, f-e)
 			}
 		}
 
@@ -795,7 +791,7 @@ func TestFloat64Distribution(t *testing.T) {
 
 					if !checkIsBestApprox(t, f, r) {
 						// Append context information.
-						t.Errorf("(input was mantissa %#x, exp %d; f=%g (%b); f~%g; r=%v)",
+						t.Errorf("(input was mantissa %#x, exp %d; f = %g (%b); f ~ %g; r = %v)",
 							b, exp, f, f, math.Ldexp(float64(b), exp), r)
 					}
 
@@ -830,7 +826,7 @@ func checkNonLossyRoundtrip(t *testing.T, f float64) {
 	}
 	f2, exact := r.Float64()
 	if f != f2 || !exact {
-		t.Errorf("Rat.SetFloat64(%g).Float64() = %g (%b), %v, want %g (%b), %v; delta=%b",
+		t.Errorf("Rat.SetFloat64(%g).Float64() = %g (%b), %v, want %g (%b), %v; delta = %b",
 			f, f2, f2, exact, f, f, true, f2-f)
 	}
 }
diff --git a/src/pkg/math/hypot.go b/src/pkg/math/hypot.go
index 3846e6d..2087cb0 100644
--- a/src/pkg/math/hypot.go
+++ b/src/pkg/math/hypot.go
@@ -12,8 +12,10 @@ package math
 // unnecessary overflow and underflow.
 //
 // Special cases are:
-//	Hypot(p, q) = +Inf if p or q is infinite
-//	Hypot(p, q) = NaN if p or q is NaN
+//	Hypot(±Inf, q) = +Inf
+//	Hypot(p, ±Inf) = +Inf
+//	Hypot(NaN, q) = NaN
+//	Hypot(p, NaN) = NaN
 func Hypot(p, q float64) float64
 
 func hypot(p, q float64) float64 {
diff --git a/src/pkg/math/tanh.go b/src/pkg/math/tanh.go
index 7305be6..cf0ffa1 100644
--- a/src/pkg/math/tanh.go
+++ b/src/pkg/math/tanh.go
@@ -65,7 +65,7 @@ var tanhQ = [...]float64{
 	4.84406305325125486048E3,
 }
 
-// Tanh computes the hyperbolic tangent of x.
+// Tanh returns the hyperbolic tangent of x.
 //
 // Special cases are:
 //	Tanh(±0) = ±0
diff --git a/src/pkg/net/dial.go b/src/pkg/net/dial.go
index da5f7e3..b18d283 100644
--- a/src/pkg/net/dial.go
+++ b/src/pkg/net/dial.go
@@ -9,112 +9,48 @@ import (
 	"time"
 )
 
-// A DialOption modifies a DialOpt call.
-type DialOption interface {
-	setDialOpt(*dialOpts)
-}
-
-var noLocalAddr Addr // nil
-
-// dialOpts holds all the dial options, populated by a DialOption's
-// setDialOpt.
+// A Dialer contains options for connecting to an address.
 //
-// All fields may be their zero value.
-type dialOpts struct {
-	deadline        time.Time
-	localAddr       Addr
-	network         string // if empty, "tcp"
-	deferredConnect bool
-}
-
-func (o *dialOpts) net() string {
-	if o.network == "" {
-		return "tcp"
+// The zero value for each field is equivalent to dialing
+// without that option. Dialing with the zero value of Dialer
+// is therefore equivalent to just calling the Dial function.
+type Dialer struct {
+	// Timeout is the maximum amount of time a dial will wait for
+	// a connect to complete. If Deadline is also set, it may fail
+	// earlier.
+	//
+	// The default is no timeout.
+	//
+	// With or without a timeout, the operating system may impose
+	// its own earlier timeout. For instance, TCP timeouts are
+	// often around 3 minutes.
+	Timeout time.Duration
+
+	// Deadline is the absolute point in time after which dials
+	// will fail. If Timeout is set, it may fail earlier.
+	// Zero means no deadline, or dependent on the operating system
+	// as with the Timeout option.
+	Deadline time.Time
+
+	// LocalAddr is the local address to use when dialing an
+	// address. The address must be of a compatible type for the
+	// network being dialed.
+	// If nil, a local address is automatically chosen.
+	LocalAddr Addr
+}
+
+// Return either now+Timeout or Deadline, whichever comes first.
+// Or zero, if neither is set.
+func (d *Dialer) deadline() time.Time {
+	if d.Timeout == 0 {
+		return d.Deadline
+	}
+	timeoutDeadline := time.Now().Add(d.Timeout)
+	if d.Deadline.IsZero() || timeoutDeadline.Before(d.Deadline) {
+		return timeoutDeadline
+	} else {
+		return d.Deadline
 	}
-	return o.network
-}
-
-var (
-	// TCP is a dial option to dial with TCP (over IPv4 or IPv6).
-	TCP = Network("tcp")
-
-	// UDP is a dial option to dial with UDP (over IPv4 or IPv6).
-	UDP = Network("udp")
-)
-
-// Network returns a DialOption to dial using the given network.
-//
-// Known networks are "tcp", "tcp4" (IPv4-only), "tcp6" (IPv6-only),
-// "udp", "udp4" (IPv4-only), "udp6" (IPv6-only), "ip", "ip4"
-// (IPv4-only), "ip6" (IPv6-only), "unix", "unixgram" and
-// "unixpacket".
-//
-// For IP networks, net must be "ip", "ip4" or "ip6" followed
-// by a colon and a protocol number or name, such as
-// "ipv4:1" or "ip6:ospf".
-func Network(net string) DialOption {
-	return dialNetwork(net)
-}
-
-type dialNetwork string
-
-func (s dialNetwork) setDialOpt(o *dialOpts) {
-	o.network = string(s)
-}
-
-// Deadline returns a DialOption to fail a dial that doesn't
-// complete before t.
-func Deadline(t time.Time) DialOption {
-	return dialDeadline(t)
-}
-
-type dialDeadline time.Time
-
-func (t dialDeadline) setDialOpt(o *dialOpts) {
-	o.deadline = time.Time(t)
-}
-
-// Timeout returns a DialOption to fail a dial that doesn't
-// complete within the provided duration.
-func Timeout(d time.Duration) DialOption {
-	return dialTimeoutOpt(d)
-}
-
-type dialTimeoutOpt time.Duration
-
-func (d dialTimeoutOpt) setDialOpt(o *dialOpts) {
-	o.deadline = time.Now().Add(time.Duration(d))
-}
-
-type tcpFastOpen struct{}
-
-func (tcpFastOpen) setDialOpt(o *dialOpts) {
-	o.deferredConnect = true
-}
-
-// TODO(bradfitz): implement this (golang.org/issue/4842) and unexport this.
-//
-// TCPFastTimeout returns an option to use TCP Fast Open (TFO) when
-// doing this dial. It is only valid for use with TCP connections.
-// Data sent over a TFO connection may be processed by the peer
-// multiple times, so should be used with caution.
-func todo_TCPFastTimeout() DialOption {
-	return tcpFastOpen{}
-}
-
-type localAddrOption struct {
-	la Addr
-}
-
-func (a localAddrOption) setDialOpt(o *dialOpts) {
-	o.localAddr = a.la
-}
-
-// LocalAddress returns a dial option to perform a dial with the
-// provided local address. The address must be of a compatible type
-// for the network being dialed.
-func LocalAddress(addr Addr) DialOption {
-	return localAddrOption{addr}
 }
 
 func parseNetwork(net string) (afnet string, proto int, err error) {
@@ -161,7 +97,7 @@ func resolveAddr(op, net, addr string, deadline time.Time) (Addr, error) {
 	return resolveInternetAddr(afnet, addr, deadline)
 }
 
-// Dial connects to the address addr on the network net.
+// Dial connects to the address on the named network.
 //
 // Known networks are "tcp", "tcp4" (IPv4-only), "tcp6" (IPv6-only),
 // "udp", "udp4" (IPv4-only), "udp6" (IPv6-only), "ip", "ip4"
@@ -181,32 +117,33 @@ func resolveAddr(op, net, addr string, deadline time.Time) (Addr, error) {
 //	Dial("tcp", "[2001:db8::1]:http")
 //	Dial("tcp", "[fe80::1%lo0]:80")
 //
-// For IP networks, the net must be "ip", "ip4" or "ip6" followed by a
-// colon and a protocol number or name and the addr must be a literal
-// IP address.
+// For IP networks, the network must be "ip", "ip4" or "ip6" followed
+// by a colon and a protocol number or name and the addr must be a
+// literal IP address.
 //
 // Examples:
 //	Dial("ip4:1", "127.0.0.1")
 //	Dial("ip6:ospf", "::1")
 //
-// For Unix networks, the addr must be a file system path.
-func Dial(net, addr string) (Conn, error) {
-	return DialOpt(addr, dialNetwork(net))
+// For Unix networks, the address must be a file system path.
+func Dial(network, address string) (Conn, error) {
+	var d Dialer
+	return d.Dial(network, address)
 }
 
-// DialOpt dials addr using the provided options.
-// If no options are provided, DialOpt(addr) is equivalent
-// to Dial("tcp", addr). See Dial for the syntax of addr.
-func DialOpt(addr string, opts ...DialOption) (Conn, error) {
-	var o dialOpts
-	for _, opt := range opts {
-		opt.setDialOpt(&o)
-	}
-	ra, err := resolveAddr("dial", o.net(), addr, o.deadline)
-	if err != nil {
-		return nil, err
-	}
-	return dial(o.net(), addr, o.localAddr, ra, o.deadline)
+// DialTimeout acts like Dial but takes a timeout.
+// The timeout includes name resolution, if required.
+func DialTimeout(network, address string, timeout time.Duration) (Conn, error) {
+	d := Dialer{Timeout: timeout}
+	return d.Dial(network, address)
+}
+
+// Dial connects to the address on the named network.
+//
+// See func Dial for a description of the network and address
+// parameters.
+func (d *Dialer) Dial(network, address string) (Conn, error) {
+	return resolveAndDial(network, address, d.LocalAddr, d.deadline())
 }
 
 func dial(net, addr string, la, ra Addr, deadline time.Time) (c Conn, err error) {
@@ -235,58 +172,6 @@ func dial(net, addr string, la, ra Addr, deadline time.Time) (c Conn, err error)
 	return
 }
 
-// DialTimeout acts like Dial but takes a timeout.
-// The timeout includes name resolution, if required.
-func DialTimeout(net, addr string, timeout time.Duration) (Conn, error) {
-	return dialTimeout(net, addr, timeout)
-}
-
-// dialTimeoutRace is the old implementation of DialTimeout, still used
-// on operating systems where the deadline hasn't been pushed down
-// into the pollserver.
-// TODO: fix this on plan9.
-func dialTimeoutRace(net, addr string, timeout time.Duration) (Conn, error) {
-	t := time.NewTimer(timeout)
-	defer t.Stop()
-	type pair struct {
-		Conn
-		error
-	}
-	ch := make(chan pair, 1)
-	resolvedAddr := make(chan Addr, 1)
-	go func() {
-		ra, err := resolveAddr("dial", net, addr, noDeadline)
-		if err != nil {
-			ch <- pair{nil, err}
-			return
-		}
-		resolvedAddr <- ra // in case we need it for OpError
-		c, err := dial(net, addr, noLocalAddr, ra, noDeadline)
-		ch <- pair{c, err}
-	}()
-	select {
-	case <-t.C:
-		// Try to use the real Addr in our OpError, if we resolved it
-		// before the timeout. Otherwise we just use stringAddr.
-		var ra Addr
-		select {
-		case a := <-resolvedAddr:
-			ra = a
-		default:
-			ra = &stringAddr{net, addr}
-		}
-		err := &OpError{
-			Op:   "dial",
-			Net:  net,
-			Addr: ra,
-			Err:  &timeoutError{},
-		}
-		return nil, err
-	case p := <-ch:
-		return p.Conn, p.error
-	}
-}
-
 type stringAddr struct {
 	net, addr string
 }
diff --git a/src/pkg/net/dial_gen.go b/src/pkg/net/dial_gen.go
new file mode 100644
index 0000000..0a3277d
--- /dev/null
+++ b/src/pkg/net/dial_gen.go
@@ -0,0 +1,61 @@
+// Copyright 2012 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.
+
+// +build windows plan9
+
+package net
+
+import (
+	"time"
+)
+
+// resolveAndDialChannel is the simple pure-Go implementation of
+// resolveAndDial, still used on operating systems where the deadline
+// hasn't been pushed down into the pollserver. (Plan 9 and some old
+// versions of Windows)
+func resolveAndDialChannel(net, addr string, localAddr Addr, deadline time.Time) (Conn, error) {
+	timeout := deadline.Sub(time.Now())
+	if timeout < 0 {
+		timeout = 0
+	}
+	t := time.NewTimer(timeout)
+	defer t.Stop()
+	type pair struct {
+		Conn
+		error
+	}
+	ch := make(chan pair, 1)
+	resolvedAddr := make(chan Addr, 1)
+	go func() {
+		ra, err := resolveAddr("dial", net, addr, noDeadline)
+		if err != nil {
+			ch <- pair{nil, err}
+			return
+		}
+		resolvedAddr <- ra // in case we need it for OpError
+		c, err := dial(net, addr, localAddr, ra, noDeadline)
+		ch <- pair{c, err}
+	}()
+	select {
+	case <-t.C:
+		// Try to use the real Addr in our OpError, if we resolved it
+		// before the timeout. Otherwise we just use stringAddr.
+		var ra Addr
+		select {
+		case a := <-resolvedAddr:
+			ra = a
+		default:
+			ra = &stringAddr{net, addr}
+		}
+		err := &OpError{
+			Op:   "dial",
+			Net:  net,
+			Addr: ra,
+			Err:  &timeoutError{},
+		}
+		return nil, err
+	case p := <-ch:
+		return p.Conn, p.error
+	}
+}
diff --git a/src/pkg/net/example_test.go b/src/pkg/net/example_test.go
index eefe84f..6f2f907 100644
--- a/src/pkg/net/example_test.go
+++ b/src/pkg/net/example_test.go
@@ -16,6 +16,7 @@ func ExampleListener() {
 	if err != nil {
 		log.Fatal(err)
 	}
+	defer l.Close()
 	for {
 		// Wait for a connection.
 		conn, err := l.Accept()
diff --git a/src/pkg/net/fd_plan9.go b/src/pkg/net/fd_plan9.go
index 1690879..e9527a3 100644
--- a/src/pkg/net/fd_plan9.go
+++ b/src/pkg/net/fd_plan9.go
@@ -23,10 +23,10 @@ var canCancelIO = true // used for testing current package
 func sysInit() {
 }
 
-func dialTimeout(net, addr string, timeout time.Duration) (Conn, error) {
+func resolveAndDial(net, addr string, localAddr Addr, deadline time.Time) (Conn, error) {
 	// On plan9, use the relatively inefficient
 	// goroutine-racing implementation.
-	return dialTimeoutRace(net, addr, timeout)
+	return resolveAndDialChannel(net, addr, localAddr, deadline)
 }
 
 func newFD(proto, name string, ctl, data *os.File, laddr, raddr Addr) *netFD {
diff --git a/src/pkg/net/fd_unix.go b/src/pkg/net/fd_unix.go
index 2b418a8..f52c98a 100644
--- a/src/pkg/net/fd_unix.go
+++ b/src/pkg/net/fd_unix.go
@@ -41,13 +41,12 @@ type netFD struct {
 	pd pollDesc
 }
 
-func dialTimeout(net, addr string, timeout time.Duration) (Conn, error) {
-	deadline := time.Now().Add(timeout)
+func resolveAndDial(net, addr string, localAddr Addr, deadline time.Time) (Conn, error) {
 	ra, err := resolveAddr("dial", net, addr, deadline)
 	if err != nil {
 		return nil, err
 	}
-	return dial(net, addr, noLocalAddr, ra, deadline)
+	return dial(net, addr, localAddr, ra, deadline)
 }
 
 func newFD(fd, family, sotype int, net string) (*netFD, error) {
diff --git a/src/pkg/net/fd_windows.go b/src/pkg/net/fd_windows.go
index 0e331b4..3a16d8a 100644
--- a/src/pkg/net/fd_windows.go
+++ b/src/pkg/net/fd_windows.go
@@ -54,18 +54,17 @@ func canUseConnectEx(net string) bool {
 	return syscall.LoadConnectEx() == nil
 }
 
-func dialTimeout(net, addr string, timeout time.Duration) (Conn, error) {
+func resolveAndDial(net, addr string, localAddr Addr, deadline time.Time) (Conn, error) {
 	if !canUseConnectEx(net) {
 		// Use the relatively inefficient goroutine-racing
 		// implementation of DialTimeout.
-		return dialTimeoutRace(net, addr, timeout)
+		return resolveAndDialChannel(net, addr, localAddr, deadline)
 	}
-	deadline := time.Now().Add(timeout)
 	ra, err := resolveAddr("dial", net, addr, deadline)
 	if err != nil {
 		return nil, err
 	}
-	return dial(net, addr, noLocalAddr, ra, deadline)
+	return dial(net, addr, localAddr, ra, deadline)
 }
 
 // Interface for all IO operations.
@@ -138,12 +137,18 @@ type resultSrv struct {
 	iocp syscall.Handle
 }
 
+func runtime_blockingSyscallHint()
+
 func (s *resultSrv) Run() {
 	var o *syscall.Overlapped
 	var key uint32
 	var r ioResult
 	for {
-		r.err = syscall.GetQueuedCompletionStatus(s.iocp, &(r.qty), &key, &o, syscall.INFINITE)
+		r.err = syscall.GetQueuedCompletionStatus(s.iocp, &(r.qty), &key, &o, 0)
+		if r.err == syscall.Errno(syscall.WAIT_TIMEOUT) && o == nil {
+			runtime_blockingSyscallHint()
+			r.err = syscall.GetQueuedCompletionStatus(s.iocp, &(r.qty), &key, &o, syscall.INFINITE)
+		}
 		switch {
 		case r.err == nil:
 			// Dequeued successfully completed IO packet.
diff --git a/src/pkg/net/file_windows.go b/src/pkg/net/file_windows.go
index c50c32e..ca2b9b2 100644
--- a/src/pkg/net/file_windows.go
+++ b/src/pkg/net/file_windows.go
@@ -9,16 +9,28 @@ import (
 	"syscall"
 )
 
+// FileConn returns a copy of the network connection corresponding to
+// the open file f.  It is the caller's responsibility to close f when
+// finished.  Closing c does not affect f, and closing f does not
+// affect c.
 func FileConn(f *os.File) (c Conn, err error) {
 	// TODO: Implement this
 	return nil, os.NewSyscallError("FileConn", syscall.EWINDOWS)
 }
 
+// FileListener returns a copy of the network listener corresponding
+// to the open file f.  It is the caller's responsibility to close l
+// when finished.  Closing l does not affect f, and closing f does not
+// affect l.
 func FileListener(f *os.File) (l Listener, err error) {
 	// TODO: Implement this
 	return nil, os.NewSyscallError("FileListener", syscall.EWINDOWS)
 }
 
+// FilePacketConn returns a copy of the packet network connection
+// corresponding to the open file f.  It is the caller's
+// responsibility to close f when finished.  Closing c does not affect
+// f, and closing f does not affect c.
 func FilePacketConn(f *os.File) (c PacketConn, err error) {
 	// TODO: Implement this
 	return nil, os.NewSyscallError("FilePacketConn", syscall.EWINDOWS)
diff --git a/src/pkg/net/http/example_test.go b/src/pkg/net/http/example_test.go
index eed3bee..bc60df7 100644
--- a/src/pkg/net/http/example_test.go
+++ b/src/pkg/net/http/example_test.go
@@ -51,11 +51,20 @@ func ExampleGet() {
 }
 
 func ExampleFileServer() {
-	// we use StripPrefix so that /tmpfiles/somefile will access /tmp/somefile
+	// Simple static webserver:
+	log.Fatal(http.ListenAndServe(":8080", http.FileServer(http.Dir("/usr/share/doc"))))
+}
+
+func ExampleFileServer_stripPrefix() {
+	// To serve a directory on disk (/tmp) under an alternate URL
+	// path (/tmpfiles/), use StripPrefix to modify the request
+	// URL's path before the FileServer sees it:
 	http.Handle("/tmpfiles/", http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("/tmp"))))
 }
 
 func ExampleStripPrefix() {
-	// we use StripPrefix so that /tmpfiles/somefile will access /tmp/somefile
+	// To serve a directory on disk (/tmp) under an alternate URL
+	// path (/tmpfiles/), use StripPrefix to modify the request
+	// URL's path before the FileServer sees it:
 	http.Handle("/tmpfiles/", http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("/tmp"))))
 }
diff --git a/src/pkg/net/http/request.go b/src/pkg/net/http/request.go
index dabb169..c1f862a 100644
--- a/src/pkg/net/http/request.go
+++ b/src/pkg/net/http/request.go
@@ -467,10 +467,42 @@ func (r *Request) SetBasicAuth(username, password string) {
 	r.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(s)))
 }
 
+// parseRequestLine parses "GET /foo HTTP/1.1" into its three parts.
+func parseRequestLine(line string) (method, requestURI, proto string, ok bool) {
+	s1 := strings.Index(line, " ")
+	s2 := strings.Index(line[s1+1:], " ")
+	if s1 < 0 || s2 < 0 {
+		return
+	}
+	s2 += s1 + 1
+	return line[:s1], line[s1+1 : s2], line[s2+1:], true
+}
+
+// TODO(bradfitz): use a sync.Cache when available
+var textprotoReaderCache = make(chan *textproto.Reader, 4)
+
+func newTextprotoReader(br *bufio.Reader) *textproto.Reader {
+	select {
+	case r := <-textprotoReaderCache:
+		r.R = br
+		return r
+	default:
+		return textproto.NewReader(br)
+	}
+}
+
+func putTextprotoReader(r *textproto.Reader) {
+	r.R = nil
+	select {
+	case textprotoReaderCache <- r:
+	default:
+	}
+}
+
 // ReadRequest reads and parses a request from b.
 func ReadRequest(b *bufio.Reader) (req *Request, err error) {
 
-	tp := textproto.NewReader(b)
+	tp := newTextprotoReader(b)
 	req = new(Request)
 
 	// First line: GET /index.html HTTP/1.0
@@ -479,18 +511,18 @@ func ReadRequest(b *bufio.Reader) (req *Request, err error) {
 		return nil, err
 	}
 	defer func() {
+		putTextprotoReader(tp)
 		if err == io.EOF {
 			err = io.ErrUnexpectedEOF
 		}
 	}()
 
-	var f []string
-	if f = strings.SplitN(s, " ", 3); len(f) < 3 {
+	var ok bool
+	req.Method, req.RequestURI, req.Proto, ok = parseRequestLine(s)
+	if !ok {
 		return nil, &badStringError{"malformed HTTP request", s}
 	}
-	req.Method, req.RequestURI, req.Proto = f[0], f[1], f[2]
 	rawurl := req.RequestURI
-	var ok bool
 	if req.ProtoMajor, req.ProtoMinor, ok = ParseHTTPVersion(req.Proto); !ok {
 		return nil, &badStringError{"malformed HTTP version", req.Proto}
 	}
diff --git a/src/pkg/net/http/response_test.go b/src/pkg/net/http/response_test.go
index 49836ce..02796e8 100644
--- a/src/pkg/net/http/response_test.go
+++ b/src/pkg/net/http/response_test.go
@@ -112,8 +112,8 @@ var respTests = []respTest{
 			ProtoMinor: 0,
 			Request:    dummyReq("GET"),
 			Header: Header{
-				"Connection":     {"close"}, // TODO(rsc): Delete?
-				"Content-Length": {"10"},    // TODO(rsc): Delete?
+				"Connection":     {"close"},
+				"Content-Length": {"10"},
 			},
 			Close:         true,
 			ContentLength: 10,
@@ -170,7 +170,7 @@ var respTests = []respTest{
 			Request:          dummyReq("GET"),
 			Header:           Header{},
 			Close:            false,
-			ContentLength:    -1, // TODO(rsc): Fix?
+			ContentLength:    -1,
 			TransferEncoding: []string{"chunked"},
 		},
 
diff --git a/src/pkg/net/http/serve_test.go b/src/pkg/net/http/serve_test.go
index 5adde54..102f489 100644
--- a/src/pkg/net/http/serve_test.go
+++ b/src/pkg/net/http/serve_test.go
@@ -10,6 +10,7 @@ import (
 	"bufio"
 	"bytes"
 	"crypto/tls"
+	"errors"
 	"fmt"
 	"io"
 	"io/ioutil"
@@ -64,10 +65,39 @@ func (a dummyAddr) String() string {
 	return string(a)
 }
 
+type noopConn struct{}
+
+func (noopConn) LocalAddr() net.Addr                { return dummyAddr("local-addr") }
+func (noopConn) RemoteAddr() net.Addr               { return dummyAddr("remote-addr") }
+func (noopConn) SetDeadline(t time.Time) error      { return nil }
+func (noopConn) SetReadDeadline(t time.Time) error  { return nil }
+func (noopConn) SetWriteDeadline(t time.Time) error { return nil }
+
+type rwTestConn struct {
+	io.Reader
+	io.Writer
+	noopConn
+
+	closeFunc func() error // called if non-nil
+	closec    chan bool    // else, if non-nil, send value to it on close
+}
+
+func (c *rwTestConn) Close() error {
+	if c.closeFunc != nil {
+		return c.closeFunc()
+	}
+	select {
+	case c.closec <- true:
+	default:
+	}
+	return nil
+}
+
 type testConn struct {
 	readBuf  bytes.Buffer
 	writeBuf bytes.Buffer
 	closec   chan bool // if non-nil, send value to it on close
+	noopConn
 }
 
 func (c *testConn) Read(b []byte) (int, error) {
@@ -86,26 +116,6 @@ func (c *testConn) Close() error {
 	return nil
 }
 
-func (c *testConn) LocalAddr() net.Addr {
-	return dummyAddr("local-addr")
-}
-
-func (c *testConn) RemoteAddr() net.Addr {
-	return dummyAddr("remote-addr")
-}
-
-func (c *testConn) SetDeadline(t time.Time) error {
-	return nil
-}
-
-func (c *testConn) SetReadDeadline(t time.Time) error {
-	return nil
-}
-
-func (c *testConn) SetWriteDeadline(t time.Time) error {
-	return nil
-}
-
 func TestConsumingBodyOnNextConn(t *testing.T) {
 	conn := new(testConn)
 	for i := 0; i < 2; i++ {
@@ -1447,6 +1457,198 @@ func TestOptions(t *testing.T) {
 	}
 }
 
+// Tests regarding the ordering of Write, WriteHeader, Header, and
+// Flush calls.  In Go 1.0, rw.WriteHeader immediately flushed the
+// (*response).header to the wire. In Go 1.1, the actual wire flush is
+// delayed, so we could maybe tack on a Content-Length and better
+// Content-Type after we see more (or all) of the output. To preserve
+// compatibility with Go 1, we need to be careful to track which
+// headers were live at the time of WriteHeader, so we write the same
+// ones, even if the handler modifies them (~erroneously) after the
+// first Write.
+func TestHeaderToWire(t *testing.T) {
+	req := []byte(strings.Replace(`GET / HTTP/1.1
+Host: golang.org
+
+`, "\n", "\r\n", -1))
+
+	tests := []struct {
+		name    string
+		handler func(ResponseWriter, *Request)
+		check   func(output string) error
+	}{
+		{
+			name: "write without Header",
+			handler: func(rw ResponseWriter, r *Request) {
+				rw.Write([]byte("hello world"))
+			},
+			check: func(got string) error {
+				if !strings.Contains(got, "Content-Length:") {
+					return errors.New("no content-length")
+				}
+				if !strings.Contains(got, "Content-Type: text/plain") {
+					return errors.New("no content-length")
+				}
+				return nil
+			},
+		},
+		{
+			name: "Header mutation before write",
+			handler: func(rw ResponseWriter, r *Request) {
+				h := rw.Header()
+				h.Set("Content-Type", "some/type")
+				rw.Write([]byte("hello world"))
+				h.Set("Too-Late", "bogus")
+			},
+			check: func(got string) error {
+				if !strings.Contains(got, "Content-Length:") {
+					return errors.New("no content-length")
+				}
+				if !strings.Contains(got, "Content-Type: some/type") {
+					return errors.New("wrong content-type")
+				}
+				if strings.Contains(got, "Too-Late") {
+					return errors.New("don't want too-late header")
+				}
+				return nil
+			},
+		},
+		{
+			name: "write then useless Header mutation",
+			handler: func(rw ResponseWriter, r *Request) {
+				rw.Write([]byte("hello world"))
+				rw.Header().Set("Too-Late", "Write already wrote headers")
+			},
+			check: func(got string) error {
+				if strings.Contains(got, "Too-Late") {
+					return errors.New("header appeared from after WriteHeader")
+				}
+				return nil
+			},
+		},
+		{
+			name: "flush then write",
+			handler: func(rw ResponseWriter, r *Request) {
+				rw.(Flusher).Flush()
+				rw.Write([]byte("post-flush"))
+				rw.Header().Set("Too-Late", "Write already wrote headers")
+			},
+			check: func(got string) error {
+				if !strings.Contains(got, "Transfer-Encoding: chunked") {
+					return errors.New("not chunked")
+				}
+				if strings.Contains(got, "Too-Late") {
+					return errors.New("header appeared from after WriteHeader")
+				}
+				return nil
+			},
+		},
+		{
+			name: "header then flush",
+			handler: func(rw ResponseWriter, r *Request) {
+				rw.Header().Set("Content-Type", "some/type")
+				rw.(Flusher).Flush()
+				rw.Write([]byte("post-flush"))
+				rw.Header().Set("Too-Late", "Write already wrote headers")
+			},
+			check: func(got string) error {
+				if !strings.Contains(got, "Transfer-Encoding: chunked") {
+					return errors.New("not chunked")
+				}
+				if strings.Contains(got, "Too-Late") {
+					return errors.New("header appeared from after WriteHeader")
+				}
+				if !strings.Contains(got, "Content-Type: some/type") {
+					return errors.New("wrong content-length")
+				}
+				return nil
+			},
+		},
+		{
+			name: "sniff-on-first-write content-type",
+			handler: func(rw ResponseWriter, r *Request) {
+				rw.Write([]byte("<html><head></head><body>some html</body></html>"))
+				rw.Header().Set("Content-Type", "x/wrong")
+			},
+			check: func(got string) error {
+				if !strings.Contains(got, "Content-Type: text/html") {
+					return errors.New("wrong content-length; want html")
+				}
+				return nil
+			},
+		},
+		{
+			name: "explicit content-type wins",
+			handler: func(rw ResponseWriter, r *Request) {
+				rw.Header().Set("Content-Type", "some/type")
+				rw.Write([]byte("<html><head></head><body>some html</body></html>"))
+			},
+			check: func(got string) error {
+				if !strings.Contains(got, "Content-Type: some/type") {
+					return errors.New("wrong content-length; want html")
+				}
+				return nil
+			},
+		},
+		{
+			name: "empty handler",
+			handler: func(rw ResponseWriter, r *Request) {
+			},
+			check: func(got string) error {
+				if !strings.Contains(got, "Content-Type: text/plain") {
+					return errors.New("wrong content-length; want text/plain")
+				}
+				if !strings.Contains(got, "Content-Length: 0") {
+					return errors.New("want 0 content-length")
+				}
+				return nil
+			},
+		},
+		{
+			name: "only Header, no write",
+			handler: func(rw ResponseWriter, r *Request) {
+				rw.Header().Set("Some-Header", "some-value")
+			},
+			check: func(got string) error {
+				if !strings.Contains(got, "Some-Header") {
+					return errors.New("didn't get header")
+				}
+				return nil
+			},
+		},
+		{
+			name: "WriteHeader call",
+			handler: func(rw ResponseWriter, r *Request) {
+				rw.WriteHeader(404)
+				rw.Header().Set("Too-Late", "some-value")
+			},
+			check: func(got string) error {
+				if !strings.Contains(got, "404") {
+					return errors.New("wrong status")
+				}
+				if strings.Contains(got, "Some-Header") {
+					return errors.New("shouldn't have seen Too-Late")
+				}
+				return nil
+			},
+		},
+	}
+	for _, tc := range tests {
+		var output bytes.Buffer
+		conn := &rwTestConn{
+			Reader: bytes.NewReader(req),
+			Writer: &output,
+			closec: make(chan bool, 1),
+		}
+		ln := &oneConnListener{conn: conn}
+		go Serve(ln, HandlerFunc(tc.handler))
+		<-conn.closec
+		if err := tc.check(output.String()); err != nil {
+			t.Errorf("%s: %v\nGot response:\n%s", tc.name, err, output.Bytes())
+		}
+	}
+}
+
 // goTimeout runs f, failing t if f takes more than ns to complete.
 func goTimeout(t *testing.T, d time.Duration, f func()) {
 	ch := make(chan bool, 2)
@@ -1635,7 +1837,9 @@ Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
 	res := []byte("Hello world!\n")
 
 	conn := &testConn{
-		closec: make(chan bool),
+		// testConn.Close will not push into the channel
+		// if it's full.
+		closec: make(chan bool, 1),
 	}
 	handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
 		rw.Header().Set("Content-Type", "text/html; charset=utf-8")
@@ -1651,3 +1855,146 @@ Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
 		<-conn.closec
 	}
 }
+
+// repeatReader reads content count times, then EOFs.
+type repeatReader struct {
+	content []byte
+	count   int
+	off     int
+}
+
+func (r *repeatReader) Read(p []byte) (n int, err error) {
+	if r.count <= 0 {
+		return 0, io.EOF
+	}
+	n = copy(p, r.content[r.off:])
+	r.off += n
+	if r.off == len(r.content) {
+		r.count--
+		r.off = 0
+	}
+	return
+}
+
+func BenchmarkServerFakeConnWithKeepAlive(b *testing.B) {
+	b.ReportAllocs()
+
+	req := []byte(strings.Replace(`GET / HTTP/1.1
+Host: golang.org
+Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.52 Safari/537.17
+Accept-Encoding: gzip,deflate,sdch
+Accept-Language: en-US,en;q=0.8
+Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
+
+`, "\n", "\r\n", -1))
+	res := []byte("Hello world!\n")
+
+	conn := &rwTestConn{
+		Reader: &repeatReader{content: req, count: b.N},
+		Writer: ioutil.Discard,
+		closec: make(chan bool, 1),
+	}
+	handled := 0
+	handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
+		handled++
+		rw.Header().Set("Content-Type", "text/html; charset=utf-8")
+		rw.Write(res)
+	})
+	ln := &oneConnListener{conn: conn}
+	go Serve(ln, handler)
+	<-conn.closec
+	if b.N != handled {
+		b.Errorf("b.N=%d but handled %d", b.N, handled)
+	}
+}
+
+// same as above, but representing the most simple possible request
+// and handler. Notably: the handler does not call rw.Header().
+func BenchmarkServerFakeConnWithKeepAliveLite(b *testing.B) {
+	b.ReportAllocs()
+
+	req := []byte(strings.Replace(`GET / HTTP/1.1
+Host: golang.org
+
+`, "\n", "\r\n", -1))
+	res := []byte("Hello world!\n")
+
+	conn := &rwTestConn{
+		Reader: &repeatReader{content: req, count: b.N},
+		Writer: ioutil.Discard,
+		closec: make(chan bool, 1),
+	}
+	handled := 0
+	handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
+		handled++
+		rw.Write(res)
+	})
+	ln := &oneConnListener{conn: conn}
+	go Serve(ln, handler)
+	<-conn.closec
+	if b.N != handled {
+		b.Errorf("b.N=%d but handled %d", b.N, handled)
+	}
+}
+
+const someResponse = "<html>some response</html>"
+
+// A Reponse that's just no bigger than 2KB, the buffer-before-chunking threshold.
+var response = bytes.Repeat([]byte(someResponse), 2<<10/len(someResponse))
+
+// Both Content-Type and Content-Length set. Should be no buffering.
+func BenchmarkServerHandlerTypeLen(b *testing.B) {
+	benchmarkHandler(b, HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Header().Set("Content-Type", "text/html")
+		w.Header().Set("Content-Length", strconv.Itoa(len(response)))
+		w.Write(response)
+	}))
+}
+
+// A Content-Type is set, but no length. No sniffing, but will count the Content-Length.
+func BenchmarkServerHandlerNoLen(b *testing.B) {
+	benchmarkHandler(b, HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Header().Set("Content-Type", "text/html")
+		w.Write(response)
+	}))
+}
+
+// A Content-Length is set, but the Content-Type will be sniffed.
+func BenchmarkServerHandlerNoType(b *testing.B) {
+	benchmarkHandler(b, HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Header().Set("Content-Length", strconv.Itoa(len(response)))
+		w.Write(response)
+	}))
+}
+
+// Neither a Content-Type or Content-Length, so sniffed and counted.
+func BenchmarkServerHandlerNoHeader(b *testing.B) {
+	benchmarkHandler(b, HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Write(response)
+	}))
+}
+
+func benchmarkHandler(b *testing.B, h Handler) {
+	b.ReportAllocs()
+	req := []byte(strings.Replace(`GET / HTTP/1.1
+Host: golang.org
+
+`, "\n", "\r\n", -1))
+	conn := &rwTestConn{
+		Reader: &repeatReader{content: req, count: b.N},
+		Writer: ioutil.Discard,
+		closec: make(chan bool, 1),
+	}
+	handled := 0
+	handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
+		handled++
+		h.ServeHTTP(rw, r)
+	})
+	ln := &oneConnListener{conn: conn}
+	go Serve(ln, handler)
+	<-conn.closec
+	if b.N != handled {
+		b.Errorf("b.N=%d but handled %d", b.N, handled)
+	}
+}
diff --git a/src/pkg/net/http/server.go b/src/pkg/net/http/server.go
index aee3229..4792bfb 100644
--- a/src/pkg/net/http/server.go
+++ b/src/pkg/net/http/server.go
@@ -4,9 +4,6 @@
 
 // HTTP server.  See RFC 2616.
 
-// TODO(rsc):
-//	logging
-
 package http
 
 import (
@@ -222,15 +219,28 @@ const bufferBeforeChunkingSize = 2048
 //
 // See the comment above (*response).Write for the entire write flow.
 type chunkWriter struct {
-	res         *response
-	header      Header // a deep copy of r.Header, once WriteHeader is called
-	wroteHeader bool   // whether the header's been sent
+	res *response
+
+	// header is either nil or a deep clone of res.handlerHeader
+	// at the time of res.WriteHeader, if res.WriteHeader is
+	// called and extra buffering is being done to calculate
+	// Content-Type and/or Content-Length.
+	header Header
+
+	// wroteHeader tells whether the header's been written to "the
+	// wire" (or rather: w.conn.buf). this is unlike
+	// (*response).wroteHeader, which tells only whether it was
+	// logically written.
+	wroteHeader bool
 
 	// set by the writeHeader method:
 	chunking bool // using chunked transfer encoding for reply body
 }
 
-var crlf = []byte("\r\n")
+var (
+	crlf       = []byte("\r\n")
+	colonSpace = []byte(": ")
+)
 
 func (cw *chunkWriter) Write(p []byte) (n int, err error) {
 	if !cw.wroteHeader {
@@ -280,13 +290,15 @@ type response struct {
 	wroteContinue bool     // 100 Continue response was written
 
 	w  *bufio.Writer // buffers output in chunks to chunkWriter
-	cw *chunkWriter
+	cw chunkWriter
+	sw *switchWriter // of the bufio.Writer, for return to putBufioWriter
 
 	// handlerHeader is the Header that Handlers get access to,
 	// which may be retained and mutated even after WriteHeader.
 	// handlerHeader is copied into cw.header at WriteHeader
 	// time, and privately mutated thereafter.
 	handlerHeader Header
+	calledHeader  bool // handler accessed handlerHeader via Header
 
 	written       int64 // number of bytes written in body
 	contentLength int64 // explicitly-declared Content-Length; or -1
@@ -381,7 +393,7 @@ func (srv *Server) newConn(rwc net.Conn) (c *conn, err error) {
 	c.sr = liveSwitchReader{r: c.rwc}
 	c.lr = io.LimitReader(&c.sr, noLimit).(*io.LimitedReader)
 	br, sr := newBufioReader(c.lr)
-	bw, sw := newBufioWriter(c.rwc)
+	bw, sw := newBufioWriterSize(c.rwc, 4<<10)
 	c.buf = bufio.NewReadWriter(br, bw)
 	c.bufswr = sr
 	c.bufsww = sw
@@ -402,10 +414,21 @@ type bufioWriterPair struct {
 
 // TODO: use a sync.Cache instead
 var (
-	bufioReaderCache = make(chan bufioReaderPair, 4)
-	bufioWriterCache = make(chan bufioWriterPair, 4)
+	bufioReaderCache   = make(chan bufioReaderPair, 4)
+	bufioWriterCache2k = make(chan bufioWriterPair, 4)
+	bufioWriterCache4k = make(chan bufioWriterPair, 4)
 )
 
+func bufioWriterCache(size int) chan bufioWriterPair {
+	switch size {
+	case 2 << 10:
+		return bufioWriterCache2k
+	case 4 << 10:
+		return bufioWriterCache4k
+	}
+	return nil
+}
+
 func newBufioReader(r io.Reader) (*bufio.Reader, *switchReader) {
 	select {
 	case p := <-bufioReaderCache:
@@ -429,14 +452,14 @@ func putBufioReader(br *bufio.Reader, sr *switchReader) {
 	}
 }
 
-func newBufioWriter(w io.Writer) (*bufio.Writer, *switchWriter) {
+func newBufioWriterSize(w io.Writer, size int) (*bufio.Writer, *switchWriter) {
 	select {
-	case p := <-bufioWriterCache:
+	case p := <-bufioWriterCache(size):
 		p.sw.Writer = w
 		return p.bw, p.sw
 	default:
 		sw := &switchWriter{w}
-		return bufio.NewWriter(sw), sw
+		return bufio.NewWriterSize(sw, size), sw
 	}
 }
 
@@ -454,7 +477,7 @@ func putBufioWriter(bw *bufio.Writer, sw *switchWriter) {
 	}
 	sw.Writer = nil
 	select {
-	case bufioWriterCache <- bufioWriterPair{bw, sw}:
+	case bufioWriterCache(bw.Available()) <- bufioWriterPair{bw, sw}:
 	default:
 	}
 }
@@ -537,14 +560,20 @@ func (c *conn) readRequest() (w *response, err error) {
 		req:           req,
 		handlerHeader: make(Header),
 		contentLength: -1,
-		cw:            new(chunkWriter),
 	}
 	w.cw.res = w
-	w.w = bufio.NewWriterSize(w.cw, bufferBeforeChunkingSize)
+	w.w, w.sw = newBufioWriterSize(&w.cw, bufferBeforeChunkingSize)
 	return w, nil
 }
 
 func (w *response) Header() Header {
+	if w.cw.header == nil && w.wroteHeader && !w.cw.wroteHeader {
+		// Accessing the header between logically writing it
+		// and physically writing it means we need to allocate
+		// a clone to snapshot the logically written state.
+		w.cw.header = w.handlerHeader.clone()
+	}
+	w.calledHeader = true
 	return w.handlerHeader
 }
 
@@ -571,15 +600,48 @@ func (w *response) WriteHeader(code int) {
 	w.wroteHeader = true
 	w.status = code
 
-	w.cw.header = w.handlerHeader.clone()
+	if w.calledHeader && w.cw.header == nil {
+		w.cw.header = w.handlerHeader.clone()
+	}
 
-	if cl := w.cw.header.get("Content-Length"); cl != "" {
+	if cl := w.handlerHeader.get("Content-Length"); cl != "" {
 		v, err := strconv.ParseInt(cl, 10, 64)
 		if err == nil && v >= 0 {
 			w.contentLength = v
 		} else {
 			log.Printf("http: invalid Content-Length of %q", cl)
-			w.cw.header.Del("Content-Length")
+			w.handlerHeader.Del("Content-Length")
+		}
+	}
+}
+
+// extraHeader is the set of headers sometimes added by chunkWriter.writeHeader.
+// This type is used to avoid extra allocations from cloning and/or populating
+// the response Header map and all its 1-element slices.
+type extraHeader struct {
+	contentType      string
+	contentLength    string
+	connection       string
+	date             string
+	transferEncoding string
+}
+
+// Sorted the same as extraHeader.Write's loop.
+var extraHeaderKeys = [][]byte{
+	[]byte("Content-Type"), []byte("Content-Length"),
+	[]byte("Connection"), []byte("Date"), []byte("Transfer-Encoding"),
+}
+
+// The value receiver, despite copying 5 strings to the stack,
+// prevents an extra allocation. The escape analysis isn't smart
+// enough to realize this doesn't mutate h.
+func (h extraHeader) Write(w io.Writer) {
+	for i, v := range []string{h.contentType, h.contentLength, h.connection, h.date, h.transferEncoding} {
+		if v != "" {
+			w.Write(extraHeaderKeys[i])
+			w.Write(colonSpace)
+			io.WriteString(w, v)
+			w.Write(crlf)
 		}
 	}
 }
@@ -599,23 +661,47 @@ func (cw *chunkWriter) writeHeader(p []byte) {
 	cw.wroteHeader = true
 
 	w := cw.res
-	code := w.status
-	done := w.handlerDone
+
+	// header is written out to w.conn.buf below. Depending on the
+	// state of the handler, we either own the map or not. If we
+	// don't own it, the exclude map is created lazily for
+	// WriteSubset to remove headers. The setHeader struct holds
+	// headers we need to add.
+	header := cw.header
+	owned := header != nil
+	if !owned {
+		header = w.handlerHeader
+	}
+	var excludeHeader map[string]bool
+	delHeader := func(key string) {
+		if owned {
+			header.Del(key)
+			return
+		}
+		if _, ok := header[key]; !ok {
+			return
+		}
+		if excludeHeader == nil {
+			excludeHeader = make(map[string]bool)
+		}
+		excludeHeader[key] = true
+	}
+	var setHeader extraHeader
 
 	// If the handler is done but never sent a Content-Length
 	// response header and this is our first (and last) write, set
 	// it, even to zero. This helps HTTP/1.0 clients keep their
 	// "keep-alive" connections alive.
-	if done && cw.header.get("Content-Length") == "" && w.req.Method != "HEAD" {
+	if w.handlerDone && header.get("Content-Length") == "" && w.req.Method != "HEAD" {
 		w.contentLength = int64(len(p))
-		cw.header.Set("Content-Length", strconv.Itoa(len(p)))
+		setHeader.contentLength = strconv.Itoa(len(p))
 	}
 
 	// If this was an HTTP/1.0 request with keep-alive and we sent a
 	// Content-Length back, we can make this a keep-alive response ...
 	if w.req.wantsHttp10KeepAlive() {
-		sentLength := cw.header.get("Content-Length") != ""
-		if sentLength && cw.header.get("Connection") == "keep-alive" {
+		sentLength := header.get("Content-Length") != ""
+		if sentLength && header.get("Connection") == "keep-alive" {
 			w.closeAfterReply = false
 		}
 	}
@@ -624,15 +710,15 @@ func (cw *chunkWriter) writeHeader(p []byte) {
 	hasCL := w.contentLength != -1
 
 	if w.req.wantsHttp10KeepAlive() && (w.req.Method == "HEAD" || hasCL) {
-		_, connectionHeaderSet := cw.header["Connection"]
+		_, connectionHeaderSet := header["Connection"]
 		if !connectionHeaderSet {
-			cw.header.Set("Connection", "keep-alive")
+			setHeader.connection = "keep-alive"
 		}
 	} else if !w.req.ProtoAtLeast(1, 1) || w.req.wantsClose() {
 		w.closeAfterReply = true
 	}
 
-	if cw.header.get("Connection") == "close" {
+	if header.get("Connection") == "close" {
 		w.closeAfterReply = true
 	}
 
@@ -646,49 +732,49 @@ func (cw *chunkWriter) writeHeader(p []byte) {
 			n, _ := io.CopyN(ioutil.Discard, w.req.Body, maxPostHandlerReadBytes+1)
 			if n >= maxPostHandlerReadBytes {
 				w.requestTooLarge()
-				cw.header.Set("Connection", "close")
+				delHeader("Connection")
+				setHeader.connection = "close"
 			} else {
 				w.req.Body.Close()
 			}
 		}
 	}
 
+	code := w.status
 	if code == StatusNotModified {
 		// Must not have body.
-		for _, header := range []string{"Content-Type", "Content-Length", "Transfer-Encoding"} {
-			// RFC 2616 section 10.3.5: "the response MUST NOT include other entity-headers"
-			if cw.header.get(header) != "" {
-				cw.header.Del(header)
-			}
+		// RFC 2616 section 10.3.5: "the response MUST NOT include other entity-headers"
+		for _, k := range []string{"Content-Type", "Content-Length", "Transfer-Encoding"} {
+			delHeader(k)
 		}
 	} else {
 		// If no content type, apply sniffing algorithm to body.
-		if cw.header.get("Content-Type") == "" && w.req.Method != "HEAD" {
-			cw.header.Set("Content-Type", DetectContentType(p))
+		if header.get("Content-Type") == "" && w.req.Method != "HEAD" {
+			setHeader.contentType = DetectContentType(p)
 		}
 	}
 
-	if _, ok := cw.header["Date"]; !ok {
-		cw.header.Set("Date", time.Now().UTC().Format(TimeFormat))
+	if _, ok := header["Date"]; !ok {
+		setHeader.date = time.Now().UTC().Format(TimeFormat)
 	}
 
-	te := cw.header.get("Transfer-Encoding")
+	te := header.get("Transfer-Encoding")
 	hasTE := te != ""
 	if hasCL && hasTE && te != "identity" {
 		// TODO: return an error if WriteHeader gets a return parameter
 		// For now just ignore the Content-Length.
 		log.Printf("http: WriteHeader called with both Transfer-Encoding of %q and a Content-Length of %d",
 			te, w.contentLength)
-		cw.header.Del("Content-Length")
+		delHeader("Content-Length")
 		hasCL = false
 	}
 
 	if w.req.Method == "HEAD" || code == StatusNotModified {
 		// do nothing
 	} else if code == StatusNoContent {
-		cw.header.Del("Transfer-Encoding")
+		delHeader("Transfer-Encoding")
 	} else if hasCL {
-		cw.header.Del("Transfer-Encoding")
+		delHeader("Transfer-Encoding")
 	} else if w.req.ProtoAtLeast(1, 1) {
 		// HTTP/1.1 or greater: use chunked transfer encoding
 		// to avoid closing the connection at EOF.
@@ -696,29 +782,63 @@ func (cw *chunkWriter) writeHeader(p []byte) {
 		// might have set.  Deal with that as need arises once we have a valid
 		// use case.
 		cw.chunking = true
-		cw.header.Set("Transfer-Encoding", "chunked")
+		setHeader.transferEncoding = "chunked"
 	} else {
 		// HTTP version < 1.1: cannot do chunked transfer
 		// encoding and we don't know the Content-Length so
 		// signal EOF by closing connection.
 		w.closeAfterReply = true
-		cw.header.Del("Transfer-Encoding") // in case already set
+		delHeader("Transfer-Encoding") // in case already set
 	}
 
 	// Cannot use Content-Length with non-identity Transfer-Encoding.
 	if cw.chunking {
-		cw.header.Del("Content-Length")
+		delHeader("Content-Length")
 	}
 	if !w.req.ProtoAtLeast(1, 0) {
 		return
 	}
 
 	if w.closeAfterReply && !hasToken(cw.header.get("Connection"), "close") {
-		cw.header.Set("Connection", "close")
+		delHeader("Connection")
+		setHeader.connection = "close"
 	}
 
+	io.WriteString(w.conn.buf, statusLine(w.req, code))
+	cw.header.WriteSubset(w.conn.buf, excludeHeader)
+	setHeader.Write(w.conn.buf)
+	w.conn.buf.Write(crlf)
+}
+
+// statusLines is a cache of Status-Line strings, keyed by code (for
+// HTTP/1.1) or negative code (for HTTP/1.0). This is faster than a
+// map keyed by struct of two fields. This map's max size is bounded
+// by 2*len(statusText), two protocol types for each known official
+// status code in the statusText map.
+var (
+	statusMu    sync.RWMutex
+	statusLines = make(map[int]string)
+)
+
+// statusLine returns a response Status-Line (RFC 2616 Section 6.1)
+// for the given request and response status code.
+func statusLine(req *Request, code int) string {
+	// Fast path:
+	key := code
+	proto11 := req.ProtoAtLeast(1, 1)
+	if !proto11 {
+		key = -key
+	}
+	statusMu.RLock()
+	line, ok := statusLines[key]
+	statusMu.RUnlock()
+	if ok {
+		return line
+	}
+
+	// Slow path:
 	proto := "HTTP/1.0"
-	if w.req.ProtoAtLeast(1, 1) {
+	if proto11 {
 		proto = "HTTP/1.1"
 	}
 	codestring := strconv.Itoa(code)
@@ -726,9 +846,13 @@ func (cw *chunkWriter) writeHeader(p []byte) {
 	if !ok {
 		text = "status code " + codestring
 	}
-	io.WriteString(w.conn.buf, proto+" "+codestring+" "+text+"\r\n")
-	cw.header.Write(w.conn.buf)
-	w.conn.buf.Write(crlf)
+	line = proto + " " + codestring + " " + text + "\r\n"
+	if ok {
+		statusMu.Lock()
+		defer statusMu.Unlock()
+		statusLines[key] = line
+	}
+	return line
 }
 
 // bodyAllowed returns true if a Write is allowed for this response type.
@@ -802,6 +926,7 @@ func (w *response) finishRequest() {
 	}
 
 	w.w.Flush()
+	putBufioWriter(w.w, w.sw)
 	w.cw.close()
 	w.conn.buf.Flush()
 
diff --git a/src/pkg/net/http/transfer.go b/src/pkg/net/http/transfer.go
index 43c6023..53569bc 100644
--- a/src/pkg/net/http/transfer.go
+++ b/src/pkg/net/http/transfer.go
@@ -328,12 +328,13 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err error) {
 	switch {
 	case chunked(t.TransferEncoding):
 		if noBodyExpected(t.RequestMethod) {
-			t.Body = &body{Reader: io.LimitReader(r, 0), closing: t.Close}
+			t.Body = &body{Reader: eofReader, closing: t.Close}
 		} else {
 			t.Body = &body{Reader: newChunkedReader(r), hdr: msg, r: r, closing: t.Close}
 		}
-	case realLength >= 0:
-		// TODO: limit the Content-Length. This is an easy DoS vector.
+	case realLength == 0:
+		t.Body = &body{Reader: eofReader, closing: t.Close}
+	case realLength > 0:
 		t.Body = &body{Reader: io.LimitReader(r, realLength), closing: t.Close}
 	default:
 		// realLength < 0, i.e. "Content-Length" not mentioned in header
@@ -342,7 +343,7 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err error) {
 			t.Body = &body{Reader: r, closing: t.Close}
 		} else {
 			// Persistent connection (i.e. HTTP/1.1)
-			t.Body = &body{Reader: io.LimitReader(r, 0), closing: t.Close}
+			t.Body = &body{Reader: eofReader, closing: t.Close}
 		}
 	}
 
@@ -612,30 +613,26 @@ func (b *body) Close() error {
 	if b.closed {
 		return nil
 	}
-	defer func() {
-		b.closed = true
-	}()
-	if b.hdr == nil && b.closing {
+	var err error
+	switch {
+	case b.hdr == nil && b.closing:
 		// no trailer and closing the connection next.
 		// no point in reading to EOF.
-		return nil
-	}
-
-	// In a server request, don't continue reading from the client
-	// if we've already hit the maximum body size set by the
-	// handler. If this is set, that also means the TCP connection
-	// is about to be closed, so getting to the next HTTP request
-	// in the stream is not necessary.
-	if b.res != nil && b.res.requestBodyLimitHit {
-		return nil
-	}
-
-	// Fully consume the body, which will also lead to us reading
-	// the trailer headers after the body, if present.
-	if _, err := io.Copy(ioutil.Discard, b); err != nil {
-		return err
+	case b.res != nil && b.res.requestBodyLimitHit:
+		// In a server request, don't continue reading from the client
+		// if we've already hit the maximum body size set by the
+		// handler. If this is set, that also means the TCP connection
+		// is about to be closed, so getting to the next HTTP request
+		// in the stream is not necessary.
+	case b.Reader == eofReader:
+		// Nothing to read. No need to io.Copy from it.
+	default:
+		// Fully consume the body, which will also lead to us reading
+		// the trailer headers after the body, if present.
+		_, err = io.Copy(ioutil.Discard, b)
 	}
-	return nil
+	b.closed = true
+	return err
 }
 
 // parseContentLength trims whitespace from s and returns -1 if no value
diff --git a/src/pkg/net/http/transport.go b/src/pkg/net/http/transport.go
index 08ced2c..4cd0533 100644
--- a/src/pkg/net/http/transport.go
+++ b/src/pkg/net/http/transport.go
@@ -58,7 +58,7 @@ type Transport struct {
 	// Dial specifies the dial function for creating TCP
 	// connections.
 	// If Dial is nil, net.Dial is used.
-	Dial func(net, addr string) (c net.Conn, err error)
+	Dial func(network, addr string) (net.Conn, error)
 
 	// TLSClientConfig specifies the TLS configuration to use with
 	// tls.Client. If nil, the default configuration is used.
@@ -686,6 +686,14 @@ func (pc *persistConn) readLoop() {
 		var resp *Response
 		if err == nil {
 			resp, err = ReadResponse(pc.br, rc.req)
+			if err == nil && resp.StatusCode == 100 {
+				// Skip any 100-continue for now.
+				// TODO(bradfitz): if rc.req had "Expect: 100-continue",
+				// actually block the request body write and signal the
+				// writeLoop now to begin sending it. (Issue 2184) For now we
+				// eat it, since we're never expecting one.
+				resp, err = ReadResponse(pc.br, rc.req)
+			}
 		}
 		hasBody := resp != nil && rc.req.Method != "HEAD" && resp.ContentLength != 0
 
@@ -707,7 +715,10 @@ func (pc *persistConn) readLoop() {
 			resp.Body = &bodyEOFSignal{body: resp.Body}
 		}
 
-		if err != nil || resp.Close || rc.req.Close {
+		if err != nil || resp.Close || rc.req.Close || resp.StatusCode <= 199 {
+			// Don't do keep-alive on error if either party requested a close
+			// or we get an unexpected informational (1xx) response.
+			// StatusCode 100 is already handled above.
 			alive = false
 		}
 
diff --git a/src/pkg/net/http/transport_test.go b/src/pkg/net/http/transport_test.go
index 4bb711b..9f64a6e 100644
--- a/src/pkg/net/http/transport_test.go
+++ b/src/pkg/net/http/transport_test.go
@@ -7,6 +7,7 @@
 package http_test
 
 import (
+	"bufio"
 	"bytes"
 	"compress/gzip"
 	"crypto/rand"
@@ -950,14 +951,28 @@ func TestTransportConcurrency(t *testing.T) {
 		fmt.Fprintf(w, "%v", r.FormValue("echo"))
 	}))
 	defer ts.Close()
-	tr := &Transport{}
+
+	var wg sync.WaitGroup
+	wg.Add(numReqs)
+
+	tr := &Transport{
+		Dial: func(netw, addr string) (c net.Conn, err error) {
+			// Due to the Transport's "socket late
+			// binding" (see idleConnCh in transport.go),
+			// the numReqs HTTP requests below can finish
+			// with a dial still outstanding.  So count
+			// our dials as work too so the leak checker
+			// doesn't complain at us.
+			wg.Add(1)
+			defer wg.Done()
+			return net.Dial(netw, addr)
+		},
+	}
 	defer tr.CloseIdleConnections()
 	c := &Client{Transport: tr}
 	reqs := make(chan string)
 	defer close(reqs)
 
-	var wg sync.WaitGroup
-	wg.Add(numReqs)
 	for i := 0; i < maxProcs*2; i++ {
 		go func() {
 			for req := range reqs {
@@ -1385,6 +1400,114 @@ func TestTransportSocketLateBinding(t *testing.T) {
 	dialGate <- true
 }
 
+// Issue 2184
+func TestTransportReading100Continue(t *testing.T) {
+	defer afterTest(t)
+
+	const numReqs = 5
+	reqBody := func(n int) string { return fmt.Sprintf("request body %d", n) }
+	reqID := func(n int) string { return fmt.Sprintf("REQ-ID-%d", n) }
+
+	send100Response := func(w *io.PipeWriter, r *io.PipeReader) {
+		defer w.Close()
+		defer r.Close()
+		br := bufio.NewReader(r)
+		n := 0
+		for {
+			n++
+			req, err := ReadRequest(br)
+			if err == io.EOF {
+				return
+			}
+			if err != nil {
+				t.Error(err)
+				return
+			}
+			slurp, err := ioutil.ReadAll(req.Body)
+			if err != nil {
+				t.Errorf("Server request body slurp: %v", err)
+				return
+			}
+			id := req.Header.Get("Request-Id")
+			resCode := req.Header.Get("X-Want-Response-Code")
+			if resCode == "" {
+				resCode = "100 Continue"
+				if string(slurp) != reqBody(n) {
+					t.Errorf("Server got %q, %v; want %q", slurp, err, reqBody(n))
+				}
+			}
+			body := fmt.Sprintf("Response number %d", n)
+			v := []byte(strings.Replace(fmt.Sprintf(`HTTP/1.1 %s
+Date: Thu, 28 Feb 2013 17:55:41 GMT
+
+HTTP/1.1 200 OK
+Content-Type: text/html
+Echo-Request-Id: %s
+Content-Length: %d
+
+%s`, resCode, id, len(body), body), "\n", "\r\n", -1))
+			w.Write(v)
+			if id == reqID(numReqs) {
+				return
+			}
+		}
+
+	}
+
+	tr := &Transport{
+		Dial: func(n, addr string) (net.Conn, error) {
+			sr, sw := io.Pipe() // server read/write
+			cr, cw := io.Pipe() // client read/write
+			conn := &rwTestConn{
+				Reader: cr,
+				Writer: sw,
+				closeFunc: func() error {
+					sw.Close()
+					cw.Close()
+					return nil
+				},
+			}
+			go send100Response(cw, sr)
+			return conn, nil
+		},
+		DisableKeepAlives: false,
+	}
+	defer tr.CloseIdleConnections()
+	c := &Client{Transport: tr}
+
+	testResponse := func(req *Request, name string, wantCode int) {
+		res, err := c.Do(req)
+		if err != nil {
+			t.Fatalf("%s: Do: %v", name, err)
+		}
+		if res.StatusCode != wantCode {
+			t.Fatalf("%s: Response Statuscode=%d; want %d", name, res.StatusCode, wantCode)
+		}
+		if id, idBack := req.Header.Get("Request-Id"), res.Header.Get("Echo-Request-Id"); id != "" && id != idBack {
+			t.Errorf("%s: response id %q != request id %q", name, idBack, id)
+		}
+		_, err = ioutil.ReadAll(res.Body)
+		if err != nil {
+			t.Fatalf("%s: Slurp error: %v", name, err)
+		}
+	}
+
+	// Few 100 responses, making sure we're not off-by-one.
+	for i := 1; i <= numReqs; i++ {
+		req, _ := NewRequest("POST", "http://dummy.tld/", strings.NewReader(reqBody(i)))
+		req.Header.Set("Request-Id", reqID(i))
+		testResponse(req, fmt.Sprintf("100, %d/%d", i, numReqs), 200)
+	}
+
+	// And some other informational 1xx but non-100 responses, to test
+	// we return them but don't re-use the connection.
+	for i := 1; i <= numReqs; i++ {
+		req, _ := NewRequest("POST", "http://other.tld/", strings.NewReader(reqBody(i)))
+		req.Header.Set("X-Want-Response-Code", "123 Sesame Street")
+		testResponse(req, fmt.Sprintf("123, %d/%d", i, numReqs), 123)
+	}
+}
+
 type proxyFromEnvTest struct {
 	req     string // URL to fetch; blank means "http://example.com"
 	env     string
diff --git a/src/pkg/net/http/z_last_test.go b/src/pkg/net/http/z_last_test.go
index a80fb01..bf5e3f1 100644
--- a/src/pkg/net/http/z_last_test.go
+++ b/src/pkg/net/http/z_last_test.go
@@ -27,7 +27,11 @@ func interestingGoroutines() (gs []string) {
 			strings.Contains(stack, "created by net.startServer") ||
 			strings.Contains(stack, "created by testing.RunTests") ||
 			strings.Contains(stack, "closeWriteAndWait") ||
-			strings.Contains(stack, "testing.Main(") {
+			strings.Contains(stack, "testing.Main(") ||
+			// These only show up with GOTRACEBACK=2; Issue 5005 (comment 28)
+			strings.Contains(stack, "runtime.goexit") ||
+			strings.Contains(stack, "created by runtime.gc") ||
+			strings.Contains(stack, "runtime.MHeap_Scavenger") {
 			continue
 		}
 		gs = append(gs, stack)
@@ -65,8 +69,6 @@ func afterTest(t *testing.T) {
 	if testing.Short() {
 		return
 	}
-	buf := make([]byte, 1<<20)
-	var stacks string
 	var bad string
 	badSubstring := map[string]string{
 		").readLoop(":                                  "a Transport",
@@ -75,9 +77,10 @@ func afterTest(t *testing.T) {
 		"timeoutHandler":                               "a TimeoutHandler",
 		"net.(*netFD).connect(":                        "a timing out dial",
 	}
+	var stacks string
 	for i := 0; i < 4; i++ {
 		bad = ""
-		stacks = string(buf[:runtime.Stack(buf, true)])
+		stacks = strings.Join(interestingGoroutines(), "\n\n")
 		for substr, what := range badSubstring {
 			if strings.Contains(stacks, substr) {
 				bad = what
@@ -90,6 +93,5 @@ func afterTest(t *testing.T) {
 		// shutting down, so give it some time.
 		time.Sleep(250 * time.Millisecond)
 	}
-	gs := interestingGoroutines()
-	t.Errorf("Test appears to have leaked %s:\n%s", bad, strings.Join(gs, "\n\n"))
+	t.Errorf("Test appears to have leaked %s:\n%s", bad, stacks)
 }
diff --git a/src/pkg/net/interface_unix_test.go b/src/pkg/net/interface_unix_test.go
index 6dbd6e6..0a453c0 100644
--- a/src/pkg/net/interface_unix_test.go
+++ b/src/pkg/net/interface_unix_test.go
@@ -41,8 +41,11 @@ func (ti *testInterface) teardown() error {
 }
 
 func TestPointToPointInterface(t *testing.T) {
-	switch runtime.GOOS {
-	case "darwin":
+	if testing.Short() {
+		t.Skip("skipping test in short mode")
+	}
+	switch {
+	case runtime.GOOS == "darwin":
 		t.Skipf("skipping read test on %q", runtime.GOOS)
 	}
 	if os.Getuid() != 0 {
@@ -90,6 +93,9 @@ func TestPointToPointInterface(t *testing.T) {
 }
 
 func TestInterfaceArrivalAndDeparture(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping test in short mode")
+	}
 	if os.Getuid() != 0 {
 		t.Skip("skipping test; must be root")
 	}
diff --git a/src/pkg/net/ipraw_test.go b/src/pkg/net/ipraw_test.go
index 841b57a..6cdb5ab 100644
--- a/src/pkg/net/ipraw_test.go
+++ b/src/pkg/net/ipraw_test.go
@@ -14,12 +14,14 @@ import (
 	"time"
 )
 
-var resolveIPAddrTests = []struct {
+type resolveIPAddrTest struct {
 	net     string
 	litAddr string
 	addr    *IPAddr
 	err     error
-}{
+}
+
+var resolveIPAddrTests = []resolveIPAddrTest{
 	{"ip", "127.0.0.1", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
 	{"ip4", "127.0.0.1", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
 	{"ip4:icmp", "127.0.0.1", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
@@ -30,8 +32,6 @@ var resolveIPAddrTests = []struct {
 
 	{"ip", "::1%en0", &IPAddr{IP: ParseIP("::1"), Zone: "en0"}, nil},
 	{"ip6", "::1%911", &IPAddr{IP: ParseIP("::1"), Zone: "911"}, nil},
-	{"ip6", "fe80::1", &IPAddr{IP: ParseIP("fe80::1"), Zone: "name"}, nil},
-	{"ip6", "fe80::1", &IPAddr{IP: ParseIP("fe80::1"), Zone: "index"}, nil},
 
 	{"", "127.0.0.1", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil}, // Go 1.0 behavior
 	{"", "::1", &IPAddr{IP: ParseIP("::1")}, nil},           // Go 1.0 behavior
@@ -41,23 +41,18 @@ var resolveIPAddrTests = []struct {
 	{"tcp", "1.2.3.4:123", nil, UnknownNetworkError("tcp")},
 }
 
+func init() {
+	if ifi := loopbackInterface(); ifi != nil {
+		index := fmt.Sprintf("%v", ifi.Index)
+		resolveIPAddrTests = append(resolveIPAddrTests, []resolveIPAddrTest{
+			{"ip6", "fe80::1%" + ifi.Name, &IPAddr{IP: ParseIP("fe80::1"), Zone: zoneToString(ifi.Index)}, nil},
+			{"ip6", "fe80::1%" + index, &IPAddr{IP: ParseIP("fe80::1"), Zone: index}, nil},
+		}...)
+	}
+}
+
 func TestResolveIPAddr(t *testing.T) {
 	for _, tt := range resolveIPAddrTests {
-		if tt.addr != nil && (tt.addr.Zone == "name" || tt.addr.Zone == "index") {
-			ifi := loopbackInterface()
-			if ifi == nil {
-				continue
-			}
-			switch tt.addr.Zone {
-			case "name":
-				tt.litAddr += "%" + ifi.Name
-				tt.addr.Zone = zoneToString(ifi.Index)
-			case "index":
-				index := fmt.Sprintf("%v", ifi.Index)
-				tt.litAddr += "%" + index
-				tt.addr.Zone = index
-			}
-		}
 		addr, err := ResolveIPAddr(tt.net, tt.litAddr)
 		if err != tt.err {
 			t.Fatalf("ResolveIPAddr(%v, %v) failed: %v", tt.net, tt.litAddr, err)
diff --git a/src/pkg/net/iprawsock.go b/src/pkg/net/iprawsock.go
index 9d99e75..0be94eb 100644
--- a/src/pkg/net/iprawsock.go
+++ b/src/pkg/net/iprawsock.go
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Raw IP sockets
-
 package net
 
 // IPAddr represents the address of an IP end point.
diff --git a/src/pkg/net/iprawsock_plan9.go b/src/pkg/net/iprawsock_plan9.go
index 43a5eab..e62d116 100644
--- a/src/pkg/net/iprawsock_plan9.go
+++ b/src/pkg/net/iprawsock_plan9.go
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Raw IP sockets for Plan 9
-
 package net
 
 import (
@@ -76,7 +74,7 @@ func dialIP(netProto string, laddr, raddr *IPAddr, deadline time.Time) (*IPConn,
 }
 
 // ListenIP listens for incoming IP packets addressed to the local
-// address laddr.  The returned connection c's ReadFrom and WriteTo
+// address laddr.  The returned connection's ReadFrom and WriteTo
 // methods can be used to receive and send IP packets with per-packet
 // addressing.
 func ListenIP(netProto string, laddr *IPAddr) (*IPConn, error) {
diff --git a/src/pkg/net/iprawsock_posix.go b/src/pkg/net/iprawsock_posix.go
index 1bcaef9..caeeb46 100644
--- a/src/pkg/net/iprawsock_posix.go
+++ b/src/pkg/net/iprawsock_posix.go
@@ -4,8 +4,6 @@
 
 // +build darwin freebsd linux netbsd openbsd windows
 
-// Raw IP sockets for POSIX
-
 package net
 
 import (
@@ -51,8 +49,8 @@ func (a *IPAddr) toAddr() sockaddr {
 	return a
 }
 
-// IPConn is the implementation of the Conn and PacketConn
-// interfaces for IP network connections.
+// IPConn is the implementation of the Conn and PacketConn interfaces
+// for IP network connections.
 type IPConn struct {
 	conn
 }
@@ -116,12 +114,13 @@ func (c *IPConn) ReadMsgIP(b, oob []byte) (n, oobn, flags int, addr *IPAddr, err
 	return
 }
 
-// WriteToIP writes an IP packet to addr via c, copying the payload from b.
+// WriteToIP writes an IP packet to addr via c, copying the payload
+// from b.
 //
-// WriteToIP can be made to time out and return
-// an error with Timeout() == true after a fixed time limit;
-// see SetDeadline and SetWriteDeadline.
-// On packet-oriented connections, write timeouts are rare.
+// WriteToIP can be made to time out and return an error with
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetWriteDeadline.  On packet-oriented connections, write timeouts
+// are rare.
 func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (int, error) {
 	if !c.ok() {
 		return 0, syscall.EINVAL
@@ -159,8 +158,9 @@ func (c *IPConn) WriteMsgIP(b, oob []byte, addr *IPAddr) (n, oobn int, err error
 	return c.fd.WriteMsg(b, oob, sa)
 }
 
-// DialIP connects to the remote address raddr on the network protocol netProto,
-// which must be "ip", "ip4", or "ip6" followed by a colon and a protocol number or name.
+// DialIP connects to the remote address raddr on the network protocol
+// netProto, which must be "ip", "ip4", or "ip6" followed by a colon
+// and a protocol number or name.
 func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error) {
 	return dialIP(netProto, laddr, raddr, noDeadline)
 }
@@ -185,10 +185,10 @@ func dialIP(netProto string, laddr, raddr *IPAddr, deadline time.Time) (*IPConn,
 	return newIPConn(fd), nil
 }
 
-// ListenIP listens for incoming IP packets addressed to the
-// local address laddr.  The returned connection c's ReadFrom
-// and WriteTo methods can be used to receive and send IP
-// packets with per-packet addressing.
+// ListenIP listens for incoming IP packets addressed to the local
+// address laddr.  The returned connection's ReadFrom and WriteTo
+// methods can be used to receive and send IP packets with per-packet
+// addressing.
 func ListenIP(netProto string, laddr *IPAddr) (*IPConn, error) {
 	net, proto, err := parseNetwork(netProto)
 	if err != nil {
diff --git a/src/pkg/net/multicast_test.go b/src/pkg/net/multicast_test.go
index 1eb6a42..8ff02a3 100644
--- a/src/pkg/net/multicast_test.go
+++ b/src/pkg/net/multicast_test.go
@@ -93,7 +93,7 @@ var ipv6MulticastListenerTests = []struct {
 // port.
 func TestIPv6MulticastListener(t *testing.T) {
 	switch runtime.GOOS {
-	case "plan9", "solaris", "windows":
+	case "plan9", "solaris":
 		t.Skipf("skipping test on %q", runtime.GOOS)
 	}
 	if !supportsIPv6 {
diff --git a/src/pkg/net/server_test.go b/src/pkg/net/server_test.go
index c101ffe..9194a8e 100644
--- a/src/pkg/net/server_test.go
+++ b/src/pkg/net/server_test.go
@@ -402,7 +402,7 @@ func runDatagramConnClient(t *testing.T, net, laddr, taddr string, isEmpty bool)
 			t.Fatalf("Dial(%q, %q) failed: %v", net, taddr, err)
 		}
 	case "unixgram":
-		c, err = DialUnix(net, &UnixAddr{laddr, net}, &UnixAddr{taddr, net})
+		c, err = DialUnix(net, &UnixAddr{Name: laddr, Net: net}, &UnixAddr{Name: taddr, Net: net})
 		if err != nil {
 			t.Fatalf("DialUnix(%q, {%q, %q}) failed: %v", net, laddr, taddr, err)
 		}
diff --git a/src/pkg/net/smtp/auth.go b/src/pkg/net/smtp/auth.go
index d401e3c..3f1339e 100644
--- a/src/pkg/net/smtp/auth.go
+++ b/src/pkg/net/smtp/auth.go
@@ -54,7 +54,16 @@ func PlainAuth(identity, username, password, host string) Auth {
 
 func (a *plainAuth) Start(server *ServerInfo) (string, []byte, error) {
 	if !server.TLS {
-		return "", nil, errors.New("unencrypted connection")
+		advertised := false
+		for _, mechanism := range server.Auth {
+			if mechanism == "PLAIN" {
+				advertised = true
+				break
+			}
+		}
+		if !advertised {
+			return "", nil, errors.New("unencrypted connection")
+		}
 	}
 	if server.Name != a.host {
 		return "", nil, errors.New("wrong host name")
diff --git a/src/pkg/net/smtp/smtp_test.go b/src/pkg/net/smtp/smtp_test.go
index 8317428..c190b32 100644
--- a/src/pkg/net/smtp/smtp_test.go
+++ b/src/pkg/net/smtp/smtp_test.go
@@ -57,6 +57,41 @@ testLoop:
 	}
 }
 
+func TestAuthPlain(t *testing.T) {
+	auth := PlainAuth("foo", "bar", "baz", "servername")
+
+	tests := []struct {
+		server *ServerInfo
+		err    string
+	}{
+		{
+			server: &ServerInfo{Name: "servername", TLS: true},
+		},
+		{
+			// Okay; explicitly advertised by server.
+			server: &ServerInfo{Name: "servername", Auth: []string{"PLAIN"}},
+		},
+		{
+			server: &ServerInfo{Name: "servername", Auth: []string{"CRAM-MD5"}},
+			err:    "unencrypted connection",
+		},
+		{
+			server: &ServerInfo{Name: "attacker", TLS: true},
+			err:    "wrong host name",
+		},
+	}
+	for i, tt := range tests {
+		_, _, err := auth.Start(tt.server)
+		got := ""
+		if err != nil {
+			got = err.Error()
+		}
+		if got != tt.err {
+			t.Errorf("%d. got error = %q; want %q", i, got, tt.err)
+		}
+	}
+}
+
 type faker struct {
 	io.ReadWriter
 }
diff --git a/src/pkg/net/sock_posix.go b/src/pkg/net/sock_posix.go
index 2ebde87..e2487c8 100644
--- a/src/pkg/net/sock_posix.go
+++ b/src/pkg/net/sock_posix.go
@@ -25,7 +25,8 @@ func socket(net string, f, t, p int, ipv6only bool, ulsa, ursa syscall.Sockaddr,
 		return nil, err
 	}
 
-	if ulsa != nil {
+	// This socket is used by a listener.
+	if ulsa != nil && ursa == nil {
 		// We provide a socket that listens to a wildcard
 		// address with reusable UDP port when the given ulsa
 		// is an appropriate UDP multicast address prefix.
@@ -37,6 +38,9 @@ func socket(net string, f, t, p int, ipv6only bool, ulsa, ursa syscall.Sockaddr,
 			closesocket(s)
 			return nil, err
 		}
+	}
+
+	if ulsa != nil {
 		if err = syscall.Bind(s, ulsa); err != nil {
 			closesocket(s)
 			return nil, err
@@ -48,6 +52,7 @@ func socket(net string, f, t, p int, ipv6only bool, ulsa, ursa syscall.Sockaddr,
 		return nil, err
 	}
 
+	// This socket is used by a dialer.
 	if ursa != nil {
 		if !deadline.IsZero() {
 			setWriteDeadline(fd, deadline)
@@ -65,10 +70,10 @@ func socket(net string, f, t, p int, ipv6only bool, ulsa, ursa syscall.Sockaddr,
 	lsa, _ := syscall.Getsockname(s)
 	laddr := toAddr(lsa)
 	rsa, _ := syscall.Getpeername(s)
+	if rsa == nil {
+		rsa = ursa
+	}
 	raddr := toAddr(rsa)
 	fd.setAddr(laddr, raddr)
-	if fd.raddr == nil {
-		fd.raddr = toAddr(ursa)
-	}
 	return fd, nil
 }
diff --git a/src/pkg/net/tcp_test.go b/src/pkg/net/tcp_test.go
index add8e48..a71b02b 100644
--- a/src/pkg/net/tcp_test.go
+++ b/src/pkg/net/tcp_test.go
@@ -147,12 +147,14 @@ func benchmarkTCP(b *testing.B, persistent, timeout bool, laddr string) {
 	}
 }
 
-var resolveTCPAddrTests = []struct {
+type resolveTCPAddrTest struct {
 	net     string
 	litAddr string
 	addr    *TCPAddr
 	err     error
-}{
+}
+
+var resolveTCPAddrTests = []resolveTCPAddrTest{
 	{"tcp", "127.0.0.1:0", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil},
 	{"tcp4", "127.0.0.1:65535", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 65535}, nil},
 
@@ -161,8 +163,6 @@ var resolveTCPAddrTests = []struct {
 
 	{"tcp", "[::1%en0]:1", &TCPAddr{IP: ParseIP("::1"), Port: 1, Zone: "en0"}, nil},
 	{"tcp6", "[::1%911]:2", &TCPAddr{IP: ParseIP("::1"), Port: 2, Zone: "911"}, nil},
-	{"tcp6", "[fe80::1]:3", &TCPAddr{IP: ParseIP("fe80::1"), Port: 3, Zone: "name"}, nil},
-	{"tcp6", "[fe80::1]:4", &TCPAddr{IP: ParseIP("fe80::1"), Port: 4, Zone: "index"}, nil},
 
 	{"", "127.0.0.1:0", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil}, // Go 1.0 behavior
 	{"", "[::1]:0", &TCPAddr{IP: ParseIP("::1"), Port: 0}, nil},         // Go 1.0 behavior
@@ -170,26 +170,18 @@ var resolveTCPAddrTests = []struct {
 	{"http", "127.0.0.1:0", nil, UnknownNetworkError("http")},
 }
 
+func init() {
+	if ifi := loopbackInterface(); ifi != nil {
+		index := fmt.Sprintf("%v", ifi.Index)
+		resolveTCPAddrTests = append(resolveTCPAddrTests, []resolveTCPAddrTest{
+			{"tcp6", "[fe80::1%" + ifi.Name + "]:3", &TCPAddr{IP: ParseIP("fe80::1"), Port: 3, Zone: zoneToString(ifi.Index)}, nil},
+			{"tcp6", "[fe80::1%" + index + "]:4", &TCPAddr{IP: ParseIP("fe80::1"), Port: 4, Zone: index}, nil},
+		}...)
+	}
+}
+
 func TestResolveTCPAddr(t *testing.T) {
 	for _, tt := range resolveTCPAddrTests {
-		if tt.addr != nil && (tt.addr.Zone == "name" || tt.addr.Zone == "index") {
-			ifi := loopbackInterface()
-			if ifi == nil {
-				continue
-			}
-			i := last(tt.litAddr, ']')
-			if i > 0 {
-				switch tt.addr.Zone {
-				case "name":
-					tt.litAddr = tt.litAddr[:i] + "%" + ifi.Name + tt.litAddr[i:]
-					tt.addr.Zone = zoneToString(ifi.Index)
-				case "index":
-					index := fmt.Sprintf("%v", ifi.Index)
-					tt.litAddr = tt.litAddr[:i] + "%" + index + tt.litAddr[i:]
-					tt.addr.Zone = index
-				}
-			}
-		}
 		addr, err := ResolveTCPAddr(tt.net, tt.litAddr)
 		if err != tt.err {
 			t.Fatalf("ResolveTCPAddr(%v, %v) failed: %v", tt.net, tt.litAddr, err)
@@ -217,14 +209,12 @@ func TestTCPListenerName(t *testing.T) {
 	for _, tt := range tcpListenerNameTests {
 		ln, err := ListenTCP(tt.net, tt.laddr)
 		if err != nil {
-			t.Errorf("ListenTCP failed: %v", err)
-			return
+			t.Fatalf("ListenTCP failed: %v", err)
 		}
 		defer ln.Close()
 		la := ln.Addr()
 		if a, ok := la.(*TCPAddr); !ok || a.Port == 0 {
-			t.Errorf("got %v; expected a proper address with non-zero port number", la)
-			return
+			t.Fatalf("got %v; expected a proper address with non-zero port number", la)
 		}
 	}
 }
diff --git a/src/pkg/net/tcpsock.go b/src/pkg/net/tcpsock.go
index 27db115..4d9ebd2 100644
--- a/src/pkg/net/tcpsock.go
+++ b/src/pkg/net/tcpsock.go
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// TCP sockets
-
 package net
 
 // TCPAddr represents the address of a TCP end point.
diff --git a/src/pkg/net/tcpsock_plan9.go b/src/pkg/net/tcpsock_plan9.go
index ed36646..96cbcc2 100644
--- a/src/pkg/net/tcpsock_plan9.go
+++ b/src/pkg/net/tcpsock_plan9.go
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// TCP sockets for Plan 9
-
 package net
 
 import (
@@ -165,8 +163,8 @@ func (l *TCPListener) File() (f *os.File, err error) { return l.dup() }
 
 // ListenTCP announces on the TCP address laddr and returns a TCP
 // listener.  Net must be "tcp", "tcp4", or "tcp6".  If laddr has a
-// port of 0, it means to listen on some available port.  The caller
-// can use l.Addr() to retrieve the chosen address.
+// port of 0, ListenTCP will choose an available port.  The caller can
+// use the Addr method of TCPListener to retrieve the chosen address.
 func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error) {
 	switch net {
 	case "tcp", "tcp4", "tcp6":
diff --git a/src/pkg/net/tcpsock_posix.go b/src/pkg/net/tcpsock_posix.go
index bd5a2a2..8133ca1 100644
--- a/src/pkg/net/tcpsock_posix.go
+++ b/src/pkg/net/tcpsock_posix.go
@@ -4,8 +4,6 @@
 
 // +build darwin freebsd linux netbsd openbsd windows
 
-// TCP sockets
-
 package net
 
 import (
@@ -58,8 +56,8 @@ func (a *TCPAddr) toAddr() sockaddr {
 	return a
 }
 
-// TCPConn is an implementation of the Conn interface
-// for TCP network connections.
+// TCPConn is an implementation of the Conn interface for TCP network
+// connections.
 type TCPConn struct {
 	conn
 }
@@ -96,17 +94,17 @@ func (c *TCPConn) CloseWrite() error {
 	return c.fd.CloseWrite()
 }
 
-// SetLinger sets the behavior of Close() on a connection
-// which still has data waiting to be sent or to be acknowledged.
+// SetLinger sets the behavior of Close() on a connection which still
+// has data waiting to be sent or to be acknowledged.
 //
-// If sec < 0 (the default), Close returns immediately and
-// the operating system finishes sending the data in the background.
+// If sec < 0 (the default), Close returns immediately and the
+// operating system finishes sending the data in the background.
 //
 // If sec == 0, Close returns immediately and the operating system
 // discards any unsent or unacknowledged data.
 //
-// If sec > 0, Close blocks for at most sec seconds waiting for
-// data to be sent and acknowledged.
+// If sec > 0, Close blocks for at most sec seconds waiting for data
+// to be sent and acknowledged.
 func (c *TCPConn) SetLinger(sec int) error {
 	if !c.ok() {
 		return syscall.EINVAL
@@ -124,9 +122,9 @@ func (c *TCPConn) SetKeepAlive(keepalive bool) error {
 }
 
 // SetNoDelay controls whether the operating system should delay
-// packet transmission in hopes of sending fewer packets
-// (Nagle's algorithm).  The default is true (no delay), meaning
-// that data is sent as soon as possible after a Write.
+// packet transmission in hopes of sending fewer packets (Nagle's
+// algorithm).  The default is true (no delay), meaning that data is
+// sent as soon as possible after a Write.
 func (c *TCPConn) SetNoDelay(noDelay bool) error {
 	if !c.ok() {
 		return syscall.EINVAL
@@ -135,8 +133,8 @@ func (c *TCPConn) SetNoDelay(noDelay bool) error {
 }
 
 // DialTCP connects to the remote address raddr on the network net,
-// which must be "tcp", "tcp4", or "tcp6".  If laddr is not nil, it is used
-// as the local address for the connection.
+// which must be "tcp", "tcp4", or "tcp6".  If laddr is not nil, it is
+// used as the local address for the connection.
 func DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error) {
 	switch net {
 	case "tcp", "tcp4", "tcp6":
@@ -216,16 +214,15 @@ func spuriousENOTAVAIL(err error) bool {
 	return ok && e.Err == syscall.EADDRNOTAVAIL
 }
 
-// TCPListener is a TCP network listener.
-// Clients should typically use variables of type Listener
-// instead of assuming TCP.
+// TCPListener is a TCP network listener.  Clients should typically
+// use variables of type Listener instead of assuming TCP.
 type TCPListener struct {
 	fd *netFD
 }
 
-// AcceptTCP accepts the next incoming call and returns the new connection
-// and the remote address.
-func (l *TCPListener) AcceptTCP() (c *TCPConn, err error) {
+// AcceptTCP accepts the next incoming call and returns the new
+// connection and the remote address.
+func (l *TCPListener) AcceptTCP() (*TCPConn, error) {
 	if l == nil || l.fd == nil {
 		return nil, syscall.EINVAL
 	}
@@ -236,14 +233,14 @@ func (l *TCPListener) AcceptTCP() (c *TCPConn, err error) {
 	return newTCPConn(fd), nil
 }
 
-// Accept implements the Accept method in the Listener interface;
-// it waits for the next call and returns a generic Conn.
-func (l *TCPListener) Accept() (c Conn, err error) {
-	c1, err := l.AcceptTCP()
+// Accept implements the Accept method in the Listener interface; it
+// waits for the next call and returns a generic Conn.
+func (l *TCPListener) Accept() (Conn, error) {
+	c, err := l.AcceptTCP()
 	if err != nil {
 		return nil, err
 	}
-	return c1, nil
+	return c, nil
 }
 
 // Close stops listening on the TCP address.
@@ -267,15 +264,15 @@ func (l *TCPListener) SetDeadline(t time.Time) error {
 	return setDeadline(l.fd, t)
 }
 
-// File returns a copy of the underlying os.File, set to blocking mode.
-// It is the caller's responsibility to close f when finished.
+// File returns a copy of the underlying os.File, set to blocking
+// mode.  It is the caller's responsibility to close f when finished.
 // Closing l does not affect f, and closing f does not affect l.
 func (l *TCPListener) File() (f *os.File, err error) { return l.fd.dup() }
 
-// ListenTCP announces on the TCP address laddr and returns a TCP listener.
-// Net must be "tcp", "tcp4", or "tcp6".
-// If laddr has a port of 0, it means to listen on some available port.
-// The caller can use l.Addr() to retrieve the chosen address.
+// ListenTCP announces on the TCP address laddr and returns a TCP
+// listener.  Net must be "tcp", "tcp4", or "tcp6".  If laddr has a
+// port of 0, ListenTCP will choose an available port.  The caller can
+// use the Addr method of TCPListener to retrieve the chosen address.
 func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error) {
 	switch net {
 	case "tcp", "tcp4", "tcp6":
diff --git a/src/pkg/net/textproto/reader.go b/src/pkg/net/textproto/reader.go
index 35e27ac..5bd26ac 100644
--- a/src/pkg/net/textproto/reader.go
+++ b/src/pkg/net/textproto/reader.go
@@ -574,6 +574,7 @@ var commonHeaders = []string{
 	"Content-Length",
 	"Content-Transfer-Encoding",
 	"Content-Type",
+	"Cookie",
 	"Date",
 	"Dkim-Signature",
 	"Etag",
diff --git a/src/pkg/net/textproto/reader_test.go b/src/pkg/net/textproto/reader_test.go
index 26987f6..f27042d 100644
--- a/src/pkg/net/textproto/reader_test.go
+++ b/src/pkg/net/textproto/reader_test.go
@@ -290,6 +290,7 @@ Non-Interned: test
 `, "\n", "\r\n", -1)
 
 func BenchmarkReadMIMEHeader(b *testing.B) {
+	b.ReportAllocs()
 	var buf bytes.Buffer
 	br := bufio.NewReader(&buf)
 	r := NewReader(br)
@@ -319,6 +320,7 @@ func BenchmarkReadMIMEHeader(b *testing.B) {
 }
 
 func BenchmarkUncommon(b *testing.B) {
+	b.ReportAllocs()
 	var buf bytes.Buffer
 	br := bufio.NewReader(&buf)
 	r := NewReader(br)
diff --git a/src/pkg/net/udp_test.go b/src/pkg/net/udp_test.go
index b3cafb0..4278f6d 100644
--- a/src/pkg/net/udp_test.go
+++ b/src/pkg/net/udp_test.go
@@ -11,12 +11,14 @@ import (
 	"testing"
 )
 
-var resolveUDPAddrTests = []struct {
+type resolveUDPAddrTest struct {
 	net     string
 	litAddr string
 	addr    *UDPAddr
 	err     error
-}{
+}
+
+var resolveUDPAddrTests = []resolveUDPAddrTest{
 	{"udp", "127.0.0.1:0", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil},
 	{"udp4", "127.0.0.1:65535", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 65535}, nil},
 
@@ -25,8 +27,6 @@ var resolveUDPAddrTests = []struct {
 
 	{"udp", "[::1%en0]:1", &UDPAddr{IP: ParseIP("::1"), Port: 1, Zone: "en0"}, nil},
 	{"udp6", "[::1%911]:2", &UDPAddr{IP: ParseIP("::1"), Port: 2, Zone: "911"}, nil},
-	{"udp6", "[fe80::1]:3", &UDPAddr{IP: ParseIP("fe80::1"), Port: 3, Zone: "name"}, nil},
-	{"udp6", "[fe80::1]:4", &UDPAddr{IP: ParseIP("fe80::1"), Port: 4, Zone: "index"}, nil},
 
 	{"", "127.0.0.1:0", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil}, // Go 1.0 behavior
 	{"", "[::1]:0", &UDPAddr{IP: ParseIP("::1"), Port: 0}, nil},         // Go 1.0 behavior
@@ -34,26 +34,18 @@ var resolveUDPAddrTests = []struct {
 	{"sip", "127.0.0.1:0", nil, UnknownNetworkError("sip")},
 }
 
+func init() {
+	if ifi := loopbackInterface(); ifi != nil {
+		index := fmt.Sprintf("%v", ifi.Index)
+		resolveUDPAddrTests = append(resolveUDPAddrTests, []resolveUDPAddrTest{
+			{"udp6", "[fe80::1%" + ifi.Name + "]:3", &UDPAddr{IP: ParseIP("fe80::1"), Port: 3, Zone: zoneToString(ifi.Index)}, nil},
+			{"udp6", "[fe80::1%" + index + "]:4", &UDPAddr{IP: ParseIP("fe80::1"), Port: 4, Zone: index}, nil},
+		}...)
+	}
+}
+
 func TestResolveUDPAddr(t *testing.T) {
 	for _, tt := range resolveUDPAddrTests {
-		if tt.addr != nil && (tt.addr.Zone == "name" || tt.addr.Zone == "index") {
-			ifi := loopbackInterface()
-			if ifi == nil {
-				continue
-			}
-			i := last(tt.litAddr, ']')
-			if i > 0 {
-				switch tt.addr.Zone {
-				case "name":
-					tt.litAddr = tt.litAddr[:i] + "%" + ifi.Name + tt.litAddr[i:]
-					tt.addr.Zone = zoneToString(ifi.Index)
-				case "index":
-					index := fmt.Sprintf("%v", ifi.Index)
-					tt.litAddr = tt.litAddr[:i] + "%" + index + tt.litAddr[i:]
-					tt.addr.Zone = index
-				}
-			}
-		}
 		addr, err := ResolveUDPAddr(tt.net, tt.litAddr)
 		if err != tt.err {
 			t.Fatalf("ResolveUDPAddr(%v, %v) failed: %v", tt.net, tt.litAddr, err)
@@ -159,14 +151,50 @@ func TestUDPConnLocalName(t *testing.T) {
 	for _, tt := range udpConnLocalNameTests {
 		c, err := ListenUDP(tt.net, tt.laddr)
 		if err != nil {
-			t.Errorf("ListenUDP failed: %v", err)
-			return
+			t.Fatalf("ListenUDP failed: %v", err)
 		}
 		defer c.Close()
 		la := c.LocalAddr()
 		if a, ok := la.(*UDPAddr); !ok || a.Port == 0 {
-			t.Errorf("got %v; expected a proper address with non-zero port number", la)
-			return
+			t.Fatalf("got %v; expected a proper address with non-zero port number", la)
+		}
+	}
+}
+
+func TestUDPConnLocalAndRemoteNames(t *testing.T) {
+	for _, laddr := range []string{"", "127.0.0.1:0"} {
+		c1, err := ListenPacket("udp", "127.0.0.1:0")
+		if err != nil {
+			t.Fatalf("ListenUDP failed: %v", err)
+		}
+		defer c1.Close()
+
+		var la *UDPAddr
+		if laddr != "" {
+			var err error
+			if la, err = ResolveUDPAddr("udp", laddr); err != nil {
+				t.Fatalf("ResolveUDPAddr failed: %v", err)
+			}
+		}
+		c2, err := DialUDP("udp", la, c1.LocalAddr().(*UDPAddr))
+		if err != nil {
+			t.Fatalf("DialUDP failed: %v", err)
+		}
+		defer c2.Close()
+
+		var connAddrs = [4]struct {
+			got Addr
+			ok  bool
+		}{
+			{c1.LocalAddr(), true},
+			{c1.(*UDPConn).RemoteAddr(), false},
+			{c2.LocalAddr(), true},
+			{c2.RemoteAddr(), true},
+		}
+		for _, ca := range connAddrs {
+			if a, ok := ca.got.(*UDPAddr); ok != ca.ok || ok && a.Port == 0 {
+				t.Fatalf("got %v; expected a proper address with non-zero port number", ca.got)
+			}
 		}
 	}
 }
diff --git a/src/pkg/net/udpsock.go b/src/pkg/net/udpsock.go
index 2770506..5ce7d6b 100644
--- a/src/pkg/net/udpsock.go
+++ b/src/pkg/net/udpsock.go
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// UDP sockets
-
 package net
 
 import "errors"
diff --git a/src/pkg/net/udpsock_plan9.go b/src/pkg/net/udpsock_plan9.go
index 66dcbab..12a3483 100644
--- a/src/pkg/net/udpsock_plan9.go
+++ b/src/pkg/net/udpsock_plan9.go
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// UDP sockets for Plan 9
-
 package net
 
 import (
@@ -13,15 +11,13 @@ import (
 	"time"
 )
 
-// UDPConn is the implementation of the Conn and PacketConn
-// interfaces for UDP network connections.
+// UDPConn is the implementation of the Conn and PacketConn interfaces
+// for UDP network connections.
 type UDPConn struct {
 	conn
 }
 
-func newUDPConn(fd *netFD) *UDPConn {
-	return &UDPConn{conn{fd}}
-}
+func newUDPConn(fd *netFD) *UDPConn { return &UDPConn{conn{fd}} }
 
 // ReadFromUDP reads a UDP packet from c, copying the payload into b.
 // It returns the number of bytes copied into b and the return address
@@ -164,7 +160,10 @@ func unmarshalUDPHeader(b []byte) (*udpHeader, []byte) {
 }
 
 // ListenUDP listens for incoming UDP packets addressed to the local
-// address laddr.  The returned connection c's ReadFrom and WriteTo
+// address laddr.  Net must be "udp", "udp4", or "udp6".  If laddr has
+// a port of 0, ListenUDP will choose an available port.
+// The LocalAddr method of the returned UDPConn can be used to
+// discover the port.  The returned connection's ReadFrom and WriteTo
 // methods can be used to receive and send UDP packets with per-packet
 // addressing.
 func ListenUDP(net string, laddr *UDPAddr) (*UDPConn, error) {
diff --git a/src/pkg/net/udpsock_posix.go b/src/pkg/net/udpsock_posix.go
index 9aafb70..b90cb03 100644
--- a/src/pkg/net/udpsock_posix.go
+++ b/src/pkg/net/udpsock_posix.go
@@ -4,8 +4,6 @@
 
 // +build darwin freebsd linux netbsd openbsd windows
 
-// UDP sockets for POSIX
-
 package net
 
 import (
@@ -51,8 +49,8 @@ func (a *UDPAddr) toAddr() sockaddr {
 	return a
 }
 
-// UDPConn is the implementation of the Conn and PacketConn
-// interfaces for UDP network connections.
+// UDPConn is the implementation of the Conn and PacketConn interfaces
+// for UDP network connections.
 type UDPConn struct {
 	conn
 }
@@ -63,8 +61,9 @@ func newUDPConn(fd *netFD) *UDPConn { return &UDPConn{conn{fd}} }
 // It returns the number of bytes copied into b and the return address
 // that was on the packet.
 //
-// ReadFromUDP can be made to time out and return an error with Timeout() == true
-// after a fixed time limit; see SetDeadline and SetReadDeadline.
+// ReadFromUDP can be made to time out and return an error with
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetReadDeadline.
 func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err error) {
 	if !c.ok() {
 		return 0, nil, syscall.EINVAL
@@ -108,12 +107,13 @@ func (c *UDPConn) ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *UDPAddr,
 	return
 }
 
-// WriteToUDP writes a UDP packet to addr via c, copying the payload from b.
+// WriteToUDP writes a UDP packet to addr via c, copying the payload
+// from b.
 //
-// WriteToUDP can be made to time out and return
-// an error with Timeout() == true after a fixed time limit;
-// see SetDeadline and SetWriteDeadline.
-// On packet-oriented connections, write timeouts are rare.
+// WriteToUDP can be made to time out and return an error with
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetWriteDeadline.  On packet-oriented connections, write timeouts
+// are rare.
 func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error) {
 	if !c.ok() {
 		return 0, syscall.EINVAL
@@ -158,8 +158,8 @@ func (c *UDPConn) WriteMsgUDP(b, oob []byte, addr *UDPAddr) (n, oobn int, err er
 }
 
 // DialUDP connects to the remote address raddr on the network net,
-// which must be "udp", "udp4", or "udp6".  If laddr is not nil, it is used
-// as the local address for the connection.
+// which must be "udp", "udp4", or "udp6".  If laddr is not nil, it is
+// used as the local address for the connection.
 func DialUDP(net string, laddr, raddr *UDPAddr) (*UDPConn, error) {
 	return dialUDP(net, laddr, raddr, noDeadline)
 }
@@ -180,10 +180,13 @@ func dialUDP(net string, laddr, raddr *UDPAddr, deadline time.Time) (*UDPConn, e
 	return newUDPConn(fd), nil
 }
 
-// ListenUDP listens for incoming UDP packets addressed to the
-// local address laddr.  The returned connection c's ReadFrom
-// and WriteTo methods can be used to receive and send UDP
-// packets with per-packet addressing.
+// ListenUDP listens for incoming UDP packets addressed to the local
+// address laddr.  Net must be "udp", "udp4", or "udp6".  If laddr has
+// a port of 0, ListenUDP will choose an available port.
+// The LocalAddr method of the returned UDPConn can be used to
+// discover the port.  The returned connection's ReadFrom and WriteTo
+// methods can be used to receive and send UDP packets with per-packet
+// addressing.
 func ListenUDP(net string, laddr *UDPAddr) (*UDPConn, error) {
 	switch net {
 	case "udp", "udp4", "udp6":
@@ -201,9 +204,9 @@ func ListenUDP(net string, laddr *UDPAddr) (*UDPConn, error) {
 }
 
 // ListenMulticastUDP listens for incoming multicast UDP packets
-// addressed to the group address gaddr on ifi, which specifies
-// the interface to join.  ListenMulticastUDP uses default
-// multicast interface if ifi is nil.
+// addressed to the group address gaddr on ifi, which specifies the
+// interface to join.  ListenMulticastUDP uses default multicast
+// interface if ifi is nil.
 func ListenMulticastUDP(net string, ifi *Interface, gaddr *UDPAddr) (*UDPConn, error) {
 	switch net {
 	case "udp", "udp4", "udp6":
diff --git a/src/pkg/net/unicast_posix_test.go b/src/pkg/net/unicast_posix_test.go
index a8855ca..b0588f4 100644
--- a/src/pkg/net/unicast_posix_test.go
+++ b/src/pkg/net/unicast_posix_test.go
@@ -45,7 +45,7 @@ var listenerTests = []struct {
 // same port.
 func TestTCPListener(t *testing.T) {
 	switch runtime.GOOS {
-	case "plan9", "windows":
+	case "plan9":
 		t.Skipf("skipping test on %q", runtime.GOOS)
 	}
 
@@ -69,65 +69,8 @@ func TestTCPListener(t *testing.T) {
 // same port.
 func TestUDPListener(t *testing.T) {
 	switch runtime.GOOS {
-	case "plan9", "windows":
-		t.Skipf("skipping test on %q", runtime.GOOS)
-	}
-
-	toudpnet := func(net string) string {
-		switch net {
-		case "tcp":
-			return "udp"
-		case "tcp4":
-			return "udp4"
-		case "tcp6":
-			return "udp6"
-		}
-		return "<nil>"
-	}
-
-	for _, tt := range listenerTests {
-		if tt.wildcard && (testing.Short() || !*testExternal) {
-			continue
-		}
-		if tt.ipv6 && !supportsIPv6 {
-			continue
-		}
-		tt.net = toudpnet(tt.net)
-		l1, port := usableListenPacketPort(t, tt.net, tt.laddr)
-		checkFirstListener(t, tt.net, tt.laddr+":"+port, l1)
-		l2, err := ListenPacket(tt.net, tt.laddr+":"+port)
-		checkSecondListener(t, tt.net, tt.laddr+":"+port, err, l2)
-		l1.Close()
-	}
-}
-
-func TestSimpleTCPListener(t *testing.T) {
-	switch runtime.GOOS {
-	case "plan9":
-		t.Skipf("skipping test on %q", runtime.GOOS)
-		return
-	}
-
-	for _, tt := range listenerTests {
-		if tt.wildcard && (testing.Short() || !*testExternal) {
-			continue
-		}
-		if tt.ipv6 {
-			continue
-		}
-		l1, port := usableListenPort(t, tt.net, tt.laddr)
-		checkFirstListener(t, tt.net, tt.laddr+":"+port, l1)
-		l2, err := Listen(tt.net, tt.laddr+":"+port)
-		checkSecondListener(t, tt.net, tt.laddr+":"+port, err, l2)
-		l1.Close()
-	}
-}
-
-func TestSimpleUDPListener(t *testing.T) {
-	switch runtime.GOOS {
 	case "plan9":
 		t.Skipf("skipping test on %q", runtime.GOOS)
-		return
 	}
 
 	toudpnet := func(net string) string {
@@ -146,7 +89,7 @@ func TestSimpleUDPListener(t *testing.T) {
 		if tt.wildcard && (testing.Short() || !*testExternal) {
 			continue
 		}
-		if tt.ipv6 {
+		if tt.ipv6 && !supportsIPv6 {
 			continue
 		}
 		tt.net = toudpnet(tt.net)
@@ -231,7 +174,7 @@ func TestDualStackTCPListener(t *testing.T) {
 		t.Skipf("skipping test on %q", runtime.GOOS)
 	}
 	if !supportsIPv6 {
-		return
+		t.Skip("ipv6 is not supported")
 	}
 
 	for _, tt := range dualStackListenerTests {
@@ -263,7 +206,7 @@ func TestDualStackUDPListener(t *testing.T) {
 		t.Skipf("skipping test on %q", runtime.GOOS)
 	}
 	if !supportsIPv6 {
-		return
+		t.Skip("ipv6 is not supported")
 	}
 
 	toudpnet := func(net string) string {
diff --git a/src/pkg/net/unix_test.go b/src/pkg/net/unix_test.go
index 2eaabe8..5e63e9d 100644
--- a/src/pkg/net/unix_test.go
+++ b/src/pkg/net/unix_test.go
@@ -33,7 +33,6 @@ func TestReadUnixgramWithUnnamedSocket(t *testing.T) {
 
 	off := make(chan bool)
 	data := [5]byte{1, 2, 3, 4, 5}
-
 	go func() {
 		defer func() { off <- true }()
 		s, err := syscall.Socket(syscall.AF_UNIX, syscall.SOCK_DGRAM, 0)
@@ -54,15 +53,13 @@ func TestReadUnixgramWithUnnamedSocket(t *testing.T) {
 	c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
 	n, from, err := c.ReadFrom(b)
 	if err != nil {
-		t.Errorf("UnixConn.ReadFrom failed: %v", err)
-		return
+		t.Fatalf("UnixConn.ReadFrom failed: %v", err)
 	}
 	if from != nil {
-		t.Errorf("neighbor address is %v", from)
+		t.Fatalf("neighbor address is %v", from)
 	}
 	if !bytes.Equal(b[:n], data[:]) {
-		t.Errorf("got %v, want %v", b[:n], data[:])
-		return
+		t.Fatalf("got %v, want %v", b[:n], data[:])
 	}
 }
 
@@ -101,13 +98,12 @@ func TestReadUnixgramWithZeroBytesBuffer(t *testing.T) {
 
 	<-off
 	c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
-	var peer Addr
-	if _, peer, err = c.ReadFrom(nil); err != nil {
-		t.Errorf("UnixConn.ReadFrom failed: %v", err)
-		return
+	_, from, err := c.ReadFrom(nil)
+	if err != nil {
+		t.Fatalf("UnixConn.ReadFrom failed: %v", err)
 	}
-	if peer != nil {
-		t.Errorf("peer adddress is %v", peer)
+	if from != nil {
+		t.Fatalf("neighbor address is %v", from)
 	}
 }
 
@@ -126,10 +122,10 @@ func TestUnixAutobind(t *testing.T) {
 	// retrieve the autobind address
 	autoAddr := c1.LocalAddr().(*UnixAddr)
 	if len(autoAddr.Name) <= 1 {
-		t.Fatalf("Invalid autobind address: %v", autoAddr)
+		t.Fatalf("invalid autobind address: %v", autoAddr)
 	}
 	if autoAddr.Name[0] != '@' {
-		t.Fatalf("Invalid autobind address: %v", autoAddr)
+		t.Fatalf("invalid autobind address: %v", autoAddr)
 	}
 
 	c2, err := DialUnix("unixgram", nil, autoAddr)
@@ -139,6 +135,112 @@ func TestUnixAutobind(t *testing.T) {
 	defer c2.Close()
 
 	if !reflect.DeepEqual(c1.LocalAddr(), c2.RemoteAddr()) {
-		t.Fatalf("Expected autobind address %v, got %v", c1.LocalAddr(), c2.RemoteAddr())
+		t.Fatalf("expected autobind address %v, got %v", c1.LocalAddr(), c2.RemoteAddr())
+	}
+}
+
+func TestUnixConnLocalAndRemoteNames(t *testing.T) {
+	for _, laddr := range []string{"", testUnixAddr()} {
+		taddr := testUnixAddr()
+		ta, err := ResolveUnixAddr("unix", taddr)
+		if err != nil {
+			t.Fatalf("ResolveUnixAddr failed: %v", err)
+		}
+		ln, err := ListenUnix("unix", ta)
+		if err != nil {
+			t.Fatalf("ListenUnix failed: %v", err)
+		}
+		defer func() {
+			ln.Close()
+			os.Remove(taddr)
+		}()
+
+		done := make(chan int)
+		go transponder(t, ln, done)
+
+		la, err := ResolveUnixAddr("unix", laddr)
+		if err != nil {
+			t.Fatalf("ResolveUnixAddr failed: %v", err)
+		}
+		c, err := DialUnix("unix", la, ta)
+		if err != nil {
+			t.Fatalf("DialUnix failed: %v", err)
+		}
+		defer func() {
+			c.Close()
+			if la != nil {
+				defer os.Remove(laddr)
+			}
+		}()
+		if _, err := c.Write([]byte("UNIXCONN LOCAL AND REMOTE NAME TEST")); err != nil {
+			t.Fatalf("UnixConn.Write failed: %v", err)
+		}
+
+		if runtime.GOOS == "linux" && laddr == "" {
+			laddr = "@" // autobind feature
+		}
+		var connAddrs = [3]struct{ got, want Addr }{
+			{ln.Addr(), ta},
+			{c.LocalAddr(), &UnixAddr{Name: laddr, Net: "unix"}},
+			{c.RemoteAddr(), ta},
+		}
+		for _, ca := range connAddrs {
+			if !reflect.DeepEqual(ca.got, ca.want) {
+				t.Fatalf("got %#v, expected %#v", ca.got, ca.want)
+			}
+		}
+
+		<-done
+	}
+}
+
+func TestUnixgramConnLocalAndRemoteNames(t *testing.T) {
+	for _, laddr := range []string{"", testUnixAddr()} {
+		taddr := testUnixAddr()
+		ta, err := ResolveUnixAddr("unixgram", taddr)
+		if err != nil {
+			t.Fatalf("ResolveUnixAddr failed: %v", err)
+		}
+		c1, err := ListenUnixgram("unixgram", ta)
+		if err != nil {
+			t.Fatalf("ListenUnixgram failed: %v", err)
+		}
+		defer func() {
+			c1.Close()
+			os.Remove(taddr)
+		}()
+
+		var la *UnixAddr
+		if laddr != "" {
+			var err error
+			if la, err = ResolveUnixAddr("unixgram", laddr); err != nil {
+				t.Fatalf("ResolveUnixAddr failed: %v", err)
+			}
+		}
+		c2, err := DialUnix("unixgram", la, ta)
+		if err != nil {
+			t.Fatalf("DialUnix failed: %v", err)
+		}
+		defer func() {
+			c2.Close()
+			if la != nil {
+				defer os.Remove(laddr)
+			}
+		}()
+
+		if runtime.GOOS == "linux" && laddr == "" {
+			laddr = "@" // autobind feature
+		}
+		var connAddrs = [4]struct{ got, want Addr }{
+			{c1.LocalAddr(), ta},
+			{c1.RemoteAddr(), nil},
+			{c2.LocalAddr(), &UnixAddr{Name: laddr, Net: "unixgram"}},
+			{c2.RemoteAddr(), ta},
+		}
+		for _, ca := range connAddrs {
+			if !reflect.DeepEqual(ca.got, ca.want) {
+				t.Fatalf("got %#v, expected %#v", ca.got, ca.want)
+			}
+		}
 	}
 }
diff --git a/src/pkg/net/unixsock.go b/src/pkg/net/unixsock.go
index 977ff91..21a19ec 100644
--- a/src/pkg/net/unixsock.go
+++ b/src/pkg/net/unixsock.go
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Unix domain sockets
-
 package net
 
 // UnixAddr represents the address of a Unix domain socket end point.
diff --git a/src/pkg/net/unixsock_plan9.go b/src/pkg/net/unixsock_plan9.go
index 00a0be5..0390207 100644
--- a/src/pkg/net/unixsock_plan9.go
+++ b/src/pkg/net/unixsock_plan9.go
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Unix domain sockets stubs for Plan 9
-
 package net
 
 import (
@@ -133,9 +131,9 @@ func (l *UnixListener) File() (*os.File, error) {
 }
 
 // ListenUnixgram listens for incoming Unix datagram packets addressed
-// to the local address laddr.  The returned connection c's ReadFrom
-// and WriteTo methods can be used to receive and send packets with
-// per-packet addressing.  The network net must be "unixgram".
+// to the local address laddr.  The network net must be "unixgram".
+// The returned connection's ReadFrom and WriteTo methods can be used
+// to receive and send packets with per-packet addressing.
 func ListenUnixgram(net string, laddr *UnixAddr) (*UnixConn, error) {
 	return nil, syscall.EPLAN9
 }
diff --git a/src/pkg/net/unixsock_posix.go b/src/pkg/net/unixsock_posix.go
index 8d57dac..760d38f 100644
--- a/src/pkg/net/unixsock_posix.go
+++ b/src/pkg/net/unixsock_posix.go
@@ -4,8 +4,6 @@
 
 // +build darwin freebsd linux netbsd openbsd windows
 
-// Unix domain sockets
-
 package net
 
 import (
@@ -15,6 +13,13 @@ import (
 	"time"
 )
 
+func (a *UnixAddr) isUnnamed() bool {
+	if a == nil || a.Name == "" {
+		return true
+	}
+	return false
+}
+
 func unixSocket(net string, laddr, raddr *UnixAddr, mode string, deadline time.Time) (*netFD, error) {
 	var sotype int
 	switch net {
@@ -31,12 +36,12 @@ func unixSocket(net string, laddr, raddr *UnixAddr, mode string, deadline time.T
 	var la, ra syscall.Sockaddr
 	switch mode {
 	case "dial":
-		if laddr != nil {
+		if !laddr.isUnnamed() {
 			la = &syscall.SockaddrUnix{Name: laddr.Name}
 		}
 		if raddr != nil {
 			ra = &syscall.SockaddrUnix{Name: raddr.Name}
-		} else if sotype != syscall.SOCK_DGRAM || laddr == nil {
+		} else if sotype != syscall.SOCK_DGRAM || laddr.isUnnamed() {
 			return nil, &OpError{Op: mode, Net: net, Err: errMissingAddress}
 		}
 	case "listen":
@@ -69,21 +74,21 @@ error:
 
 func sockaddrToUnix(sa syscall.Sockaddr) Addr {
 	if s, ok := sa.(*syscall.SockaddrUnix); ok {
-		return &UnixAddr{s.Name, "unix"}
+		return &UnixAddr{Name: s.Name, Net: "unix"}
 	}
 	return nil
 }
 
 func sockaddrToUnixgram(sa syscall.Sockaddr) Addr {
 	if s, ok := sa.(*syscall.SockaddrUnix); ok {
-		return &UnixAddr{s.Name, "unixgram"}
+		return &UnixAddr{Name: s.Name, Net: "unixgram"}
 	}
 	return nil
 }
 
 func sockaddrToUnixpacket(sa syscall.Sockaddr) Addr {
 	if s, ok := sa.(*syscall.SockaddrUnix); ok {
-		return &UnixAddr{s.Name, "unixpacket"}
+		return &UnixAddr{Name: s.Name, Net: "unixpacket"}
 	}
 	return nil
 }
@@ -92,10 +97,10 @@ func sotypeToNet(sotype int) string {
 	switch sotype {
 	case syscall.SOCK_STREAM:
 		return "unix"
-	case syscall.SOCK_SEQPACKET:
-		return "unixpacket"
 	case syscall.SOCK_DGRAM:
 		return "unixgram"
+	case syscall.SOCK_SEQPACKET:
+		return "unixpacket"
 	default:
 		panic("sotypeToNet unknown socket type")
 	}
@@ -124,7 +129,7 @@ func (c *UnixConn) ReadFromUnix(b []byte) (n int, addr *UnixAddr, err error) {
 	switch sa := sa.(type) {
 	case *syscall.SockaddrUnix:
 		if sa.Name != "" {
-			addr = &UnixAddr{sa.Name, sotypeToNet(c.fd.sotype)}
+			addr = &UnixAddr{Name: sa.Name, Net: sotypeToNet(c.fd.sotype)}
 		}
 	}
 	return
@@ -151,7 +156,7 @@ func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAdd
 	switch sa := sa.(type) {
 	case *syscall.SockaddrUnix:
 		if sa.Name != "" {
-			addr = &UnixAddr{sa.Name, sotypeToNet(c.fd.sotype)}
+			addr = &UnixAddr{Name: sa.Name, Net: sotypeToNet(c.fd.sotype)}
 		}
 	}
 	return
@@ -337,9 +342,9 @@ func (l *UnixListener) SetDeadline(t time.Time) (err error) {
 func (l *UnixListener) File() (f *os.File, err error) { return l.fd.dup() }
 
 // ListenUnixgram listens for incoming Unix datagram packets addressed
-// to the local address laddr.  The returned connection c's ReadFrom
-// and WriteTo methods can be used to receive and send packets with
-// per-packet addressing.  The network net must be "unixgram".
+// to the local address laddr.  The network net must be "unixgram".
+// The returned connection's ReadFrom and WriteTo methods can be used
+// to receive and send packets with per-packet addressing.
 func ListenUnixgram(net string, laddr *UnixAddr) (*UnixConn, error) {
 	switch net {
 	case "unixgram":
diff --git a/src/pkg/net/url/url.go b/src/pkg/net/url/url.go
index c186403..459dc47 100644
--- a/src/pkg/net/url/url.go
+++ b/src/pkg/net/url/url.go
@@ -317,23 +317,22 @@ func getscheme(rawurl string) (scheme, path string, err error) {
 // Maybe s is of the form t c u.
 // If so, return t, c u (or t, u if cutc == true).
 // If not, return s, "".
-func split(s string, c byte, cutc bool) (string, string) {
-	for i := 0; i < len(s); i++ {
-		if s[i] == c {
-			if cutc {
-				return s[0:i], s[i+1:]
-			}
-			return s[0:i], s[i:]
-		}
+func split(s string, c string, cutc bool) (string, string) {
+	i := strings.Index(s, c)
+	if i < 0 {
+		return s, ""
+	}
+	if cutc {
+		return s[0:i], s[i+len(c):]
 	}
-	return s, ""
+	return s[0:i], s[i:]
 }
 
 // Parse parses rawurl into a URL structure.
 // The rawurl may be relative or absolute.
 func Parse(rawurl string) (url *URL, err error) {
 	// Cut off #frag
-	u, frag := split(rawurl, '#', true)
+	u, frag := split(rawurl, "#", true)
 	if url, err = parse(u, false); err != nil {
 		return nil, err
 	}
@@ -380,7 +379,7 @@ func parse(rawurl string, viaRequest bool) (url *URL, err error) {
 	}
 	url.Scheme = strings.ToLower(url.Scheme)
 
-	rest, url.RawQuery = split(rest, '?', true)
+	rest, url.RawQuery = split(rest, "?", true)
 
 	if !strings.HasPrefix(rest, "/") {
 		if url.Scheme != "" {
@@ -396,7 +395,7 @@ func parse(rawurl string, viaRequest bool) (url *URL, err error) {
 
 	if (url.Scheme != "" || !viaRequest && !strings.HasPrefix(rest, "///")) && strings.HasPrefix(rest, "//") {
 		var authority string
-		authority, rest = split(rest[2:], '/', false)
+		authority, rest = split(rest[2:], "/", false)
 		url.User, url.Host, err = parseAuthority(authority)
 		if err != nil {
 			goto Error
@@ -428,7 +427,7 @@ func parseAuthority(authority string) (user *Userinfo, host string, err error) {
 		}
 		user = User(userinfo)
 	} else {
-		username, password := split(userinfo, ':', true)
+		username, password := split(userinfo, ":", true)
 		if username, err = unescape(username, encodeUserPassword); err != nil {
 			return
 		}
diff --git a/src/pkg/os/exec/exec_test.go b/src/pkg/os/exec/exec_test.go
index dfcf4be..2467d29 100644
--- a/src/pkg/os/exec/exec_test.go
+++ b/src/pkg/os/exec/exec_test.go
@@ -25,7 +25,7 @@ func helperCommand(s ...string) *Cmd {
 	cs := []string{"-test.run=TestHelperProcess", "--"}
 	cs = append(cs, s...)
 	cmd := Command(os.Args[0], cs...)
-	cmd.Env = append([]string{"GO_WANT_HELPER_PROCESS=1"}, os.Environ()...)
+	cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"}
 	return cmd
 }
 
diff --git a/src/pkg/reflect/all_test.go b/src/pkg/reflect/all_test.go
index 9a4dd6c..56cb315 100644
--- a/src/pkg/reflect/all_test.go
+++ b/src/pkg/reflect/all_test.go
@@ -14,6 +14,7 @@ import (
 	"os"
 	. "reflect"
 	"runtime"
+	"sort"
 	"sync"
 	"testing"
 	"time"
@@ -2199,6 +2200,30 @@ func TestPtrTo(t *testing.T) {
 	}
 }
 
+func TestPtrToGC(t *testing.T) {
+	type T *uintptr
+	tt := TypeOf(T(nil))
+	pt := PtrTo(tt)
+	const n = 100
+	var x []interface{}
+	for i := 0; i < n; i++ {
+		v := New(pt)
+		p := new(*uintptr)
+		*p = new(uintptr)
+		**p = uintptr(i)
+		v.Elem().Set(ValueOf(p).Convert(pt))
+		x = append(x, v.Interface())
+	}
+	runtime.GC()
+
+	for i, xi := range x {
+		k := ValueOf(xi).Elem().Elem().Elem().Interface().(uintptr)
+		if k != uintptr(i) {
+			t.Errorf("lost x[%d] = %d, want %d", i, k, i)
+		}
+	}
+}
+
 func TestAddr(t *testing.T) {
 	var p struct {
 		X, Y int
@@ -2991,8 +3016,10 @@ func TestSliceOf(t *testing.T) {
 	type T int
 	st := SliceOf(TypeOf(T(1)))
 	v := MakeSlice(st, 10, 10)
+	runtime.GC()
 	for i := 0; i < v.Len(); i++ {
 		v.Index(i).Set(ValueOf(T(i)))
+		runtime.GC()
 	}
 	s := fmt.Sprint(v.Interface())
 	want := "[0 1 2 3 4 5 6 7 8 9]"
@@ -3005,13 +3032,44 @@ func TestSliceOf(t *testing.T) {
 	checkSameType(t, Zero(SliceOf(TypeOf(T1(1)))).Interface(), []T1{})
 }
 
+func TestSliceOfGC(t *testing.T) {
+	type T *uintptr
+	tt := TypeOf(T(nil))
+	st := SliceOf(tt)
+	const n = 100
+	var x []interface{}
+	for i := 0; i < n; i++ {
+		v := MakeSlice(st, n, n)
+		for j := 0; j < v.Len(); j++ {
+			p := new(uintptr)
+			*p = uintptr(i*n + j)
+			v.Index(j).Set(ValueOf(p).Convert(tt))
+		}
+		x = append(x, v.Interface())
+	}
+	runtime.GC()
+
+	for i, xi := range x {
+		v := ValueOf(xi)
+		for j := 0; j < v.Len(); j++ {
+			k := v.Index(j).Elem().Interface()
+			if k != uintptr(i*n+j) {
+				t.Errorf("lost x[%d][%d] = %d, want %d", i, j, k, i*n+j)
+			}
+		}
+	}
+}
+
 func TestChanOf(t *testing.T) {
 	// check construction and use of type not in binary
 	type T string
 	ct := ChanOf(BothDir, TypeOf(T("")))
 	v := MakeChan(ct, 2)
+	runtime.GC()
 	v.Send(ValueOf(T("hello")))
+	runtime.GC()
 	v.Send(ValueOf(T("world")))
+	runtime.GC()
 
 	sv1, _ := v.Recv()
 	sv2, _ := v.Recv()
@@ -3026,13 +3084,63 @@ func TestChanOf(t *testing.T) {
 	checkSameType(t, Zero(ChanOf(BothDir, TypeOf(T1(1)))).Interface(), (chan T1)(nil))
 }
 
+func TestChanOfGC(t *testing.T) {
+	done := make(chan bool, 1)
+	go func() {
+		select {
+		case <-done:
+		case <-time.After(5 * time.Second):
+			panic("deadlock in TestChanOfGC")
+		}
+	}()
+
+	defer func() {
+		done <- true
+	}()
+
+	type T *uintptr
+	tt := TypeOf(T(nil))
+	ct := ChanOf(BothDir, tt)
+
+	// NOTE: The garbage collector handles allocated channels specially,
+	// so we have to save pointers to channels in x; the pointer code will
+	// use the gc info in the newly constructed chan type.
+	const n = 100
+	var x []interface{}
+	for i := 0; i < n; i++ {
+		v := MakeChan(ct, n)
+		for j := 0; j < n; j++ {
+			p := new(uintptr)
+			*p = uintptr(i*n + j)
+			v.Send(ValueOf(p).Convert(tt))
+		}
+		pv := New(ct)
+		pv.Elem().Set(v)
+		x = append(x, pv.Interface())
+	}
+	runtime.GC()
+
+	for i, xi := range x {
+		v := ValueOf(xi).Elem()
+		for j := 0; j < n; j++ {
+			pv, _ := v.Recv()
+			k := pv.Elem().Interface()
+			if k != uintptr(i*n+j) {
+				t.Errorf("lost x[%d][%d] = %d, want %d", i, j, k, i*n+j)
+			}
+		}
+	}
+}
+
 func TestMapOf(t *testing.T) {
 	// check construction and use of type not in binary
 	type K string
 	type V float64
 
 	v := MakeMap(MapOf(TypeOf(K("")), TypeOf(V(0))))
+	runtime.GC()
 	v.SetMapIndex(ValueOf(K("a")), ValueOf(V(1)))
+	runtime.GC()
 
 	s := fmt.Sprint(v.Interface())
 	want := "map[a:1]"
@@ -3042,6 +3150,81 @@ func TestMapOf(t *testing.T) {
 
 	// check that type already in binary is found
 	checkSameType(t, Zero(MapOf(TypeOf(V(0)), TypeOf(K("")))).Interface(), map[V]K(nil))
+
+	// check that invalid key type panics
+	shouldPanic(func() { MapOf(TypeOf((func())(nil)), TypeOf(false)) })
+}
+
+func TestMapOfGCKeys(t *testing.T) {
+	type T *uintptr
+	tt := TypeOf(T(nil))
+	mt := MapOf(tt, TypeOf(false))
+
+	// NOTE: The garbage collector handles allocated maps specially,
+	// so we have to save pointers to maps in x; the pointer code will
+	// use the gc info in the newly constructed map type.
+	const n = 100
+	var x []interface{}
+	for i := 0; i < n; i++ {
+		v := MakeMap(mt)
+		for j := 0; j < n; j++ {
+			p := new(uintptr)
+			*p = uintptr(i*n + j)
+			v.SetMapIndex(ValueOf(p).Convert(tt), ValueOf(true))
+		}
+		pv := New(mt)
+		pv.Elem().Set(v)
+		x = append(x, pv.Interface())
+	}
+	runtime.GC()
+
+	for i, xi := range x {
+		v := ValueOf(xi).Elem()
+		var out []int
+		for _, kv := range v.MapKeys() {
+			out = append(out, int(kv.Elem().Interface().(uintptr)))
+		}
+		sort.Ints(out)
+		for j, k := range out {
+			if k != i*n+j {
+				t.Errorf("lost x[%d][%d] = %d, want %d", i, j, k, i*n+j)
+			}
+		}
+	}
+}
+
+func TestMapOfGCValues(t *testing.T) {
+	type T *uintptr
+	tt := TypeOf(T(nil))
+	mt := MapOf(TypeOf(1), tt)
+
+	// NOTE: The garbage collector handles allocated maps specially,
+	// so we have to save pointers to maps in x; the pointer code will
+	// use the gc info in the newly constructed map type.
+	const n = 100
+	var x []interface{}
+	for i := 0; i < n; i++ {
+		v := MakeMap(mt)
+		for j := 0; j < n; j++ {
+			p := new(uintptr)
+			*p = uintptr(i*n + j)
+			v.SetMapIndex(ValueOf(j), ValueOf(p).Convert(tt))
+		}
+		pv := New(mt)
+		pv.Elem().Set(v)
+		x = append(x, pv.Interface())
+	}
+	runtime.GC()
+
+	for i, xi := range x {
+		v := ValueOf(xi).Elem()
+		for j := 0; j < n; j++ {
+			k := v.MapIndex(ValueOf(j)).Elem().Interface().(uintptr)
+			if k != uintptr(i*n+j) {
+				t.Errorf("lost x[%d][%d] = %d, want %d", i, j, k, i*n+j)
+			}
+		}
+	}
 }
 
 type B1 struct {
diff --git a/src/pkg/reflect/type.go b/src/pkg/reflect/type.go
index 5ec94f5..b513fee 100644
--- a/src/pkg/reflect/type.go
+++ b/src/pkg/reflect/type.go
@@ -233,17 +233,17 @@ const (
 // with a unique tag like `reflect:"array"` or `reflect:"ptr"`
 // so that code cannot convert from, say, *arrayType to *ptrType.
 type rtype struct {
-	size          uintptr  // size in bytes
-	hash          uint32   // hash of type; avoids computation in hash tables
-	_             uint8    // unused/padding
-	align         uint8    // alignment of variable with this type
-	fieldAlign    uint8    // alignment of struct field with this type
-	kind          uint8    // enumeration for C
-	alg           *uintptr // algorithm table (../runtime/runtime.h:/Alg)
-	gc            uintptr  // garbage collection data
-	string        *string  // string form; unnecessary but undeniably useful
-	*uncommonType          // (relatively) uncommon fields
-	ptrToThis     *rtype   // type for pointer to this type, if used in binary or has methods
+	size          uintptr        // size in bytes
+	hash          uint32         // hash of type; avoids computation in hash tables
+	_             uint8          // unused/padding
+	align         uint8          // alignment of variable with this type
+	fieldAlign    uint8          // alignment of struct field with this type
+	kind          uint8          // enumeration for C
+	alg           *uintptr       // algorithm table (../runtime/runtime.h:/Alg)
+	gc            unsafe.Pointer // garbage collection data
+	string        *string        // string form; unnecessary but undeniably useful
+	*uncommonType                // (relatively) uncommon fields
+	ptrToThis     *rtype         // type for pointer to this type, if used in binary or has methods
 }
 
 // Method on non-interface type
@@ -345,6 +345,25 @@ type structType struct {
 	fields []structField // sorted by offset
 }
 
+// NOTE: These are copied from ../runtime/mgc0.h.
+// They must be kept in sync.
+const (
+	_GC_END = iota
+	_GC_PTR
+	_GC_APTR
+	_GC_ARRAY_START
+	_GC_ARRAY_NEXT
+	_GC_CALL
+	_GC_MAP_PTR
+	_GC_CHAN_PTR
+	_GC_STRING
+	_GC_EFACE
+	_GC_IFACE
+	_GC_SLICE
+	_GC_REGION
+	_GC_NUM_INSTR
+)
+
 /*
  * The compiler knows the exact layout of all the data structures above.
  * The compiler does not know about the data structures and methods below.
@@ -368,7 +387,10 @@ type Method struct {
 
 // High bit says whether type has
 // embedded pointers,to help garbage collector.
-const kindMask = 0x7f
+const (
+	kindMask       = 0x7f
+	kindNoPointers = 0x80
+)
 
 func (k Kind) String() string {
 	if int(k) < len(kindNames) {
@@ -978,6 +1000,32 @@ var ptrMap struct {
 	m map[*rtype]*ptrType
 }
 
+// garbage collection bytecode program for pointer to memory without pointers.
+// See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym.
+type ptrDataGC struct {
+	width uintptr // sizeof(ptr)
+	op    uintptr // _GC_APTR
+	off   uintptr // 0
+	end   uintptr // _GC_END
+}
+
+var ptrDataGCProg = ptrDataGC{
+	width: unsafe.Sizeof((*byte)(nil)),
+	op:    _GC_APTR,
+	off:   0,
+	end:   _GC_END,
+}
+
+// garbage collection bytecode program for pointer to memory with pointers.
+// See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym.
+type ptrGC struct {
+	width  uintptr        // sizeof(ptr)
+	op     uintptr        // _GC_PTR
+	off    uintptr        // 0
+	elemgc unsafe.Pointer // element gc type
+	end    uintptr        // _GC_END
+}
+
 // PtrTo returns the pointer type with element t.
 // For example, if t represents type Foo, PtrTo(t) represents *Foo.
 func PtrTo(t Type) Type {
@@ -1034,6 +1082,20 @@ func (t *rtype) ptrTo() *rtype {
 	p.ptrToThis = nil
 	p.elem = t
 
+	if t.kind&kindNoPointers != 0 {
+		p.gc = unsafe.Pointer(&ptrDataGCProg)
+	} else {
+		p.gc = unsafe.Pointer(&ptrGC{
+			width:  p.size,
+			op:     _GC_PTR,
+			off:    0,
+			elemgc: t.gc,
+			end:    _GC_END,
+		})
+	}
+	// INCORRECT. Uncomment to check that TestPtrToGC fails when p.gc is wrong.
+	//p.gc = unsafe.Pointer(&badGC{width: p.size, end: _GC_END})
+
 	ptrMap.m[t] = p
 	ptrMap.Unlock()
 	return &p.rtype
@@ -1338,6 +1400,21 @@ func cachePut(k cacheKey, t *rtype) Type {
 	return t
 }
 
+// garbage collection bytecode program for chan or map.
+// See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym.
+type chanMapGC struct {
+	width uintptr // sizeof(map)
+	op    uintptr // _GC_MAP_PTR or _GC_CHAN_PTR
+	off   uintptr // 0
+	typ   *rtype  // map type
+	end   uintptr // _GC_END
+}
+
+type badGC struct {
+	width uintptr
+	end   uintptr
+}
+
 // ChanOf returns the channel type with the given direction and element type.
 // For example, if t represents int, ChanOf(RecvDir, t) represents <-chan int.
 //
@@ -1390,20 +1467,35 @@ func ChanOf(dir ChanDir, t Type) Type {
 	ch.uncommonType = nil
 	ch.ptrToThis = nil
 
+	ch.gc = unsafe.Pointer(&chanMapGC{
+		width: ch.size,
+		op:    _GC_CHAN_PTR,
+		off:   0,
+		typ:   &ch.rtype,
+		end:   _GC_END,
+	})
+
+	// INCORRECT. Uncomment to check that TestChanOfGC fails when ch.gc is wrong.
+	//ch.gc = unsafe.Pointer(&badGC{width: ch.size, end: _GC_END})
+
 	return cachePut(ckey, &ch.rtype)
 }
 
+func ismapkey(*rtype) bool // implemented in runtime
+
 // MapOf returns the map type with the given key and element types.
 // For example, if k represents int and e represents string,
 // MapOf(k, e) represents map[int]string.
 //
 // If the key type is not a valid map key type (that is, if it does
-// not implement Go's == operator), MapOf panics. TODO(rsc).
+// not implement Go's == operator), MapOf panics.
 func MapOf(key, elem Type) Type {
 	ktyp := key.(*rtype)
 	etyp := elem.(*rtype)
 
-	// TODO: Check for invalid key types.
+	if !ismapkey(ktyp) {
+		panic("reflect.MapOf: invalid key type " + ktyp.String())
+	}
 
 	// Look in cache.
 	ckey := cacheKey{Map, ktyp, etyp, 0}
@@ -1432,9 +1524,47 @@ func MapOf(key, elem Type) Type {
 	mt.uncommonType = nil
 	mt.ptrToThis = nil
 
+	mt.gc = unsafe.Pointer(&chanMapGC{
+		width: mt.size,
+		op:    _GC_MAP_PTR,
+		off:   0,
+		typ:   &mt.rtype,
+		end:   _GC_END,
+	})
+
+	// INCORRECT. Uncomment to check that TestMapOfGC and TestMapOfGCValues
+	// fail when mt.gc is wrong.
+	//mt.gc = unsafe.Pointer(&badGC{width: mt.size, end: _GC_END})
+
 	return cachePut(ckey, &mt.rtype)
 }
 
+// garbage collection bytecode program for slice of non-zero-length values.
+// See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym.
+type sliceGC struct {
+	width  uintptr        // sizeof(slice)
+	op     uintptr        // _GC_SLICE
+	off    uintptr        // 0
+	elemgc unsafe.Pointer // element gc program
+	end    uintptr        // _GC_END
+}
+
+// garbage collection bytecode program for slice of zero-length values.
+// See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym.
+type sliceEmptyGC struct {
+	width uintptr // sizeof(slice)
+	op    uintptr // _GC_APTR
+	off   uintptr // 0
+	end   uintptr // _GC_END
+}
+
+var sliceEmptyGCProg = sliceEmptyGC{
+	width: unsafe.Sizeof([]byte(nil)),
+	op:    _GC_APTR,
+	off:   0,
+	end:   _GC_END,
+}
+
 // SliceOf returns the slice type with element type t.
 // For example, if t represents int, SliceOf(t) represents []int.
 func SliceOf(t Type) Type {
@@ -1466,6 +1596,21 @@ func SliceOf(t Type) Type {
 	slice.uncommonType = nil
 	slice.ptrToThis = nil
 
+	if typ.size == 0 {
+		slice.gc = unsafe.Pointer(&sliceEmptyGCProg)
+	} else {
+		slice.gc = unsafe.Pointer(&sliceGC{
+			width:  slice.size,
+			op:     _GC_SLICE,
+			off:    0,
+			elemgc: typ.gc,
+			end:    _GC_END,
+		})
+	}
+
+	// INCORRECT. Uncomment to check that TestSliceOfOfGC fails when slice.gc is wrong.
+	//slice.gc = unsafe.Pointer(&badGC{width: slice.size, end: _GC_END})
+
 	return cachePut(ckey, &slice.rtype)
 }
 
diff --git a/src/pkg/runtime/alg.c b/src/pkg/runtime/alg.c
index 2dc8212..a78d978 100644
--- a/src/pkg/runtime/alg.c
+++ b/src/pkg/runtime/alg.c
@@ -37,25 +37,11 @@ runtime·memhash(uintptr *h, uintptr s, void *a)
 void
 runtime·memequal(bool *eq, uintptr s, void *a, void *b)
 {
-	byte *ba, *bb, *aend;
-
 	if(a == b) {
 		*eq = 1;
 		return;
 	}
-	ba = a;
-	bb = b;
-	aend = ba+s;
-	while(ba != aend) {
-		if(*ba != *bb) {
-			*eq = 0;
-			return;
-		}
-		ba++;
-		bb++;
-	}
-	*eq = 1;
-	return;
+	*eq = runtime·memeq(a, b, s);
 }
 
 void
@@ -323,6 +309,7 @@ void
 runtime·strequal(bool *eq, uintptr s, void *a, void *b)
 {
 	intgo alen;
+	byte *s1, *s2;
 
 	USED(s);
 	alen = ((String*)a)->len;
@@ -330,11 +317,13 @@ runtime·strequal(bool *eq, uintptr s, void *a, void *b)
 		*eq = false;
 		return;
 	}
-	if(((String*)a)->str == ((String*)b)->str) {
+	s1 = ((String*)a)->str;
+	s2 = ((String*)b)->str;
+	if(s1 == s2) {
 		*eq = true;
 		return;
 	}
-	runtime·memequal(eq, alen, ((String*)a)->str, ((String*)b)->str);
+	*eq = runtime·memeq(s1, s2, alen);
 }
 
 void
diff --git a/src/pkg/runtime/asm_386.s b/src/pkg/runtime/asm_386.s
index 6bcacf4..531057f 100644
--- a/src/pkg/runtime/asm_386.s
+++ b/src/pkg/runtime/asm_386.s
@@ -37,6 +37,8 @@ nocpuinfo:
 	MOVL	_cgo_init(SB), AX
 	TESTL	AX, AX
 	JZ	needtls
+	MOVL	$setmg_gcc<>(SB), BX
+	MOVL	BX, 4(SP)
 	MOVL	BP, 0(SP)
 	CALL	AX
 	// skip runtime·ldt0setup(SB) and tls test after _cgo_init for non-windows
@@ -106,7 +108,7 @@ TEXT runtime·breakpoint(SB),7,$0
 	RET
 
 TEXT runtime·asminit(SB),7,$0
-	// Linux, Windows start the FPU in extended double precision.
+	// Linux and MinGW start the FPU in extended double precision.
 	// Other operating systems use double precision.
 	// Change to double precision to match them,
 	// and to match other hardware that only has double.
@@ -643,6 +645,15 @@ settls:
 	MOVL	BX, g(CX)
 	RET
 
+// void setmg_gcc(M*, G*); set m and g. for use by gcc
+TEXT setmg_gcc<>(SB), 7, $0	
+	get_tls(AX)
+	MOVL	mm+0(FP), DX
+	MOVL	DX, m(AX)
+	MOVL	gg+4(FP), DX
+	MOVL	DX,g (AX)
+	RET
+
 // check that SP is in range [g->stackbase, g->stackguard)
 TEXT runtime·stackcheck(SB), 7, $0
 	get_tls(CX)
@@ -975,3 +986,118 @@ TEXT shifts(SB),7,$0
 	LONG $0x0c0b0a09
 	LONG $0xff0f0e0d
 
+TEXT runtime·memeq(SB),7,$0
+	MOVL	a+0(FP), SI
+	MOVL	b+4(FP), DI
+	MOVL	count+8(FP), BX
+	JMP	runtime·memeqbody(SB)
+
+
+TEXT bytes·Equal(SB),7,$0
+	MOVL	a_len+4(FP), BX
+	MOVL	b_len+16(FP), CX
+	XORL	AX, AX
+	CMPL	BX, CX
+	JNE	eqret
+	MOVL	a+0(FP), SI
+	MOVL	b+12(FP), DI
+	CALL	runtime·memeqbody(SB)
+eqret:
+	MOVB	AX, ret+24(FP)
+	RET
+
+// a in SI
+// b in DI
+// count in BX
+TEXT runtime·memeqbody(SB),7,$0
+	XORL	AX, AX
+
+	CMPL	BX, $4
+	JB	small
+
+	// 64 bytes at a time using xmm registers
+hugeloop:
+	CMPL	BX, $64
+	JB	bigloop
+	TESTL	$0x4000000, runtime·cpuid_edx(SB) // check for sse2
+	JE	bigloop
+	MOVOU	(SI), X0
+	MOVOU	(DI), X1
+	MOVOU	16(SI), X2
+	MOVOU	16(DI), X3
+	MOVOU	32(SI), X4
+	MOVOU	32(DI), X5
+	MOVOU	48(SI), X6
+	MOVOU	48(DI), X7
+	PCMPEQB	X1, X0
+	PCMPEQB	X3, X2
+	PCMPEQB	X5, X4
+	PCMPEQB	X7, X6
+	PAND	X2, X0
+	PAND	X6, X4
+	PAND	X4, X0
+	PMOVMSKB X0, DX
+	ADDL	$64, SI
+	ADDL	$64, DI
+	SUBL	$64, BX
+	CMPL	DX, $0xffff
+	JEQ	hugeloop
+	RET
+
+	// 4 bytes at a time using 32-bit register
+bigloop:
+	CMPL	BX, $4
+	JBE	leftover
+	MOVL	(SI), CX
+	MOVL	(DI), DX
+	ADDL	$4, SI
+	ADDL	$4, DI
+	SUBL	$4, BX
+	CMPL	CX, DX
+	JEQ	bigloop
+	RET
+
+	// remaining 0-4 bytes
+leftover:
+	MOVL	-4(SI)(BX*1), CX
+	MOVL	-4(DI)(BX*1), DX
+	CMPL	CX, DX
+	SETEQ	AX
+	RET
+
+small:
+	CMPL	BX, $0
+	JEQ	equal
+
+	LEAL	0(BX*8), CX
+	NEGL	CX
+
+	MOVL	SI, DX
+	CMPB	DX, $0xfc
+	JA	si_high
+
+	// load at SI won't cross a page boundary.
+	MOVL	(SI), SI
+	JMP	si_finish
+si_high:
+	// address ends in 111111xx.  Load up to bytes we want, move to correct position.
+	MOVL	-4(SI)(BX*1), SI
+	SHRL	CX, SI
+si_finish:
+
+	// same for DI.
+	MOVL	DI, DX
+	CMPB	DX, $0xfc
+	JA	di_high
+	MOVL	(DI), DI
+	JMP	di_finish
+di_high:
+	MOVL	-4(DI)(BX*1), DI
+	SHRL	CX, DI
+di_finish:
+
+	SUBL	SI, DI
+	SHLL	CX, DI
+equal:
+	SETEQ	AX
+	RET
diff --git a/src/pkg/runtime/asm_amd64.s b/src/pkg/runtime/asm_amd64.s
index f4cfa57..0dee155 100644
--- a/src/pkg/runtime/asm_amd64.s
+++ b/src/pkg/runtime/asm_amd64.s
@@ -37,6 +37,7 @@ nocpuinfo:
 	JZ	needtls
 	// g0 already in DI
 	MOVQ	DI, CX	// Win64 uses CX for first parameter
+	MOVQ	$setmg_gcc<>(SB), SI
 	CALL	AX
 	CMPL	runtime·iswindows(SB), $0
 	JEQ ok
@@ -682,6 +683,13 @@ settls:
 	MOVQ	BX, g(CX)
 	RET
 
+// void setmg_gcc(M*, G*); set m and g called from gcc.
+TEXT setmg_gcc<>(SB),7,$0
+	get_tls(AX)
+	MOVQ	DI, m(AX)
+	MOVQ	SI, g(AX)
+	RET
+
 // check that SP is in range [g->stackbase, g->stackguard)
 TEXT runtime·stackcheck(SB), 7, $0
 	get_tls(CX)
@@ -899,3 +907,115 @@ TEXT shifts(SB),7,$0
 	QUAD $0xffff0f0e0d0c0b0a
 	QUAD $0x0807060504030201
 	QUAD $0xff0f0e0d0c0b0a09
+
+TEXT runtime·memeq(SB),7,$0
+	MOVQ	a+0(FP), SI
+	MOVQ	b+8(FP), DI
+	MOVQ	count+16(FP), BX
+	JMP	runtime·memeqbody(SB)
+
+
+TEXT bytes·Equal(SB),7,$0
+	MOVQ	a_len+8(FP), BX
+	MOVQ	b_len+32(FP), CX
+	XORQ	AX, AX
+	CMPQ	BX, CX
+	JNE	eqret
+	MOVQ	a+0(FP), SI
+	MOVQ	b+24(FP), DI
+	CALL	runtime·memeqbody(SB)
+eqret:
+	MOVB	AX, ret+48(FP)
+	RET
+
+// a in SI
+// b in DI
+// count in BX
+TEXT runtime·memeqbody(SB),7,$0
+	XORQ	AX, AX
+
+	CMPQ	BX, $8
+	JB	small
+	
+	// 64 bytes at a time using xmm registers
+hugeloop:
+	CMPQ	BX, $64
+	JB	bigloop
+	MOVOU	(SI), X0
+	MOVOU	(DI), X1
+	MOVOU	16(SI), X2
+	MOVOU	16(DI), X3
+	MOVOU	32(SI), X4
+	MOVOU	32(DI), X5
+	MOVOU	48(SI), X6
+	MOVOU	48(DI), X7
+	PCMPEQB	X1, X0
+	PCMPEQB	X3, X2
+	PCMPEQB	X5, X4
+	PCMPEQB	X7, X6
+	PAND	X2, X0
+	PAND	X6, X4
+	PAND	X4, X0
+	PMOVMSKB X0, DX
+	ADDQ	$64, SI
+	ADDQ	$64, DI
+	SUBQ	$64, BX
+	CMPL	DX, $0xffff
+	JEQ	hugeloop
+	RET
+
+	// 8 bytes at a time using 64-bit register
+bigloop:
+	CMPQ	BX, $8
+	JBE	leftover
+	MOVQ	(SI), CX
+	MOVQ	(DI), DX
+	ADDQ	$8, SI
+	ADDQ	$8, DI
+	SUBQ	$8, BX
+	CMPQ	CX, DX
+	JEQ	bigloop
+	RET
+
+	// remaining 0-8 bytes
+leftover:
+	MOVQ	-8(SI)(BX*1), CX
+	MOVQ	-8(DI)(BX*1), DX
+	CMPQ	CX, DX
+	SETEQ	AX
+	RET
+
+small:
+	CMPQ	BX, $0
+	JEQ	equal
+
+	LEAQ	0(BX*8), CX
+	NEGQ	CX
+
+	CMPB	SI, $0xf8
+	JA	si_high
+
+	// load at SI won't cross a page boundary.
+	MOVQ	(SI), SI
+	JMP	si_finish
+si_high:
+	// address ends in 11111xxx.  Load up to bytes we want, move to correct position.
+	MOVQ	-8(SI)(BX*1), SI
+	SHRQ	CX, SI
+si_finish:
+
+	// same for DI.
+	CMPB	DI, $0xf8
+	JA	di_high
+	MOVQ	(DI), DI
+	JMP	di_finish
+di_high:
+	MOVQ	-8(DI)(BX*1), DI
+	SHRQ	CX, DI
+di_finish:
+
+	SUBQ	SI, DI
+	SHLQ	CX, DI
+equal:
+	SETEQ	AX
+	RET
diff --git a/src/pkg/runtime/asm_arm.s b/src/pkg/runtime/asm_arm.s
index 6b2d6af..ee9acb7 100644
--- a/src/pkg/runtime/asm_arm.s
+++ b/src/pkg/runtime/asm_arm.s
@@ -326,7 +326,7 @@ TEXT runtime·cgocallback(SB),7,$12
 
 // cgocallback_gofunc(void (*fn)(void*), void *frame, uintptr framesize)
 // See cgocall.c for more details.
-TEXT	runtime·cgocallback_gofunc(SB),7,$16
+TEXT	runtime·cgocallback_gofunc(SB),7,$12
 	// Load m and g from thread-local storage.
 	MOVW	_cgo_load_gm(SB), R0
 	CMP	$0, R0
@@ -337,7 +337,7 @@ TEXT	runtime·cgocallback_gofunc(SB),7,$16
 	// In this case, we're running on the thread stack, so there's
 	// lots of space, but the linker doesn't know. Hide the call from
 	// the linker analysis by using an indirect call.
-	MOVW	m, savedm-16(SP)
+	MOVW	m, savedm-12(SP)
 	CMP	$0, m
 	B.NE havem
 	MOVW	$runtime·needm(SB), R0
@@ -348,10 +348,6 @@ havem:
 	// Save current m->g0->sched.sp on stack and then set it to SP.
 	// Save current sp in m->g0->sched.sp in preparation for
 	// switch back to m->curg stack.
-	MOVW	fn+0(FP), R0
-	MOVW	frame+4(FP), R1
-	MOVW	framesize+8(FP), R2
-
 	MOVW	m_g0(m), R3
 	MOVW	(g_sched+gobuf_sp)(R3), R4
 	MOVW.W	R4, -4(R13)
@@ -368,23 +364,23 @@ havem:
 	// This has the added benefit that it looks to the traceback
 	// routine like cgocallbackg is going to return to that
 	// PC (because we defined cgocallbackg to have
-	// a frame size of 16, the same amount that we use below),
+	// a frame size of 12, the same amount that we use below),
 	// so that the traceback will seamlessly trace back into
 	// the earlier calls.
+	MOVW	fn+4(FP), R0
+	MOVW	frame+8(FP), R1
+	MOVW	framesize+12(FP), R2
 
-	// Save current m->g0->sched.sp on stack and then set it to SP.
 	MOVW	m_curg(m), g
 	MOVW	(g_sched+gobuf_sp)(g), R4 // prepare stack as R4
 
 	// Push gobuf.pc
 	MOVW	(g_sched+gobuf_pc)(g), R5
-	SUB	$4, R4
-	MOVW	R5, 0(R4)
+	MOVW.W	R5, -16(R4)
 
 	// Push arguments to cgocallbackg.
 	// Frame size here must match the frame size above
 	// to trick traceback routines into doing the right thing.
-	SUB	$16, R4
 	MOVW	R0, 4(R4)
 	MOVW	R1, 8(R4)
 	MOVW	R2, 12(R4)
@@ -394,10 +390,10 @@ havem:
 	BL	runtime·cgocallbackg(SB)
 
 	// Restore g->gobuf (== m->curg->gobuf) from saved values.
-	MOVW	16(R13), R5
+	MOVW	0(R13), R5
 	MOVW	R5, (g_sched+gobuf_pc)(g)
-	ADD	$(16+4), R13 // SP clobbered! It is ok!
-	MOVW	R13, (g_sched+gobuf_sp)(g)
+	ADD	$(12+4), R13, R4
+	MOVW	R4, (g_sched+gobuf_sp)(g)
 
 	// Switch back to m->g0's stack and restore m->g0->sched.sp.
 	// (Unlike m->curg, the g0 goroutine never uses sched.pc,
@@ -411,7 +407,7 @@ havem:
 
 	// If the m on entry was nil, we called needm above to borrow an m
 	// for the duration of the call. Since the call is over, return it with dropm.
-	MOVW	savedm-16(SP), R6
+	MOVW	savedm-12(SP), R6
 	CMP	$0, R6
 	B.NE	3(PC)
 	MOVW	$runtime·dropm(SB), R0
@@ -491,7 +487,7 @@ TEXT runtime·stackguard(SB),7,$0
 	MOVW	R2, limit+4(FP)
 	RET
 
-// not implemented for ARM
+// AES hashing not implemented for ARM
 TEXT runtime·aeshash(SB),7,$-4
 	MOVW	$0, R0
 	MOVW	(R0), R1
@@ -504,3 +500,20 @@ TEXT runtime·aeshash64(SB),7,$-4
 TEXT runtime·aeshashstr(SB),7,$-4
 	MOVW	$0, R0
 	MOVW	(R0), R1
+
+TEXT runtime·memeq(SB),7,$-4
+	MOVW	a+0(FP), R1
+	MOVW	b+4(FP), R2
+	MOVW	n+8(FP), R3
+	ADD	R1, R3, R6
+	MOVW	$1, R0
+_next:
+	CMP	R1, R6
+	RET.EQ
+	MOVBU.P	1(R1), R4
+	MOVBU.P	1(R2), R5
+	CMP	R4, R5
+	BEQ	_next
+
+	MOVW	$0, R0
+	RET
diff --git a/src/pkg/runtime/cgo/gcc_freebsd_386.c b/src/pkg/runtime/cgo/gcc_freebsd_386.c
index 7c62a1b..6797824 100644
--- a/src/pkg/runtime/cgo/gcc_freebsd_386.c
+++ b/src/pkg/runtime/cgo/gcc_freebsd_386.c
@@ -10,13 +10,15 @@
 #include "libcgo.h"
 
 static void* threadentry(void*);
+static void (*setmg_gcc)(void*, void*);
 
 void
-x_cgo_init(G *g)
+x_cgo_init(G *g, void (*setmg)(void*, void*))
 {
 	pthread_attr_t attr;
 	size_t size;
 
+	setmg_gcc = setmg;
 	pthread_attr_init(&attr);
 	pthread_attr_getstacksize(&attr, &size);
 	g->stackguard = (uintptr)&attr - size + 4096;
@@ -66,15 +68,9 @@ threadentry(void *v)
 	ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
 
 	/*
-	 * Set specific keys.  On FreeBSD/ELF, the thread local storage
-	 * is just before %gs:0.  Our dynamic 8.out's reserve 8 bytes
-	 * for the two words g and m at %gs:-8 and %gs:-4.
+	 * Set specific keys.
 	 */
-	asm volatile (
-		"movl %0, %%gs:-8\n"	// MOVL g, -8(GS)
-		"movl %1, %%gs:-4\n"	// MOVL m, -4(GS)
-		:: "r"(ts.g), "r"(ts.m)
-	);
+	setmg_gcc((void*)ts.m, (void*)ts.g);
 
 	crosscall_386(ts.fn);
 	return nil;
diff --git a/src/pkg/runtime/cgo/gcc_freebsd_amd64.c b/src/pkg/runtime/cgo/gcc_freebsd_amd64.c
index 6be8bd2..eb342a2 100644
--- a/src/pkg/runtime/cgo/gcc_freebsd_amd64.c
+++ b/src/pkg/runtime/cgo/gcc_freebsd_amd64.c
@@ -10,20 +10,21 @@
 #include "libcgo.h"
 
 static void* threadentry(void*);
+static void (*setmg_gcc)(void*, void*);
 
 void
-x_cgo_init(G *g)
+x_cgo_init(G *g, void (*setmg)(void*, void*))
 {
 	pthread_attr_t attr;
 	size_t size;
 
+	setmg_gcc = setmg;
 	pthread_attr_init(&attr);
 	pthread_attr_getstacksize(&attr, &size);
 	g->stackguard = (uintptr)&attr - size + 4096;
 	pthread_attr_destroy(&attr);
 }
 
-
 void
 _cgo_sys_thread_start(ThreadStart *ts)
 {
@@ -67,15 +68,10 @@ threadentry(void *v)
 	ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
 
 	/*
-	 * Set specific keys.  On FreeBSD/ELF, the thread local storage
-	 * is just before %fs:0.  Our dynamic 6.out's reserve 16 bytes
-	 * for the two words g and m at %fs:-16 and %fs:-8.
+	 * Set specific keys.
 	 */
-	asm volatile (
-		"movq %0, %%fs:-16\n"	// MOVL g, -16(FS)
-		"movq %1, %%fs:-8\n"	// MOVL m, -8(FS)
-		:: "r"(ts.g), "r"(ts.m)
-	);
+	setmg_gcc((void*)ts.m, (void*)ts.g);
+
 	crosscall_amd64(ts.fn);
 	return nil;
 }
diff --git a/src/pkg/runtime/cgo/gcc_linux_386.c b/src/pkg/runtime/cgo/gcc_linux_386.c
index 9357a63..c25c7b7 100644
--- a/src/pkg/runtime/cgo/gcc_linux_386.c
+++ b/src/pkg/runtime/cgo/gcc_linux_386.c
@@ -8,13 +8,15 @@
 #include "libcgo.h"
 
 static void *threadentry(void*);
+static void (*setmg_gcc)(void*, void*);
 
 void
-x_cgo_init(G *g)
+x_cgo_init(G *g, void (*setmg)(void*, void*))
 {
 	pthread_attr_t attr;
 	size_t size;
 
+	setmg_gcc = setmg;
 	pthread_attr_init(&attr);
 	pthread_attr_getstacksize(&attr, &size);
 	g->stackguard = (uintptr)&attr - size + 4096;
@@ -69,18 +71,9 @@ threadentry(void *v)
 	ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
 
 	/*
-	 * Set specific keys.  On Linux/ELF, the thread local storage
-	 * is just before %gs:0.  Our dynamic 8.out's reserve 8 bytes
-	 * for the two words g and m at %gs:-8 and %gs:-4.
-	 * Xen requires us to access those words indirect from %gs:0
-	 * which points at itself.
+	 * Set specific keys.
 	 */
-	asm volatile (
-		"movl %%gs:0, %%eax\n"		// MOVL 0(GS), tmp
-		"movl %0, -8(%%eax)\n"	// MOVL g, -8(GS)
-		"movl %1, -4(%%eax)\n"	// MOVL m, -4(GS)
-		:: "r"(ts.g), "r"(ts.m) : "%eax"
-	);
+	setmg_gcc((void*)ts.m, (void*)ts.g);
 
 	crosscall_386(ts.fn);
 	return nil;
diff --git a/src/pkg/runtime/cgo/gcc_linux_amd64.c b/src/pkg/runtime/cgo/gcc_linux_amd64.c
index bc76117..bd7c88d 100644
--- a/src/pkg/runtime/cgo/gcc_linux_amd64.c
+++ b/src/pkg/runtime/cgo/gcc_linux_amd64.c
@@ -8,13 +8,15 @@
 #include "libcgo.h"
 
 static void* threadentry(void*);
+static void (*setmg_gcc)(void*, void*);
 
 void
-x_cgo_init(G* g)
+x_cgo_init(G* g, void (*setmg)(void*, void*))
 {
 	pthread_attr_t attr;
 	size_t size;
 
+	setmg_gcc = setmg;
 	pthread_attr_init(&attr);
 	pthread_attr_getstacksize(&attr, &size);
 	g->stackguard = (uintptr)&attr - size + 4096;
@@ -64,15 +66,10 @@ threadentry(void *v)
 	ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
 
 	/*
-	 * Set specific keys.  On Linux/ELF, the thread local storage
-	 * is just before %fs:0.  Our dynamic 6.out's reserve 16 bytes
-	 * for the two words g and m at %fs:-16 and %fs:-8.
+	 * Set specific keys.
 	 */
-	asm volatile (
-		"movq %0, %%fs:-16\n"	// MOVL g, -16(FS)
-		"movq %1, %%fs:-8\n"	// MOVL m, -8(FS)
-		:: "r"(ts.g), "r"(ts.m)
-	);
+	setmg_gcc((void*)ts.m, (void*)ts.g);
+
 	crosscall_amd64(ts.fn);
 	return nil;
 }
diff --git a/src/pkg/runtime/cgo/gcc_netbsd_386.c b/src/pkg/runtime/cgo/gcc_netbsd_386.c
index 09b271d..b399e16 100644
--- a/src/pkg/runtime/cgo/gcc_netbsd_386.c
+++ b/src/pkg/runtime/cgo/gcc_netbsd_386.c
@@ -9,13 +9,15 @@
 #include "libcgo.h"
 
 static void* threadentry(void*);
+static void (*setmg_gcc)(void*, void*);
 
 void
-x_cgo_init(G *g)
+x_cgo_init(G *g, void (*setmg)(void*, void*))
 {
 	pthread_attr_t attr;
 	size_t size;
 
+	setmg_gcc = setmg;
 	pthread_attr_init(&attr);
 	pthread_attr_getstacksize(&attr, &size);
 	g->stackguard = (uintptr)&attr - size + 4096;
@@ -65,15 +67,9 @@ threadentry(void *v)
 	ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
 
 	/*
-	 * Set specific keys.  On NetBSD/ELF, the thread local storage
-	 * is just before %gs:0.  Our dynamic 8.out's reserve 8 bytes
-	 * for the two words g and m at %gs:-8 and %gs:-4.
+	 * Set specific keys.
 	 */
-	asm volatile (
-		"movl %0, %%gs:-8\n"	// MOVL g, -8(GS)
-		"movl %1, %%gs:-4\n"	// MOVL m, -4(GS)
-		:: "r"(ts.g), "r"(ts.m)
-	);
+	setmg_gcc((void*)ts.m, (void*)ts.g);
 
 	crosscall_386(ts.fn);
 	return nil;
diff --git a/src/pkg/runtime/cgo/gcc_netbsd_amd64.c b/src/pkg/runtime/cgo/gcc_netbsd_amd64.c
index 080c59b..f27e142 100644
--- a/src/pkg/runtime/cgo/gcc_netbsd_amd64.c
+++ b/src/pkg/runtime/cgo/gcc_netbsd_amd64.c
@@ -9,13 +9,15 @@
 #include "libcgo.h"
 
 static void* threadentry(void*);
+static void (*setmg_gcc)(void*, void*);
 
 void
-x_cgo_init(G *g)
+x_cgo_init(G *g, void (*setmg)(void*, void*))
 {
 	pthread_attr_t attr;
 	size_t size;
 
+	setmg_gcc = setmg;
 	pthread_attr_init(&attr);
 	pthread_attr_getstacksize(&attr, &size);
 	g->stackguard = (uintptr)&attr - size + 4096;
@@ -66,15 +68,10 @@ threadentry(void *v)
 	ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
 
 	/*
-	 * Set specific keys.  On NetBSD/ELF, the thread local storage
-	 * is just before %fs:0.  Our dynamic 6.out's reserve 16 bytes
-	 * for the two words g and m at %fs:-16 and %fs:-8.
+	 * Set specific keys.
 	 */
-	asm volatile (
-		"movq %0, %%fs:-16\n"	// MOVL g, -16(FS)
-		"movq %1, %%fs:-8\n"	// MOVL m, -8(FS)
-		:: "r"(ts.g), "r"(ts.m)
-	);
+	setmg_gcc((void*)ts.m, (void*)ts.g);
+
 	crosscall_amd64(ts.fn);
 	return nil;
 }
diff --git a/src/pkg/runtime/cgo/gcc_openbsd_386.c b/src/pkg/runtime/cgo/gcc_openbsd_386.c
index 80be31b..6422d1b 100644
--- a/src/pkg/runtime/cgo/gcc_openbsd_386.c
+++ b/src/pkg/runtime/cgo/gcc_openbsd_386.c
@@ -11,6 +11,7 @@
 #include "libcgo.h"
 
 static void* threadentry(void*);
+static void (*setmg_gcc)(void*, void*);
 
 // TCB_SIZE is sizeof(struct thread_control_block),
 // as defined in /usr/src/lib/librthread/tcb.h
@@ -82,12 +83,13 @@ pthread_create(pthread_t *thread, const pthread_attr_t *attr,
 }
 
 void
-x_cgo_init(G *g)
+x_cgo_init(G *g, void (*setmg)(void*, void*))
 {
 	pthread_attr_t attr;
 	size_t size;
 	void *handle;
 
+	setmg_gcc = setmg;
 	pthread_attr_init(&attr);
 	pthread_attr_getstacksize(&attr, &size);
 	g->stackguard = (uintptr)&attr - size + 4096;
@@ -154,15 +156,9 @@ threadentry(void *v)
 	ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
 
 	/*
-	 * Set specific keys.  On OpenBSD/ELF, the thread local storage
-	 * is just before %gs:0.  Our dynamic 8.out's reserve 8 bytes
-	 * for the two words g and m at %gs:-8 and %gs:-4.
+	 * Set specific keys.
 	 */
-	asm volatile (
-		"movl %0, %%gs:-8\n"	// MOVL g, -8(GS)
-		"movl %1, %%gs:-4\n"	// MOVL m, -4(GS)
-		:: "r"(ts.g), "r"(ts.m)
-	);
+	setmg_gcc((void*)ts.m, (void*)ts.g);
 
 	crosscall_386(ts.fn);
 	return nil;
diff --git a/src/pkg/runtime/cgo/gcc_openbsd_amd64.c b/src/pkg/runtime/cgo/gcc_openbsd_amd64.c
index e9cc818..5a5a171 100644
--- a/src/pkg/runtime/cgo/gcc_openbsd_amd64.c
+++ b/src/pkg/runtime/cgo/gcc_openbsd_amd64.c
@@ -11,6 +11,7 @@
 #include "libcgo.h"
 
 static void* threadentry(void*);
+static void (*setmg_gcc)(void*, void*);
 
 // TCB_SIZE is sizeof(struct thread_control_block),
 // as defined in /usr/src/lib/librthread/tcb.h
@@ -82,12 +83,13 @@ pthread_create(pthread_t *thread, const pthread_attr_t *attr,
 }
 
 void
-x_cgo_init(G *g)
+x_cgo_init(G *g, void (*setmg)(void*, void*))
 {
 	pthread_attr_t attr;
 	size_t size;
 	void *handle;
 
+	setmg_gcc = setmg;
 	pthread_attr_init(&attr);
 	pthread_attr_getstacksize(&attr, &size);
 	g->stackguard = (uintptr)&attr - size + 4096;
@@ -155,15 +157,10 @@ threadentry(void *v)
 	ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
 
 	/*
-	 * Set specific keys.  On OpenBSD/ELF, the thread local storage
-	 * is just before %fs:0.  Our dynamic 6.out's reserve 16 bytes
-	 * for the two words g and m at %fs:-16 and %fs:-8.
+	 * Set specific keys.
 	 */
-	asm volatile (
-		"movq %0, %%fs:-16\n"	// MOVL g, -16(FS)
-		"movq %1, %%fs:-8\n"	// MOVL m, -8(FS)
-		:: "r"(ts.g), "r"(ts.m)
-	);
+	setmg_gcc((void*)ts.m, (void*)ts.g);
+
 	crosscall_amd64(ts.fn);
 	return nil;
 }
diff --git a/src/pkg/runtime/cgocall.c b/src/pkg/runtime/cgocall.c
index 0c96187..b829665 100644
--- a/src/pkg/runtime/cgocall.c
+++ b/src/pkg/runtime/cgocall.c
@@ -98,6 +98,15 @@ static void unwindm(void);
 static void endcgo(void);
 static FuncVal endcgoV = { endcgo };
 
+// Gives a hint that the next syscall
+// executed by the current goroutine will block.
+// Currently used only on windows.
+void
+net·runtime_blockingSyscallHint(void)
+{
+	g->blockingsyscall = true;
+}
+
 void
 runtime·cgocall(void (*fn)(void*), void *arg)
 {
@@ -145,7 +154,11 @@ runtime·cgocall(void (*fn)(void*), void *arg)
 	 * so it is safe to call while "in a system call", outside
 	 * the $GOMAXPROCS accounting.
 	 */
-	runtime·entersyscall();
+	if(g->blockingsyscall) {
+		g->blockingsyscall = false;
+		runtime·entersyscallblock();
+	} else
+		runtime·entersyscall();
 	runtime·asmcgocall(fn, arg);
 	runtime·exitsyscall();
 
diff --git a/src/pkg/runtime/gc_test.go b/src/pkg/runtime/gc_test.go
index 3475339..26fc77d 100644
--- a/src/pkg/runtime/gc_test.go
+++ b/src/pkg/runtime/gc_test.go
@@ -13,7 +13,7 @@ import (
 
 func TestGcSys(t *testing.T) {
 	if os.Getenv("GOGC") == "off" {
-		t.Fatalf("GOGC=off in environment; test cannot pass")
+		t.Skip("skipping test; GOGC=off in environment")
 	}
 	data := struct{ Short bool }{testing.Short()}
 	got := executeTest(t, testGCSysSource, &data)
diff --git a/src/pkg/runtime/hashmap.c b/src/pkg/runtime/hashmap.c
index 0f92bec..4ebfffd 100644
--- a/src/pkg/runtime/hashmap.c
+++ b/src/pkg/runtime/hashmap.c
@@ -74,9 +74,9 @@
 typedef struct Bucket Bucket;
 struct Bucket
 {
-	uint8 tophash[BUCKETSIZE];  // top 8 bits of hash of each entry (0 = empty)
+	uint8  tophash[BUCKETSIZE]; // top 8 bits of hash of each entry (0 = empty)
 	Bucket *overflow;           // overflow bucket, if any
-	byte data[1];               // BUCKETSIZE keys followed by BUCKETSIZE values
+	byte   data[1];             // BUCKETSIZE keys followed by BUCKETSIZE values
 };
 // NOTE: packing all the keys together and then all the values together makes the
 // code a bit more complicated than alternating key/value/key/value/... but it allows
@@ -102,7 +102,7 @@ struct Hmap
 	uint16  bucketsize;   // bucket size in bytes
 
 	uintptr hash0;        // hash seed
-	byte    *buckets;     // array of 2^B Buckets
+	byte    *buckets;     // array of 2^B Buckets. may be nil if count==0.
 	byte    *oldbuckets;  // previous bucket array of half the size, non-nil only when growing
 	uintptr nevacuate;    // progress counter for evacuation (buckets less than this have been evacuated)
 };
@@ -126,6 +126,7 @@ enum
 {
 	docheck = 0,  // check invariants before and after every op.  Slow!!!
 	debug = 0,    // print every operation
+	checkgc = 0 || docheck,  // check interaction of mallocgc() with the garbage collector
 };
 static void
 check(MapType *t, Hmap *h)
@@ -221,7 +222,7 @@ hash_init(MapType *t, Hmap *h, uint32 hint)
 		keysize = sizeof(byte*);
 	}
 	valuesize = t->elem->size;
-	if(valuesize >= MAXVALUESIZE) {
+	if(valuesize > MAXVALUESIZE) {
 		flags |= IndirectValue;
 		valuesize = sizeof(byte*);
 	}
@@ -253,10 +254,16 @@ hash_init(MapType *t, Hmap *h, uint32 hint)
 
 	// allocate initial hash table
 	// If hint is large zeroing this memory could take a while.
-	buckets = runtime·mallocgc(bucketsize << B, 0, 1, 0);
-	for(i = 0; i < (uintptr)1 << B; i++) {
-		b = (Bucket*)(buckets + i * bucketsize);
-		clearbucket(b);
+	if(checkgc) mstats.next_gc = mstats.heap_alloc;
+	if(B == 0) {
+		// done lazily later.
+		buckets = nil;
+	} else {
+		buckets = runtime·mallocgc(bucketsize << B, 0, 1, 0);
+		for(i = 0; i < (uintptr)1 << B; i++) {
+			b = (Bucket*)(buckets + i * bucketsize);
+			clearbucket(b);
+		}
 	}
 
 	// initialize Hmap
@@ -322,6 +329,7 @@ evacuate(MapType *t, Hmap *h, uintptr oldbucket)
 				// the B'th bit of the hash in this case.
 				if((hash & newbit) == 0) {
 					if(xi == BUCKETSIZE) {
+						if(checkgc) mstats.next_gc = mstats.heap_alloc;
 						newx = runtime·mallocgc(h->bucketsize, 0, 1, 0);
 						clearbucket(newx);
 						x->overflow = newx;
@@ -346,6 +354,7 @@ evacuate(MapType *t, Hmap *h, uintptr oldbucket)
 					xv += h->valuesize;
 				} else {
 					if(yi == BUCKETSIZE) {
+						if(checkgc) mstats.next_gc = mstats.heap_alloc;
 						newy = runtime·mallocgc(h->bucketsize, 0, 1, 0);
 						clearbucket(newy);
 						y->overflow = newy;
@@ -441,6 +450,7 @@ hash_grow(MapType *t, Hmap *h)
 		runtime·throw("evacuation not done in time");
 	old_buckets = h->buckets;
 	// NOTE: this could be a big malloc, but since we don't need zeroing it is probably fast.
+	if(checkgc) mstats.next_gc = mstats.heap_alloc;
 	new_buckets = runtime·mallocgc(h->bucketsize << (h->B + 1), 0, 1, 0);
 	flags = (h->flags & ~(Iterator | OldIterator));
 	if((h->flags & Iterator) != 0) {
@@ -470,7 +480,7 @@ hash_lookup(MapType *t, Hmap *h, byte **keyp)
 {
 	void *key;
 	uintptr hash;
-	uintptr bucket;
+	uintptr bucket, oldbucket;
 	Bucket *b;
 	uint8 top;
 	uintptr i;
@@ -480,12 +490,20 @@ hash_lookup(MapType *t, Hmap *h, byte **keyp)
 	key = *keyp;
 	if(docheck)
 		check(t, h);
+	if(h->count == 0)
+		return nil;
 	hash = h->hash0;
 	t->key->alg->hash(&hash, t->key->size, key);
 	bucket = hash & (((uintptr)1 << h->B) - 1);
-	if(h->oldbuckets != nil)
-		grow_work(t, h, bucket);
-	b = (Bucket*)(h->buckets + bucket * h->bucketsize);
+	if(h->oldbuckets != nil) {
+		oldbucket = bucket & (((uintptr)1 << (h->B - 1)) - 1);
+		b = (Bucket*)(h->oldbuckets + oldbucket * h->bucketsize);
+		if(evacuated(b)) {
+			b = (Bucket*)(h->buckets + bucket * h->bucketsize);
+		}
+	} else {
+		b = (Bucket*)(h->buckets + bucket * h->bucketsize);
+	}
 	top = hash >> (sizeof(uintptr)*8 - 8);
 	if(top == 0)
 		top = 1;
@@ -509,12 +527,14 @@ hash_lookup(MapType *t, Hmap *h, byte **keyp)
 static uint8 empty_value[MAXVALUESIZE];
 
 // Specialized versions of mapaccess1 for specific types.
-// See ./hashmap_fast and ../../cmd/gc/walk.c.
+// See ./hashmap_fast.c and ../../cmd/gc/walk.c.
 #define HASH_LOOKUP1 runtime·mapaccess1_fast32
 #define HASH_LOOKUP2 runtime·mapaccess2_fast32
 #define KEYTYPE uint32
 #define HASHFUNC runtime·algarray[AMEM32].hash
 #define EQFUNC(x,y) ((x) == (y))
+#define EQMAYBE(x,y) ((x) == (y))
+#define HASMAYBE false
 #define QUICKEQ(x) true
 #include "hashmap_fast.c"
 
@@ -523,6 +543,8 @@ static uint8 empty_value[MAXVALUESIZE];
 #undef KEYTYPE
 #undef HASHFUNC
 #undef EQFUNC
+#undef EQMAYBE
+#undef HASMAYBE
 #undef QUICKEQ
 
 #define HASH_LOOKUP1 runtime·mapaccess1_fast64
@@ -530,6 +552,8 @@ static uint8 empty_value[MAXVALUESIZE];
 #define KEYTYPE uint64
 #define HASHFUNC runtime·algarray[AMEM64].hash
 #define EQFUNC(x,y) ((x) == (y))
+#define EQMAYBE(x,y) ((x) == (y))
+#define HASMAYBE false
 #define QUICKEQ(x) true
 #include "hashmap_fast.c"
 
@@ -538,13 +562,17 @@ static uint8 empty_value[MAXVALUESIZE];
 #undef KEYTYPE
 #undef HASHFUNC
 #undef EQFUNC
+#undef EQMAYBE
+#undef HASMAYBE
 #undef QUICKEQ
 
 #define HASH_LOOKUP1 runtime·mapaccess1_faststr
 #define HASH_LOOKUP2 runtime·mapaccess2_faststr
 #define KEYTYPE String
 #define HASHFUNC runtime·algarray[ASTRING].hash
-#define EQFUNC(x,y) ((x).len == (y).len && ((x).str == (y).str || runtime·mcmp((x).str, (y).str, (x).len) == 0))
+#define EQFUNC(x,y) ((x).len == (y).len && ((x).str == (y).str || runtime·memeq((x).str, (y).str, (x).len)))
+#define EQMAYBE(x,y) ((x).len == (y).len)
+#define HASMAYBE true
 #define QUICKEQ(x) ((x).len < 32)
 #include "hashmap_fast.c"
 
@@ -567,6 +595,12 @@ hash_insert(MapType *t, Hmap *h, void *key, void *value)
 		check(t, h);
 	hash = h->hash0;
 	t->key->alg->hash(&hash, t->key->size, key);
+	if(h->buckets == nil) {
+		h->buckets = runtime·mallocgc(h->bucketsize, 0, 1, 0);
+		b = (Bucket*)(h->buckets);
+		clearbucket(b);
+	}
+
  again:
 	bucket = hash & (((uintptr)1 << h->B) - 1);
 	if(h->oldbuckets != nil)
@@ -611,6 +645,7 @@ hash_insert(MapType *t, Hmap *h, void *key, void *value)
 
 	if(inserti == nil) {
 		// all current buckets are full, allocate a new one.
+		if(checkgc) mstats.next_gc = mstats.heap_alloc;
 		newb = runtime·mallocgc(h->bucketsize, 0, 1, 0);
 		clearbucket(newb);
 		b->overflow = newb;
@@ -621,11 +656,13 @@ hash_insert(MapType *t, Hmap *h, void *key, void *value)
 
 	// store new key/value at insert position
 	if((h->flags & IndirectKey) != 0) {
+		if(checkgc) mstats.next_gc = mstats.heap_alloc;
 		kmem = runtime·mallocgc(t->key->size, 0, 1, 0);
 		*(byte**)insertk = kmem;
 		insertk = kmem;
 	}
 	if((h->flags & IndirectValue) != 0) {
+		if(checkgc) mstats.next_gc = mstats.heap_alloc;
 		vmem = runtime·mallocgc(t->elem->size, 0, 1, 0);
 		*(byte**)insertv = vmem;
 		insertv = vmem;
@@ -651,6 +688,8 @@ hash_remove(MapType *t, Hmap *h, void *key)
 	
 	if(docheck)
 		check(t, h);
+	if(h->count == 0)
+		return;
 	hash = h->hash0;
 	t->key->alg->hash(&hash, t->key->size, key);
 	bucket = hash & (((uintptr)1 << h->B) - 1);
@@ -718,6 +757,7 @@ struct hash_iter
 	uintptr bucket;
 	struct Bucket *bptr;
 	uintptr i;
+	intptr check_bucket;
 };
 
 // iterator state:
@@ -727,6 +767,9 @@ struct hash_iter
 static void
 hash_iter_init(MapType *t, Hmap *h, struct hash_iter *it)
 {
+	if(sizeof(struct hash_iter) / sizeof(uintptr) != 11) {
+		runtime·throw("hash_iter size incorrect"); // see ../../cmd/gc/range.c
+	}
 	it->t = t;
 	it->h = h;
 
@@ -739,8 +782,14 @@ hash_iter_init(MapType *t, Hmap *h, struct hash_iter *it)
 	it->wrapped = false;
 	it->bptr = nil;
 
-	// Remember we have an iterator at this level.
-	h->flags |= Iterator;
+	// Remember we have an iterator.
+	h->flags |= Iterator | OldIterator;  // careful: see issue 5120.
+
+	if(h->buckets == nil) {
+		// Empty map. Force next hash_next to exit without
+		// evalulating h->bucket.
+		it->wrapped = true;
+	}
 }
 
 // initializes it->key and it->value to the next key/value pair
@@ -750,9 +799,11 @@ hash_next(struct hash_iter *it)
 {
 	Hmap *h;
 	MapType *t;
-	uintptr bucket;
+	uintptr bucket, oldbucket;
+	uintptr hash;
 	Bucket *b;
 	uintptr i;
+	intptr check_bucket;
 	bool eq;
 	byte *k, *v;
 	byte *rk, *rv;
@@ -762,6 +813,7 @@ hash_next(struct hash_iter *it)
 	bucket = it->bucket;
 	b = it->bptr;
 	i = it->i;
+	check_bucket = it->check_bucket;
 
 next:
 	if(b == nil) {
@@ -773,10 +825,21 @@ next:
 		}
 		if(h->oldbuckets != nil && it->B == h->B) {
 			// Iterator was started in the middle of a grow, and the grow isn't done yet.
-			// Make sure the bucket we're about to read is valid.
-			grow_work(t, h, bucket);
+			// If the bucket we're looking at hasn't been filled in yet (i.e. the old
+			// bucket hasn't been evacuated) then we need to iterate through the old
+			// bucket and only return the ones that will be migrated to this bucket.
+			oldbucket = bucket & (((uintptr)1 << (it->B - 1)) - 1);
+			b = (Bucket*)(h->oldbuckets + oldbucket * h->bucketsize);
+			if(!evacuated(b)) {
+				check_bucket = bucket;
+			} else {
+				b = (Bucket*)(it->buckets + bucket * h->bucketsize);
+				check_bucket = -1;
+			}
+		} else {
+			b = (Bucket*)(it->buckets + bucket * h->bucketsize);
+			check_bucket = -1;
 		}
-		b = (Bucket*)(it->buckets + bucket * h->bucketsize);
 		bucket++;
 		if(bucket == ((uintptr)1 << it->B)) {
 			bucket = 0;
@@ -788,6 +851,30 @@ next:
 	v = b->data + h->keysize * BUCKETSIZE + h->valuesize * i;
 	for(; i < BUCKETSIZE; i++, k += h->keysize, v += h->valuesize) {
 		if(b->tophash[i] != 0) {
+			if(check_bucket >= 0) {
+				// Special case: iterator was started during a grow and the
+				// grow is not done yet.  We're working on a bucket whose
+				// oldbucket has not been evacuated yet.  So we iterate
+				// through the oldbucket, skipping any keys that will go
+				// to the other new bucket (each oldbucket expands to two
+				// buckets during a grow).
+				t->key->alg->equal(&eq, t->key->size, IK(h, k), IK(h, k));
+				if(!eq) {
+					// Hash is meaningless if k != k (NaNs).  Return all
+					// NaNs during the first of the two new buckets.
+					if(bucket >= ((uintptr)1 << (it->B - 1))) {
+						continue;
+					}
+				} else {
+					// If the item in the oldbucket is not destined for
+					// the current new bucket in the iteration, skip it.
+					hash = h->hash0;
+					t->key->alg->hash(&hash, t->key->size, IK(h, k));
+					if((hash & (((uintptr)1 << it->B) - 1)) != check_bucket) {
+						continue;
+					}
+				}
+			}
 			if(!evacuated(b)) {
 				// this is the golden data, we can return it.
 				it->key = IK(h, k);
@@ -820,6 +907,7 @@ next:
 			it->bucket = bucket;
 			it->bptr = b;
 			it->i = i + 1;
+			it->check_bucket = check_bucket;
 			return;
 		}
 	}
@@ -840,7 +928,7 @@ next:
 bool
 hash_gciter_init (Hmap *h, struct hash_gciter *it)
 {
-	// GC during map initialization
+	// GC during map initialization or on an empty map.
 	if(h->buckets == nil)
 		return false;
 
@@ -983,6 +1071,13 @@ next:
 /// interfaces to go runtime
 //
 
+void
+reflect·ismapkey(Type *typ, bool ret)
+{
+	ret = typ != nil && typ->alg->hash != runtime·nohash;
+	FLUSH(&ret);
+}
+
 Hmap*
 runtime·makemap_c(MapType *typ, int64 hint)
 {
diff --git a/src/pkg/runtime/hashmap_fast.c b/src/pkg/runtime/hashmap_fast.c
index 2169f4c..afff7b1 100644
--- a/src/pkg/runtime/hashmap_fast.c
+++ b/src/pkg/runtime/hashmap_fast.c
@@ -17,12 +17,14 @@ void
 HASH_LOOKUP1(MapType *t, Hmap *h, KEYTYPE key, byte *value)
 {
 	uintptr hash;
-	uintptr bucket;
+	uintptr bucket, oldbucket;
 	Bucket *b;
-	uint8 top;
 	uintptr i;
 	KEYTYPE *k;
 	byte *v;
+	uint8 top;
+	int8 keymaybe;
+	bool quickkey;
 
 	if(debug) {
 		runtime·prints("runtime.mapaccess1_fastXXX: map=");
@@ -41,23 +43,55 @@ HASH_LOOKUP1(MapType *t, Hmap *h, KEYTYPE key, byte *value)
 	if(docheck)
 		check(t, h);
 
-	if(h->B == 0 && (h->count == 1 || QUICKEQ(key))) {
-		// One-bucket table.  Don't hash, just check each bucket entry.
+	if(h->B == 0) {
+		// One-bucket table. Don't hash, just check each bucket entry.
+		if(HASMAYBE) {
+			keymaybe = -1;
+		}
+		quickkey = QUICKEQ(key);
 		b = (Bucket*)h->buckets;
 		for(i = 0, k = (KEYTYPE*)b->data, v = (byte*)(k + BUCKETSIZE); i < BUCKETSIZE; i++, k++, v += h->valuesize) {
-			if(b->tophash[i] != 0 && EQFUNC(key, *k)) {
-				value = v;
+			if(b->tophash[i] != 0) {
+				if(quickkey && EQFUNC(key, *k)) {
+					value = v;
+					FLUSH(&value);
+					return;
+				}
+				if(HASMAYBE && EQMAYBE(key, *k)) {
+					// TODO: check if key.str matches. Add EQFUNCFAST?
+					if(keymaybe >= 0) {
+						// Two same-length strings in this bucket.
+						// use slow path.
+						// TODO: keep track of more than just 1. Especially
+						// if doing the TODO above.
+						goto dohash;
+					}
+					keymaybe = i;
+				}
+			}
+		}
+		if(HASMAYBE && keymaybe >= 0) {
+			k = (KEYTYPE*)b->data + keymaybe;
+			if(EQFUNC(key, *k)) {
+				value = (byte*)((KEYTYPE*)b->data + BUCKETSIZE) + keymaybe * h->valuesize;
 				FLUSH(&value);
 				return;
 			}
 		}
 	} else {
+dohash:
 		hash = h->hash0;
 		HASHFUNC(&hash, sizeof(KEYTYPE), &key);
 		bucket = hash & (((uintptr)1 << h->B) - 1);
-		if(h->oldbuckets != nil)
-			grow_work(t, h, bucket);
-		b = (Bucket*)(h->buckets + bucket * (offsetof(Bucket, data[0]) + BUCKETSIZE * sizeof(KEYTYPE) + BUCKETSIZE * h->valuesize));
+		if(h->oldbuckets != nil) {
+			oldbucket = bucket & (((uintptr)1 << (h->B - 1)) - 1);
+			b = (Bucket*)(h->oldbuckets + oldbucket * h->bucketsize);
+			if(evacuated(b)) {
+				b = (Bucket*)(h->buckets + bucket * h->bucketsize);
+			}
+		} else {
+			b = (Bucket*)(h->buckets + bucket * h->bucketsize);
+		}
 		top = hash >> (sizeof(uintptr)*8 - 8);
 		if(top == 0)
 			top = 1;
@@ -81,12 +115,14 @@ void
 HASH_LOOKUP2(MapType *t, Hmap *h, KEYTYPE key, byte *value, bool res)
 {
 	uintptr hash;
-	uintptr bucket;
+	uintptr bucket, oldbucket;
 	Bucket *b;
-	uint8 top;
 	uintptr i;
 	KEYTYPE *k;
 	byte *v;
+	uint8 top;
+	int8 keymaybe;
+	bool quickkey;
 
 	if(debug) {
 		runtime·prints("runtime.mapaccess2_fastXXX: map=");
@@ -107,12 +143,39 @@ HASH_LOOKUP2(MapType *t, Hmap *h, KEYTYPE key, byte *value, bool res)
 	if(docheck)
 		check(t, h);
 
-	if(h->B == 0 && (h->count == 1 || QUICKEQ(key))) {
+	if(h->B == 0) {
 		// One-bucket table.  Don't hash, just check each bucket entry.
+		if(HASMAYBE) {
+			keymaybe = -1;
+		}
+		quickkey = QUICKEQ(key);
 		b = (Bucket*)h->buckets;
 		for(i = 0, k = (KEYTYPE*)b->data, v = (byte*)(k + BUCKETSIZE); i < BUCKETSIZE; i++, k++, v += h->valuesize) {
-			if(b->tophash[i] != 0 && EQFUNC(key, *k)) {
-				value = v;
+			if(b->tophash[i] != 0) {
+				if(quickkey && EQFUNC(key, *k)) {
+					value = v;
+					res = true;
+					FLUSH(&value);
+					FLUSH(&res);
+					return;
+				}
+				if(HASMAYBE && EQMAYBE(key, *k)) {
+					// TODO: check if key.str matches. Add EQFUNCFAST?
+					if(keymaybe >= 0) {
+						// Two same-length strings in this bucket.
+						// use slow path.
+						// TODO: keep track of more than just 1. Especially
+						// if doing the TODO above.
+						goto dohash;
+					}
+					keymaybe = i;
+				}
+			}
+		}
+		if(HASMAYBE && keymaybe >= 0) {
+			k = (KEYTYPE*)b->data + keymaybe;
+			if(EQFUNC(key, *k)) {
+				value = (byte*)((KEYTYPE*)b->data + BUCKETSIZE) + keymaybe * h->valuesize;
 				res = true;
 				FLUSH(&value);
 				FLUSH(&res);
@@ -120,12 +183,19 @@ HASH_LOOKUP2(MapType *t, Hmap *h, KEYTYPE key, byte *value, bool res)
 			}
 		}
 	} else {
+dohash:
 		hash = h->hash0;
 		HASHFUNC(&hash, sizeof(KEYTYPE), &key);
 		bucket = hash & (((uintptr)1 << h->B) - 1);
-		if(h->oldbuckets != nil)
-			grow_work(t, h, bucket);
-		b = (Bucket*)(h->buckets + bucket * (offsetof(Bucket, data[0]) + BUCKETSIZE * sizeof(KEYTYPE) + BUCKETSIZE * h->valuesize));
+		if(h->oldbuckets != nil) {
+			oldbucket = bucket & (((uintptr)1 << (h->B - 1)) - 1);
+			b = (Bucket*)(h->oldbuckets + oldbucket * h->bucketsize);
+			if(evacuated(b)) {
+				b = (Bucket*)(h->buckets + bucket * h->bucketsize);
+			}
+		} else {
+			b = (Bucket*)(h->buckets + bucket * h->bucketsize);
+		}
 		top = hash >> (sizeof(uintptr)*8 - 8);
 		if(top == 0)
 			top = 1;
diff --git a/src/pkg/runtime/malloc.goc b/src/pkg/runtime/malloc.goc
index fa28e2b..f1d25a7 100644
--- a/src/pkg/runtime/malloc.goc
+++ b/src/pkg/runtime/malloc.goc
@@ -160,7 +160,7 @@ runtime·free(void *v)
 	if(sizeclass == 0) {
 		// Large object.
 		size = s->npages<<PageShift;
-		*(uintptr*)(s->start<<PageShift) = 1;	// mark as "needs to be zeroed"
+		*(uintptr*)(s->start<<PageShift) = (uintptr)0xfeedfeedfeedfeedll;	// mark as "needs to be zeroed"
 		// Must mark v freed before calling unmarkspan and MHeap_Free:
 		// they might coalesce v into other spans and change the bitmap further.
 		runtime·markfreed(v, size);
@@ -170,7 +170,7 @@ runtime·free(void *v)
 		// Small object.
 		size = runtime·class_to_size[sizeclass];
 		if(size > sizeof(uintptr))
-			((uintptr*)v)[1] = 1;	// mark as "needs to be zeroed"
+			((uintptr*)v)[1] = (uintptr)0xfeedfeedfeedfeedll;	// mark as "needs to be zeroed"
 		// Must mark v freed before calling MCache_Free:
 		// it might coalesce v and other blocks into a bigger span
 		// and change the bitmap further.
@@ -318,7 +318,10 @@ runtime·mallocinit(void)
 
 	runtime·InitSizes();
 
-	limit = runtime·memlimit();
+	// limit = runtime·memlimit();
+	// See https://code.google.com/p/go/issues/detail?id=5049
+	// TODO(rsc): Fix after 1.1.
+	limit = 0;
 
 	// Set up the allocation arena, a contiguous area of memory where
 	// allocated data will be found.  The arena begins with a bitmap large
diff --git a/src/pkg/runtime/map_test.go b/src/pkg/runtime/map_test.go
index 29e19db..209355e 100644
--- a/src/pkg/runtime/map_test.go
+++ b/src/pkg/runtime/map_test.go
@@ -7,8 +7,11 @@ package runtime_test
 import (
 	"fmt"
 	"math"
+	"os"
 	"runtime"
 	"sort"
+	"strings"
+	"sync"
 	"testing"
 )
 
@@ -231,6 +234,40 @@ func TestIterGrowWithGC(t *testing.T) {
 	}
 }
 
+func TestConcurrentReadsAfterGrowth(t *testing.T) {
+	if os.Getenv("GOMAXPROCS") == "" {
+		defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(16))
+	}
+	numLoop := 10
+	numGrowStep := 250
+	numReader := 16
+	if testing.Short() {
+		numLoop, numGrowStep = 2, 500
+	}
+	for i := 0; i < numLoop; i++ {
+		m := make(map[int]int, 0)
+		for gs := 0; gs < numGrowStep; gs++ {
+			m[gs] = gs
+			var wg sync.WaitGroup
+			wg.Add(numReader * 2)
+			for nr := 0; nr < numReader; nr++ {
+				go func() {
+					defer wg.Done()
+					for _ = range m {
+					}
+				}()
+				go func() {
+					defer wg.Done()
+					for key := 0; key < gs; key++ {
+						_ = m[key]
+					}
+				}()
+			}
+			wg.Wait()
+		}
+	}
+}
+
 func TestBigItems(t *testing.T) {
 	var key [256]string
 	for i := 0; i < 256; i++ {
@@ -280,3 +317,38 @@ func TestEmptyKeyAndValue(t *testing.T) {
 		t.Errorf("empty key returned wrong value")
 	}
 }
+
+// Tests a map with a single bucket, with same-lengthed short keys
+// ("quick keys") as well as long keys.
+func TestSingleBucketMapStringKeys_DupLen(t *testing.T) {
+	testMapLookups(t, map[string]string{
+		"x":    "x1val",
+		"xx":   "x2val",
+		"foo":  "fooval",
+		"bar":  "barval", // same key length as "foo"
+		"xxxx": "x4val",
+		strings.Repeat("x", 128): "longval1",
+		strings.Repeat("y", 128): "longval2",
+	})
+}
+
+// Tests a map with a single bucket, with all keys having different lengths.
+func TestSingleBucketMapStringKeys_NoDupLen(t *testing.T) {
+	testMapLookups(t, map[string]string{
+		"x":                      "x1val",
+		"xx":                     "x2val",
+		"foo":                    "fooval",
+		"xxxx":                   "x4val",
+		"xxxxx":                  "x5val",
+		"xxxxxx":                 "x6val",
+		strings.Repeat("x", 128): "longval",
+	})
+}
+
+func testMapLookups(t *testing.T, m map[string]string) {
+	for k, v := range m {
+		if m[k] != v {
+			t.Fatalf("m[%q] = %q; want %q", k, m[k], v)
+		}
+	}
+}
diff --git a/src/pkg/runtime/mapspeed_test.go b/src/pkg/runtime/mapspeed_test.go
index a379740..3b7fbfd 100644
--- a/src/pkg/runtime/mapspeed_test.go
+++ b/src/pkg/runtime/mapspeed_test.go
@@ -118,6 +118,17 @@ func BenchmarkMegOneMap(b *testing.B) {
 	}
 }
 
+func BenchmarkMegEqMap(b *testing.B) {
+	m := make(map[string]bool)
+	key1 := strings.Repeat("X", 1<<20)
+	key2 := strings.Repeat("X", 1<<20) // equal but different instance
+	m[key1] = true
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		_, _ = m[key2]
+	}
+}
+
 func BenchmarkMegEmptyMap(b *testing.B) {
 	m := make(map[string]bool)
 	key := strings.Repeat("X", 1<<20)
@@ -138,6 +149,24 @@ func BenchmarkSmallStrMap(b *testing.B) {
 		_, _ = m[key]
 	}
 }
+
+func BenchmarkMapStringKeysEight_16(b *testing.B) { benchmarkMapStringKeysEight(b, 16) }
+func BenchmarkMapStringKeysEight_32(b *testing.B) { benchmarkMapStringKeysEight(b, 32) }
+func BenchmarkMapStringKeysEight_64(b *testing.B) { benchmarkMapStringKeysEight(b, 64) }
+func BenchmarkMapStringKeysEight_1M(b *testing.B) { benchmarkMapStringKeysEight(b, 1<<20) }
+
+func benchmarkMapStringKeysEight(b *testing.B, keySize int) {
+	m := make(map[string]bool)
+	for i := 0; i < 8; i++ {
+		m[strings.Repeat("K", i+1)] = true
+	}
+	key := strings.Repeat("K", keySize)
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		_ = m[key]
+	}
+}
+
 func BenchmarkIntMap(b *testing.B) {
 	m := make(map[int]bool)
 	for i := 0; i < 8; i++ {
@@ -148,3 +177,32 @@ func BenchmarkIntMap(b *testing.B) {
 		_, _ = m[7]
 	}
 }
+
+// Accessing the same keys in a row.
+func benchmarkRepeatedLookup(b *testing.B, lookupKeySize int) {
+	m := make(map[string]bool)
+	// At least bigger than a single bucket:
+	for i := 0; i < 64; i++ {
+		m[fmt.Sprintf("some key %d", i)] = true
+	}
+	base := strings.Repeat("x", lookupKeySize-1)
+	key1 := base + "1"
+	key2 := base + "2"
+	b.ResetTimer()
+	for i := 0; i < b.N/4; i++ {
+		_ = m[key1]
+		_ = m[key1]
+		_ = m[key2]
+		_ = m[key2]
+	}
+}
+
+func BenchmarkRepeatedLookupStrMapKey32(b *testing.B) { benchmarkRepeatedLookup(b, 32) }
+func BenchmarkRepeatedLookupStrMapKey1M(b *testing.B) { benchmarkRepeatedLookup(b, 1<<20) }
+
+func BenchmarkNewEmptyMap(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		_ = make(map[int]int)
+	}
+}
diff --git a/src/pkg/runtime/mgc0.c b/src/pkg/runtime/mgc0.c
index aa499f4..caf1b10 100644
--- a/src/pkg/runtime/mgc0.c
+++ b/src/pkg/runtime/mgc0.c
@@ -18,6 +18,7 @@ enum {
 	Debug = 0,
 	DebugMark = 0,  // run second pass to check mark
 	CollectStats = 0,
+	ScanStackByFrames = 0,
 
 	// Four bits per word (see #defines below).
 	wordsPerBitmapWord = sizeof(void*)*8/4,
@@ -1316,51 +1317,94 @@ addroot(Obj obj)
 	work.nroot++;
 }
 
+// Scan a stack frame.  The doframe parameter is a signal that the previously
+// scanned activation has an unknown argument size.  When *doframe is true the
+// current activation must have its entire frame scanned.  Otherwise, only the
+// locals need to be scanned.
+static void
+addframeroots(Func *f, byte*, byte *sp, void *doframe)
+{
+	uintptr outs;
+
+	if(thechar == '5')
+		sp += sizeof(uintptr);
+	if(f->locals == 0 || *(bool*)doframe == true)
+		addroot((Obj){sp, f->frame - sizeof(uintptr), 0});
+	else if(f->locals > 0) {
+		outs = f->frame - sizeof(uintptr) - f->locals;
+		addroot((Obj){sp + outs, f->locals, 0});
+	}
+	if(f->args > 0)
+		addroot((Obj){sp + f->frame, f->args, 0});
+	*(bool*)doframe = (f->args == ArgsSizeUnknown);
+}
+
 static void
 addstackroots(G *gp)
 {
 	M *mp;
 	int32 n;
 	Stktop *stk;
-	byte *sp, *guard;
+	byte *sp, *guard, *pc;
+	Func *f;
+	bool doframe;
 
 	stk = (Stktop*)gp->stackbase;
 	guard = (byte*)gp->stackguard;
 
 	if(gp == g) {
 		// Scanning our own stack: start at &gp.
-		sp = (byte*)&gp;
+		sp = runtime·getcallersp(&gp);
+		pc = runtime·getcallerpc(&gp);
 	} else if((mp = gp->m) != nil && mp->helpgc) {
 		// gchelper's stack is in active use and has no interesting pointers.
 		return;
+	} else if(gp->gcstack != (uintptr)nil) {
+		// Scanning another goroutine that is about to enter or might
+		// have just exited a system call. It may be executing code such
+		// as schedlock and may have needed to start a new stack segment.
+		// Use the stack segment and stack pointer at the time of
+		// the system call instead, since that won't change underfoot.
+		sp = (byte*)gp->gcsp;
+		pc = gp->gcpc;
+		stk = (Stktop*)gp->gcstack;
+		guard = (byte*)gp->gcguard;
 	} else {
 		// Scanning another goroutine's stack.
 		// The goroutine is usually asleep (the world is stopped).
 		sp = (byte*)gp->sched.sp;
-
-		// The exception is that if the goroutine is about to enter or might
-		// have just exited a system call, it may be executing code such
-		// as schedlock and may have needed to start a new stack segment.
-		// Use the stack segment and stack pointer at the time of
-		// the system call instead, since that won't change underfoot.
-		if(gp->gcstack != (uintptr)nil) {
-			stk = (Stktop*)gp->gcstack;
-			sp = (byte*)gp->gcsp;
-			guard = (byte*)gp->gcguard;
+		pc = gp->sched.pc;
+		if(ScanStackByFrames && pc == (byte*)runtime·goexit && gp->fnstart != nil) {
+			// The goroutine has not started. However, its incoming
+			// arguments are live at the top of the stack and must
+			// be scanned.  No other live values should be on the
+			// stack.
+			f = runtime·findfunc((uintptr)gp->fnstart->fn);
+			if(f->args > 0) {
+				if(thechar == '5')
+					sp += sizeof(uintptr);
+				addroot((Obj){sp, f->args, 0});
+			}
+			return;
 		}
 	}
-
-	n = 0;
-	while(stk) {
-		if(sp < guard-StackGuard || (byte*)stk < sp) {
-			runtime·printf("scanstack inconsistent: g%D#%d sp=%p not in [%p,%p]\n", gp->goid, n, sp, guard-StackGuard, stk);
-			runtime·throw("scanstack");
+	if (ScanStackByFrames) {
+		doframe = false;
+		runtime·gentraceback(pc, sp, nil, gp, 0, nil, 0x7fffffff, addframeroots, &doframe);
+	} else {
+		USED(pc);
+		n = 0;
+		while(stk) {
+			if(sp < guard-StackGuard || (byte*)stk < sp) {
+				runtime·printf("scanstack inconsistent: g%D#%d sp=%p not in [%p,%p]\n", gp->goid, n, sp, guard-StackGuard, stk);
+				runtime·throw("scanstack");
+			}
+			addroot((Obj){sp, (byte*)stk - sp, (uintptr)defaultProg | PRECISE | LOOP});
+			sp = (byte*)stk->gobuf.sp;
+			guard = stk->stackguard;
+			stk = (Stktop*)stk->stackbase;
+			n++;
 		}
-		addroot((Obj){sp, (byte*)stk - sp, (uintptr)defaultProg | PRECISE | LOOP});
-		sp = (byte*)stk->gobuf.sp;
-		guard = stk->stackguard;
-		stk = (Stktop*)stk->stackbase;
-		n++;
 	}
 }
 
@@ -1563,7 +1607,7 @@ sweepspan(ParFor *desc, uint32 idx)
 		if(cl == 0) {
 			// Free large span.
 			runtime·unmarkspan(p, 1<<PageShift);
-			*(uintptr*)p = 1;	// needs zeroing
+			*(uintptr*)p = (uintptr)0xdeaddeaddeaddeadll;	// needs zeroing
 			runtime·MHeap_Free(runtime·mheap, s, 1);
 			c->local_alloc -= size;
 			c->local_nfree++;
@@ -1578,7 +1622,7 @@ sweepspan(ParFor *desc, uint32 idx)
 				break;
 			}
 			if(size > sizeof(uintptr))
-				((uintptr*)p)[1] = 1;	// mark as "needs to be zeroed"
+				((uintptr*)p)[1] = (uintptr)0xdeaddeaddeaddeadll;	// mark as "needs to be zeroed"
 			
 			end->next = (MLink*)p;
 			end = (MLink*)p;
diff --git a/src/pkg/runtime/mgc0.h b/src/pkg/runtime/mgc0.h
index 18f3654..d14fb37 100644
--- a/src/pkg/runtime/mgc0.h
+++ b/src/pkg/runtime/mgc0.h
@@ -16,6 +16,9 @@
 //   len      Length of an array
 //   elemsize Size (in bytes) of an element
 //   size     Size (in bytes)
+//
+// NOTE: There is a copy of these in ../reflect/type.go.
+// They must be kept in sync.
 enum {
 	GC_END,         // End of object, loop or subroutine. Args: none
 	GC_PTR,         // A typed pointer. Args: (off, objgc)
diff --git a/src/pkg/runtime/mkasmh.sh b/src/pkg/runtime/mkasmh.sh
deleted file mode 100755
index f37fe21..0000000
--- a/src/pkg/runtime/mkasmh.sh
+++ /dev/null
@@ -1,138 +0,0 @@
-#!/bin/sh
-# Copyright 2009 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.
-
-trap "rm -f arch_GOARCH.h defs_GOOS_GOARCH.h os_GOOS.h signals_GOOS.h" EXIT INT TERM
-set -e
-
-SYS=$1
-export GOOS=$(echo $SYS | sed 's/_.*//')
-export GOARCH=$(echo $SYS | sed 's/.*_//')
-shift
-
-case "$GOARCH" in
-386) CC=8c;;
-amd64) CC=6c;;
-arm) CC=5c;;
-esac
-CC="$GOROOT/bin/tool/$CC"
-export CC
-
-export CFLAGS="-Dos_$GOOS -Darch_$GOARCH"
-
-cp arch_$GOARCH.h arch_GOARCH.h
-cp defs_${GOOS}_$GOARCH.h defs_GOOS_GOARCH.h
-cp os_$GOOS.h os_GOOS.h
-cp signals_$GOOS.h signals_GOOS.h
-
-cat <<'EOF'
-// Assembly constants.
-// AUTO-GENERATED by autogen.sh; DO NOT EDIT
-
-EOF
-if [ ! -x "$CC" ]; then
-	echo "// dummy file for cmd/go to correctly generate buildscript"
-	exit
-fi
-
-case "$GOARCH" in
-386)
-	# The offsets 0 and 4 are also known to:
-	#	../../cmd/8l/pass.c:/D_GS
-	#	cgo/gcc_linux_386.c:/^threadentry
-	#	cgo/gcc_darwin_386.c:/^threadentry
-	case "$GOOS" in
-	windows)
-		echo '#define	get_tls(r)	MOVL 0x14(FS), r'
-		echo '#define	g(r)	0(r)'
-		echo '#define	m(r)	4(r)'
-		;;
-	plan9)
-		echo '#define	get_tls(r)	MOVL _tos(SB), r '
-		echo '#define	g(r)	-8(r)'
-		echo '#define	m(r)	-4(r)'
-		;;
-	linux)
-		# On Linux systems, what we call 0(GS) and 4(GS) for g and m
-		# turn into %gs:-8 and %gs:-4 (using gcc syntax to denote
-		# what the machine sees as opposed to 8l input).
-		# 8l rewrites 0(GS) and 4(GS) into these.
-		#
-		# On Linux Xen, it is not allowed to use %gs:-8 and %gs:-4
-		# directly.  Instead, we have to store %gs:0 into a temporary
-		# register and then use -8(%reg) and -4(%reg).  This kind
-		# of addressing is correct even when not running Xen.
-		#
-		# 8l can rewrite MOVL 0(GS), CX into the appropriate pair
-		# of mov instructions, using CX as the intermediate register
-		# (safe because CX is about to be written to anyway).
-		# But 8l cannot handle other instructions, like storing into 0(GS),
-		# which is where these macros come into play.
-		# get_tls sets up the temporary and then g and r use it.
-		#
-		# The final wrinkle is that get_tls needs to read from %gs:0,
-		# but in 8l input it's called 8(GS), because 8l is going to
-		# subtract 8 from all the offsets, as described above.
-		echo '#define	get_tls(r)	MOVL 8(GS), r'
-		echo '#define	g(r)	-8(r)'
-		echo '#define	m(r)	-4(r)'
-		;;
-	*)
-		echo '#define	get_tls(r)'
-		echo '#define	g(r)	0(GS)'
-		echo '#define	m(r)	4(GS)'
-		;;
-	esac
-	;;
-amd64)
-	case "$GOOS" in
-	windows)
-		echo '#define	get_tls(r) MOVQ 0x28(GS), r'
-		echo '#define	g(r) 0(r)'
-		echo '#define	m(r) 8(r)'
-		;;
-	*)
-		# The offsets 0 and 8 are known to:
-		#	../../cmd/6l/pass.c:/D_GS
-		#	cgo/gcc_linux_amd64.c:/^threadentry
-		#	cgo/gcc_darwin_amd64.c:/^threadentry
-		#
-		echo '#define	get_tls(r)'
-		echo '#define	g(r) 0(GS)'
-		echo '#define	m(r) 8(GS)'
-		;;
-	esac
-	;;
-arm)
-	echo '#define	g	R10'
-	echo '#define	m	R9'
-	echo '#define	LR	R14'
-	;;
-*)
-	echo 'unknown $GOARCH: '$GOARCH 1>&2
-	exit 1
-	;;
-esac
-echo
-
-"$CC" $CFLAGS -a proc.c |
-awk '
-{ gsub(/\r/, ""); }
-/^aggr G$/ { aggr="g" }
-/^aggr M$/ { aggr = "m" }
-/^aggr Gobuf$/ { aggr = "gobuf" }
-/^aggr WinCall$/ { aggr = "wincall" }
-/^}/ { aggr = "" }
-
-#	Gobuf 24 sched;
-#	'Y' 48 stack0;
-#	'Y' 56 entry;
-#	'A' G 64 alllink;
-aggr != "" && /^	/ {
-	name=$NF;
-	sub(/;/, "", name);
-	offset=$(NF-1);
-	printf("#define %s_%s %s\n", aggr, name, offset);
-}
-'
diff --git a/src/pkg/runtime/mprof.goc b/src/pkg/runtime/mprof.goc
index ebc1e3e..707e505 100644
--- a/src/pkg/runtime/mprof.goc
+++ b/src/pkg/runtime/mprof.goc
@@ -511,7 +511,7 @@ saveg(byte *pc, byte *sp, G *gp, TRecord *r)
 {
 	int32 n;
 	
-	n = runtime·gentraceback(pc, sp, 0, gp, 0, r->stk, nelem(r->stk));
+	n = runtime·gentraceback(pc, sp, 0, gp, 0, r->stk, nelem(r->stk), nil, nil);
 	if(n < nelem(r->stk))
 		r->stk[n] = 0;
 }
diff --git a/src/pkg/runtime/netpoll_epoll.c b/src/pkg/runtime/netpoll_epoll.c
index d6ef0d1..9b59807 100644
--- a/src/pkg/runtime/netpoll_epoll.c
+++ b/src/pkg/runtime/netpoll_epoll.c
@@ -57,6 +57,7 @@ runtime·netpollclose(int32 fd)
 G*
 runtime·netpoll(bool block)
 {
+	static int32 lasterr;
 	EpollEvent events[128], *ev;
 	int32 n, i, waitms, mode;
 	G *gp;
@@ -69,8 +70,10 @@ runtime·netpoll(bool block)
 retry:
 	n = runtime·epollwait(epfd, events, nelem(events), waitms);
 	if(n < 0) {
-		if(n != -EINTR)
-			runtime·printf("epollwait failed with %d\n", -n);
+		if(n != -EINTR && n != lasterr) {
+			lasterr = n;
+			runtime·printf("runtime: epollwait on fd %d failed with %d\n", epfd, -n);
+		}
 		goto retry;
 	}
 	gp = nil;
diff --git a/src/pkg/runtime/netpoll_kqueue.c b/src/pkg/runtime/netpoll_kqueue.c
index ad721e2..0ed03d3 100644
--- a/src/pkg/runtime/netpoll_kqueue.c
+++ b/src/pkg/runtime/netpoll_kqueue.c
@@ -71,6 +71,7 @@ runtime·netpollclose(int32 fd)
 G*
 runtime·netpoll(bool block)
 {
+	static int32 lasterr;
 	Kevent events[64], *ev;
 	Timespec ts, *tp;
 	int32 n, i;
@@ -88,8 +89,10 @@ runtime·netpoll(bool block)
 retry:
 	n = runtime·kevent(kq, nil, 0, events, nelem(events), tp);
 	if(n < 0) {
-		if(n != -EINTR)
-			runtime·printf("kqueue failed with %d\n", -n);
+		if(n != -EINTR && n != lasterr) {
+			lasterr = n;
+			runtime·printf("runtime: kevent on fd %d failed with %d\n", kq, -n);
+		}
 		goto retry;
 	}
 	for(i = 0; i < n; i++) {
diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c
index 8d05730..eec7531 100644
--- a/src/pkg/runtime/proc.c
+++ b/src/pkg/runtime/proc.c
@@ -1778,7 +1778,7 @@ runtime·sigprof(uint8 *pc, uint8 *sp, uint8 *lr, G *gp)
 		runtime·unlock(&prof);
 		return;
 	}
-	n = runtime·gentraceback(pc, sp, lr, gp, 0, prof.pcbuf, nelem(prof.pcbuf));
+	n = runtime·gentraceback(pc, sp, lr, gp, 0, prof.pcbuf, nelem(prof.pcbuf), nil, nil);
 	if(n > 0)
 		prof.fn(prof.pcbuf, n);
 	runtime·unlock(&prof);
diff --git a/src/pkg/runtime/race.c b/src/pkg/runtime/race.c
index cfd9704..ce250b5 100644
--- a/src/pkg/runtime/race.c
+++ b/src/pkg/runtime/race.c
@@ -36,11 +36,14 @@ static bool onstack(uintptr argp);
 uintptr
 runtime·raceinit(void)
 {
-	uintptr racectx;
+	uintptr racectx, start, size;
 
 	m->racecall = true;
 	runtime∕race·Initialize(&racectx);
-	runtime∕race·MapShadow(noptrdata, enoptrbss - noptrdata);
+	// Round data segment to page boundaries, because it's used in mmap().
+	start = (uintptr)noptrdata & ~(PageSize-1);
+	size = ROUND((uintptr)enoptrbss - start, PageSize);
+	runtime∕race·MapShadow((void*)start, size);
 	m->racecall = false;
 	return racectx;
 }
diff --git a/src/pkg/runtime/race/testdata/mop_test.go b/src/pkg/runtime/race/testdata/mop_test.go
index 26cd3a4..fa7abe0 100644
--- a/src/pkg/runtime/race/testdata/mop_test.go
+++ b/src/pkg/runtime/race/testdata/mop_test.go
@@ -227,6 +227,37 @@ func TestRaceCaseFallthrough(t *testing.T) {
 	<-ch
 }
 
+func TestRaceCaseType(t *testing.T) {
+	var x, y int
+	var i interface{} = x
+	c := make(chan int, 1)
+	go func() {
+		switch i.(type) {
+		case nil:
+		case int:
+		}
+		c <- 1
+	}()
+	i = y
+	<-c
+}
+
+func TestRaceCaseTypeBody(t *testing.T) {
+	var x, y int
+	var i interface{} = &x
+	c := make(chan int, 1)
+	go func() {
+		switch i := i.(type) {
+		case nil:
+		case *int:
+			*i = y
+		}
+		c <- 1
+	}()
+	x = y
+	<-c
+}
+
 func TestNoRaceRange(t *testing.T) {
 	ch := make(chan int, 3)
 	a := [...]int{1, 2, 3}
@@ -339,11 +370,11 @@ func TestRaceDiv(t *testing.T) {
 }
 
 func TestRaceDivConst(t *testing.T) {
-	var x, y, z int
+	var x, y, z uint32
 	ch := make(chan int, 2)
 
 	go func() {
-		x = y / 3
+		x = y / 3 // involves only a HMUL node
 		ch <- 1
 	}()
 	go func() {
@@ -576,6 +607,30 @@ func TestRaceIfaceWW(t *testing.T) {
 	a = b
 }
 
+func TestRaceIfaceCmp(t *testing.T) {
+	var a, b Writer
+	a = DummyWriter{1}
+	ch := make(chan bool, 1)
+	go func() {
+		a = DummyWriter{1}
+		ch <- true
+	}()
+	_ = a == b
+	<-ch
+}
+
+func TestRaceIfaceCmpNil(t *testing.T) {
+	var a Writer
+	a = DummyWriter{1}
+	ch := make(chan bool, 1)
+	go func() {
+		a = DummyWriter{1}
+		ch <- true
+	}()
+	_ = a == nil
+	<-ch
+}
+
 func TestRaceEfaceConv(t *testing.T) {
 	c := make(chan bool)
 	v := 0
@@ -970,8 +1025,7 @@ func TestRaceAnd(t *testing.T) {
 	<-c
 }
 
-// OANDAND is not instrumented in the compiler.
-func TestRaceFailingAnd2(t *testing.T) {
+func TestRaceAnd2(t *testing.T) {
 	c := make(chan bool)
 	x, y := 0, 0
 	go func() {
@@ -1007,8 +1061,7 @@ func TestRaceOr(t *testing.T) {
 	<-c
 }
 
-// OOROR is not instrumented in the compiler.
-func TestRaceFailingOr2(t *testing.T) {
+func TestRaceOr2(t *testing.T) {
 	c := make(chan bool)
 	x, y := 0, 0
 	go func() {
@@ -1153,6 +1206,15 @@ func (p InterImpl) Foo(x int) {
 	_, _, _ = x, y, z
 }
 
+type InterImpl2 InterImpl
+
+func (p *InterImpl2) Foo(x int) {
+	if p == nil {
+		InterImpl{}.Foo(x)
+	}
+	InterImpl(*p).Foo(x)
+}
+
 func TestRaceInterCall(t *testing.T) {
 	c := make(chan bool, 1)
 	p := InterImpl{}
@@ -1214,6 +1276,54 @@ func TestRaceMethodCall2(t *testing.T) {
 	<-c
 }
 
+// Method value with concrete value receiver.
+func TestRaceMethodValue(t *testing.T) {
+	c := make(chan bool, 1)
+	i := InterImpl{}
+	go func() {
+		i = InterImpl{}
+		c <- true
+	}()
+	_ = i.Foo
+	<-c
+}
+
+// Method value with interface receiver.
+func TestRaceMethodValue2(t *testing.T) {
+	c := make(chan bool, 1)
+	var i Inter = InterImpl{}
+	go func() {
+		i = InterImpl{}
+		c <- true
+	}()
+	_ = i.Foo
+	<-c
+}
+
+// Method value with implicit dereference.
+func TestRaceMethodValue3(t *testing.T) {
+	c := make(chan bool, 1)
+	i := &InterImpl{}
+	go func() {
+		*i = InterImpl{}
+		c <- true
+	}()
+	_ = i.Foo // dereferences i.
+	<-c
+}
+
+// Method value implicitly taking receiver address.
+func TestNoRaceMethodValue(t *testing.T) {
+	c := make(chan bool, 1)
+	i := InterImpl2{}
+	go func() {
+		i = InterImpl2{}
+		c <- true
+	}()
+	_ = i.Foo // takes the address of i only.
+	<-c
+}
+
 func TestRacePanicArg(t *testing.T) {
 	c := make(chan bool, 1)
 	err := errors.New("err")
@@ -1340,6 +1450,17 @@ func TestRaceSliceSlice2(t *testing.T) {
 	<-c
 }
 
+func TestRaceSliceString(t *testing.T) {
+	c := make(chan bool, 1)
+	x := "hello"
+	go func() {
+		x = "world"
+		c <- true
+	}()
+	_ = x[2:3]
+	<-c
+}
+
 // http://golang.org/issue/4453
 func TestRaceFailingSliceStruct(t *testing.T) {
 	type X struct {
@@ -1356,6 +1477,21 @@ func TestRaceFailingSliceStruct(t *testing.T) {
 	<-c
 }
 
+func TestRaceFailingAppendSliceStruct(t *testing.T) {
+	type X struct {
+		x, y int
+	}
+	c := make(chan bool, 1)
+	x := make([]X, 10)
+	go func() {
+		y := make([]X, 0, 10)
+		y = append(y, x...)
+		c <- true
+	}()
+	x[1].y = 42
+	<-c
+}
+
 func TestRaceStructInd(t *testing.T) {
 	c := make(chan bool, 1)
 	type Item struct {
diff --git a/src/pkg/runtime/race/testdata/slice_test.go b/src/pkg/runtime/race/testdata/slice_test.go
index 1fe051b..c85df5e 100644
--- a/src/pkg/runtime/race/testdata/slice_test.go
+++ b/src/pkg/runtime/race/testdata/slice_test.go
@@ -338,8 +338,7 @@ func TestRaceSliceVarCopy2(t *testing.T) {
 	<-c
 }
 
-// Not implemented.
-func TestRaceFailingSliceAppend(t *testing.T) {
+func TestRaceSliceAppend(t *testing.T) {
 	c := make(chan bool, 1)
 	s := make([]int, 10, 20)
 	go func() {
diff --git a/src/pkg/runtime/runtime-gdb.py b/src/pkg/runtime/runtime-gdb.py
index eff9a40..cb70ca0 100644
--- a/src/pkg/runtime/runtime-gdb.py
+++ b/src/pkg/runtime/runtime-gdb.py
@@ -84,26 +84,35 @@ class MapTypePrinter:
 		return str(self.val.type)
 
 	def children(self):
-		stab = self.val['st']
-		i = 0
-		for v in self.traverse_hash(stab):
-			yield ("[%d]" % i, v['key'])
-			yield ("[%d]" % (i + 1), v['val'])
-			i += 2
-
-	def traverse_hash(self, stab):
-		ptr = stab['entry'].address
-		last = stab['last']
-		while ptr <= last:
-			v = ptr.dereference()
-			ptr = ptr + 1
-			if v['hash'] == 0: continue
-			if v['hash'] & 63 == 63:   # subtable
-				for v in self.traverse_hash(v['key'].cast(self.val['st'].type)):
-					yield v
-			else:
-				yield v
-
+		B = self.val['b']
+		buckets = self.val['buckets']
+		oldbuckets = self.val['oldbuckets']
+		flags = self.val['flags']
+		inttype = self.val['hash0'].type
+		cnt = 0
+		for bucket in xrange(2 ** B):
+			bp = buckets + bucket
+			if oldbuckets:
+				oldbucket = bucket & (2 ** (B - 1) - 1)
+				oldbp = oldbuckets + oldbucket
+				oldb = oldbp.dereference()
+				if (oldb['overflow'].cast(inttype) & 1) == 0: # old bucket not evacuated yet
+					if bucket >= 2 ** (B - 1): continue   # already did old bucket
+					bp = oldbp
+			while bp:
+				b = bp.dereference()
+				for i in xrange(8):
+					if b['tophash'][i] != 0:
+						k = b['keys'][i]
+						v = b['values'][i]
+						if flags & 1:
+							k = k.dereference()
+						if flags & 2:
+							v = v.dereference()
+						yield '%d' % cnt, k
+						yield '%d' % (cnt + 1), v
+						cnt += 2
+				bp = b['overflow']
 
 class ChanTypePrinter:
 	"""Pretty print chan[T] types.
diff --git a/src/pkg/runtime/runtime.h b/src/pkg/runtime/runtime.h
index 46c77e3..864b2aa 100644
--- a/src/pkg/runtime/runtime.h
+++ b/src/pkg/runtime/runtime.h
@@ -147,7 +147,12 @@ enum
 	// Global <-> per-M stack segment cache transfer batch size.
 	StackCacheBatch = 16,
 };
-
+enum
+{
+	// This value is generated by the linker and should be kept in
+	// sync with cmd/ld/lib.h
+	ArgsSizeUnknown = 0x80000000,
+};
 /*
  * structures
  */
@@ -238,6 +243,7 @@ struct	G
 	bool	ispanic;
 	bool	issystem;	// do not output in stack dump
 	bool	isbackground;	// ignore in deadlock detector
+	bool	blockingsyscall;	// hint that the next syscall will block
 	int8	raceignore;	// ignore race detection events
 	M*	m;		// for debuggers, but offset not hard-coded
 	M*	lockedm;
@@ -587,6 +593,8 @@ void	runtime·strequal(bool*, uintptr, void*, void*);
 void	runtime·interequal(bool*, uintptr, void*, void*);
 void	runtime·nilinterequal(bool*, uintptr, void*, void*);
 
+bool	runtime·memeq(void*, void*, uintptr);
+
 void	runtime·memprint(uintptr, void*);
 void	runtime·strprint(uintptr, void*);
 void	runtime·interprint(uintptr, void*);
@@ -774,7 +782,7 @@ void	runtime·exitsyscall(void);
 G*	runtime·newproc1(FuncVal*, byte*, int32, int32, void*);
 bool	runtime·sigsend(int32 sig);
 int32	runtime·callers(int32, uintptr*, int32);
-int32	runtime·gentraceback(byte*, byte*, byte*, G*, int32, uintptr*, int32);
+int32	runtime·gentraceback(byte*, byte*, byte*, G*, int32, uintptr*, int32, void (*)(Func*, byte*, byte*, void*), void*);
 int64	runtime·nanotime(void);
 void	runtime·dopanic(int32);
 void	runtime·startpanic(void);
diff --git a/src/pkg/runtime/string.goc b/src/pkg/runtime/string.goc
index c0d3f2b..49bf114 100644
--- a/src/pkg/runtime/string.goc
+++ b/src/pkg/runtime/string.goc
@@ -206,8 +206,6 @@ func cmpstring(s1 String, s2 String) (v int) {
 }
 
 func eqstring(s1 String, s2 String) (v bool) {
-	uintgo i, l;
-
 	if(s1.len != s2.len) {
 		v = false;
 		return;
@@ -216,13 +214,7 @@ func eqstring(s1 String, s2 String) (v bool) {
 		v = true;
 		return;
 	}
-	l = s1.len;
-	for(i=0; i<l; i++)
-		if(s1.str[i] != s2.str[i]) {
-			v = false;
-			return;
-		}
-	v = true;
+	v = runtime·memeq(s1.str, s2.str, s1.len);
 }
 
 int32
diff --git a/src/pkg/runtime/string_test.go b/src/pkg/runtime/string_test.go
index 6ba3c1d..df3ff06 100644
--- a/src/pkg/runtime/string_test.go
+++ b/src/pkg/runtime/string_test.go
@@ -47,3 +47,31 @@ func BenchmarkCompareStringDifferentLength(b *testing.B) {
 		}
 	}
 }
+
+func BenchmarkCompareStringBigUnaligned(b *testing.B) {
+	bytes := make([]byte, 0, 1<<20)
+	for len(bytes) < 1<<20 {
+		bytes = append(bytes, "Hello Gophers!"...)
+	}
+	s1, s2 := string(bytes), "hello"+string(bytes)
+	for i := 0; i < b.N; i++ {
+		if s1 != s2[len("hello"):] {
+			b.Fatal("s1 != s2")
+		}
+	}
+	b.SetBytes(int64(len(s1)))
+}
+
+func BenchmarkCompareStringBig(b *testing.B) {
+	bytes := make([]byte, 0, 1<<20)
+	for len(bytes) < 1<<20 {
+		bytes = append(bytes, "Hello Gophers!"...)
+	}
+	s1, s2 := string(bytes), string(bytes)
+	for i := 0; i < b.N; i++ {
+		if s1 != s2 {
+			b.Fatal("s1 != s2")
+		}
+	}
+	b.SetBytes(int64(len(s1)))
+}
diff --git a/src/pkg/runtime/traceback_arm.c b/src/pkg/runtime/traceback_arm.c
index dd85cc0..ae2d324 100644
--- a/src/pkg/runtime/traceback_arm.c
+++ b/src/pkg/runtime/traceback_arm.c
@@ -17,9 +17,9 @@ void _divu(void);
 void _modu(void);
 
 int32
-runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr *pcbuf, int32 max)
+runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr *pcbuf, int32 max, void (*fn)(Func*, byte*, byte*, void*), void *arg)
 {
-	int32 i, n, iter;
+	int32 i, n;
 	uintptr pc, lr, tracepc, x;
 	byte *fp;
 	bool waspanic;
@@ -46,7 +46,7 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
 
 	n = 0;
 	stk = (Stktop*)gp->stackbase;
-	for(iter = 0; iter < 100 && n < max; iter++) {	// iter avoids looping forever
+	while(n < max) {
 		// Typically:
 		//	pc is the PC of the running function.
 		//	sp is the stack pointer at that program counter.
@@ -60,28 +60,34 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
 			sp = (byte*)stk->gobuf.sp;
 			lr = 0;
 			fp = nil;
-			if(pcbuf == nil && runtime·showframe(nil, gp == m->curg))
+			if(pcbuf == nil && fn == nil && runtime·showframe(nil, gp == m->curg))
 				runtime·printf("----- stack segment boundary -----\n");
 			stk = (Stktop*)stk->stackbase;
 			continue;
 		}
 		
-		if(pc <= 0x1000 || (f = runtime·findfunc(pc)) == nil)
+		if(pc <= 0x1000 || (f = runtime·findfunc(pc)) == nil) {
+			if(fn != nil)
+				runtime·throw("unknown pc");
 			break;
+		}
 		
 		// Found an actual function.
 		if(lr == 0)
 			lr = *(uintptr*)sp;
 		if(fp == nil) {
 			fp = sp;
-			if(pc > f->entry && f->frame >= 0)
-				fp += f->frame;
+			if(pc > f->entry && f->frame >= sizeof(uintptr))
+				fp += f->frame - sizeof(uintptr);
+			fp += sizeof(uintptr);
 		}
 
 		if(skip > 0)
 			skip--;
 		else if(pcbuf != nil)
 			pcbuf[n++] = pc;
+		else if(fn != nil)
+			(*fn)(f, (byte*)pc, sp, arg);
 		else {
 			if(runtime·showframe(f, gp == m->curg)) {
 				// Print during crash.
@@ -113,7 +119,7 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
 		
 		waspanic = f->entry == (uintptr)runtime·sigpanic;
 
-		if(pcbuf == nil && f->entry == (uintptr)runtime·newstack && gp == m->g0) {
+		if(pcbuf == nil && fn == nil && f->entry == (uintptr)runtime·newstack && gp == m->g0) {
 			runtime·printf("----- newstack called from goroutine %D -----\n", m->curg->goid);
 			pc = (uintptr)m->morepc;
 			sp = (byte*)m->moreargp - sizeof(void*);
@@ -124,7 +130,7 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
 			continue;
 		}
 		
-		if(pcbuf == nil && f->entry == (uintptr)runtime·lessstack && gp == m->g0) {
+		if(pcbuf == nil && fn == nil && f->entry == (uintptr)runtime·lessstack && gp == m->g0) {
 			runtime·printf("----- lessstack called from goroutine %D -----\n", m->curg->goid);
 			gp = m->curg;
 			stk = (Stktop*)gp->stackbase;
@@ -135,6 +141,10 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
 			continue;
 		}	
 		
+		// Do not unwind past the bottom of the stack.
+		if(pc == (uintptr)runtime·goexit)
+			break;
+
 		// Unwind to next frame.
 		pc = lr;
 		lr = 0;
@@ -162,7 +172,7 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
 		}
 	}
 	
-	if(pcbuf == nil && (pc = gp->gopc) != 0 && (f = runtime·findfunc(pc)) != nil
+	if(pcbuf == nil && fn == nil && (pc = gp->gopc) != 0 && (f = runtime·findfunc(pc)) != nil
 			&& runtime·showframe(f, gp == m->curg) && gp->goid != 1) {
 		runtime·printf("created by %S\n", f->name);
 		tracepc = pc;	// back up to CALL instruction for funcline.
@@ -186,7 +196,7 @@ runtime·traceback(byte *pc0, byte *sp, byte *lr, G *gp)
 		sp = (byte*)gp->sched.sp;
 		lr = nil;
 	}
-	runtime·gentraceback(pc0, sp, lr, gp, 0, nil, 100);
+	runtime·gentraceback(pc0, sp, lr, gp, 0, nil, 100, nil, nil);
 }
 
 // func caller(n int) (pc uintptr, file string, line int, ok bool)
@@ -198,5 +208,5 @@ runtime·callers(int32 skip, uintptr *pcbuf, int32 m)
 	sp = runtime·getcallersp(&skip);
 	pc = runtime·getcallerpc(&skip);
 
-	return runtime·gentraceback(pc, sp, 0, g, skip, pcbuf, m);
+	return runtime·gentraceback(pc, sp, 0, g, skip, pcbuf, m, nil, nil);
 }
diff --git a/src/pkg/runtime/traceback_x86.c b/src/pkg/runtime/traceback_x86.c
index 72603ae..ce52df8 100644
--- a/src/pkg/runtime/traceback_x86.c
+++ b/src/pkg/runtime/traceback_x86.c
@@ -17,14 +17,14 @@ void runtime·sigpanic(void);
 // This code is also used for the 386 tracebacks.
 // Use uintptr for an appropriate word-sized integer.
 
-// Generic traceback.  Handles runtime stack prints (pcbuf == nil)
-// as well as the runtime.Callers function (pcbuf != nil).
-// A little clunky to merge the two but avoids duplicating
-// the code and all its subtlety.
+// Generic traceback.  Handles runtime stack prints (pcbuf == nil),
+// the runtime.Callers function (pcbuf != nil), as well as the garbage
+// collector (fn != nil).  A little clunky to merge the two but avoids
+// duplicating the code and all its subtlety.
 int32
-runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr *pcbuf, int32 max)
+runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr *pcbuf, int32 max, void (*fn)(Func*, byte*, byte*, void*), void *arg)
 {
-	int32 i, n, iter, sawnewstack;
+	int32 i, n, sawnewstack;
 	uintptr pc, lr, tracepc;
 	byte *fp;
 	Stktop *stk;
@@ -54,7 +54,7 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
 	n = 0;
 	sawnewstack = 0;
 	stk = (Stktop*)gp->stackbase;
-	for(iter = 0; iter < 100 && n < max; iter++) {	// iter avoids looping forever
+	while(n < max) {
 		// Typically:
 		//	pc is the PC of the running function.
 		//	sp is the stack pointer at that program counter.
@@ -68,13 +68,16 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
 			sp = (byte*)stk->gobuf.sp;
 			lr = 0;
 			fp = nil;
-			if(pcbuf == nil && runtime·showframe(nil, gp == m->curg))
+			if(pcbuf == nil && fn == nil && runtime·showframe(nil, gp == m->curg))
 				runtime·printf("----- stack segment boundary -----\n");
 			stk = (Stktop*)stk->stackbase;
 			continue;
 		}
-		if(pc <= 0x1000 || (f = runtime·findfunc(pc)) == nil)
+		if(pc <= 0x1000 || (f = runtime·findfunc(pc)) == nil) {
+			if(fn != nil)
+				runtime·throw("unknown pc");
 			break;
+		}
 
 		// Found an actual function.
 		if(fp == nil) {
@@ -91,6 +94,8 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
 			skip--;
 		else if(pcbuf != nil)
 			pcbuf[n++] = pc;
+		else if(fn != nil)
+			(*fn)(f, (byte*)pc, sp, arg);
 		else {
 			if(runtime·showframe(f, gp == m->curg)) {
 				// Print during crash.
@@ -129,7 +134,7 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
 		if(f->entry == (uintptr)runtime·newstack)
 			sawnewstack = 1;
 
-		if(pcbuf == nil && f->entry == (uintptr)runtime·morestack && gp == m->g0 && sawnewstack) {
+		if(pcbuf == nil && fn == nil && f->entry == (uintptr)runtime·morestack && gp == m->g0 && sawnewstack) {
 			// The fact that we saw newstack means that morestack
 			// has managed to record its information in m, so we can
 			// use it to keep unwinding the stack.
@@ -144,7 +149,7 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
 			continue;
 		}
 
-		if(pcbuf == nil && f->entry == (uintptr)runtime·lessstack && gp == m->g0) {
+		if(pcbuf == nil && fn == nil && f->entry == (uintptr)runtime·lessstack && gp == m->g0) {
 			// Lessstack is running on scheduler stack.  Switch to original goroutine.
 			runtime·printf("----- lessstack called from goroutine %D -----\n", m->curg->goid);
 			gp = m->curg;
@@ -156,6 +161,10 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
 			continue;
 		}
 
+		// Do not unwind past the bottom of the stack.
+		if(pc == (uintptr)runtime·goexit)
+			break;
+
 		// Unwind to next frame.
 		pc = lr;
 		lr = 0;
@@ -164,7 +173,7 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
 	}
 	
 	// Show what created goroutine, except main goroutine (goid 1).
-	if(pcbuf == nil && (pc = gp->gopc) != 0 && (f = runtime·findfunc(pc)) != nil
+	if(pcbuf == nil && fn == nil && (pc = gp->gopc) != 0 && (f = runtime·findfunc(pc)) != nil
 			&& runtime·showframe(f, gp == m->curg) && gp->goid != 1) {
 		runtime·printf("created by %S\n", f->name);
 		tracepc = pc;	// back up to CALL instruction for funcline.
@@ -187,7 +196,7 @@ runtime·traceback(byte *pc0, byte *sp, byte*, G *gp)
 		pc0 = gp->sched.pc;
 		sp = (byte*)gp->sched.sp;
 	}
-	runtime·gentraceback(pc0, sp, nil, gp, 0, nil, 100);
+	runtime·gentraceback(pc0, sp, nil, gp, 0, nil, 100, nil, nil);
 }
 
 int32
@@ -199,5 +208,5 @@ runtime·callers(int32 skip, uintptr *pcbuf, int32 m)
 	sp = (byte*)&skip;
 	pc = runtime·getcallerpc(&skip);
 
-	return runtime·gentraceback(pc, sp, nil, g, skip, pcbuf, m);
+	return runtime·gentraceback(pc, sp, nil, g, skip, pcbuf, m, nil, nil);
 }
diff --git a/src/pkg/sort/example_multi_test.go b/src/pkg/sort/example_multi_test.go
new file mode 100644
index 0000000..d0a9e7d
--- /dev/null
+++ b/src/pkg/sort/example_multi_test.go
@@ -0,0 +1,132 @@
+// Copyright 2013 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.
+
+package sort_test
+
+import (
+	"fmt"
+	"sort"
+)
+
+// A Change is a record of source code changes, recording user, language, and delta size.
+type Change struct {
+	user     string
+	language string
+	lines    int
+}
+
+type lessFunc func(p1, p2 *Change) bool
+
+// multiSorter implements the Sort interface, sorting the changes within.
+type multiSorter struct {
+	changes []Change
+	less    []lessFunc
+}
+
+// Sort sorts the argument slice according to the less functions passed to OrderedBy.
+func (ms *multiSorter) Sort(changes []Change) {
+	sort.Sort(ms)
+}
+
+// OrderedBy returns a Sorter that sorts using the less functions, in order.
+// Call its Sort method to sort the data.
+func OrderedBy(less ...lessFunc) *multiSorter {
+	return &multiSorter{
+		changes: changes,
+		less:    less,
+	}
+}
+
+// Len is part of sort.Interface.
+func (ms *multiSorter) Len() int {
+	return len(ms.changes)
+}
+
+// Swap is part of sort.Interface.
+func (ms *multiSorter) Swap(i, j int) {
+	ms.changes[i], ms.changes[j] = ms.changes[j], ms.changes[i]
+}
+
+// Less is part of sort.Interface. It is implemented by looping along the
+// less functions until it finds a comparison that is either Less or
+// !Less. Note that it can call the less functions twice per call. We
+// could change the functions to return -1, 0, 1 and reduce the
+// number of calls for greater efficiency: an exercise for the reader.
+func (ms *multiSorter) Less(i, j int) bool {
+	p, q := &ms.changes[i], &ms.changes[j]
+	// Try all but the last comparison.
+	var k int
+	for k = 0; k < len(ms.less)-1; k++ {
+		less := ms.less[k]
+		switch {
+		case less(p, q):
+			// p < q, so we have a decision.
+			return true
+		case less(q, p):
+			// p > q, so we have a decision.
+			return false
+		}
+		// p == q; try the next comparison.
+	}
+	// All comparisons to here said "equal", so just return whatever
+	// the final comparison reports.
+	return ms.less[k](p, q)
+}
+
+var changes = []Change{
+	{"gri", "Go", 100},
+	{"ken", "C", 150},
+	{"glenda", "Go", 200},
+	{"rsc", "Go", 200},
+	{"r", "Go", 100},
+	{"ken", "Go", 200},
+	{"dmr", "C", 100},
+	{"r", "C", 150},
+	{"gri", "Smalltalk", 80},
+}
+
+// ExampleMultiKeys demonstrates a technique for sorting a struct type using different
+// sets of multiple fields in the comparison. We chain together "Less" functions, each of
+// which compares a single field.
+func Example_sortMultiKeys() {
+	// Closures that order the Change structure.
+	user := func(c1, c2 *Change) bool {
+		return c1.user < c2.user
+	}
+	language := func(c1, c2 *Change) bool {
+		return c1.language < c2.language
+	}
+	increasingLines := func(c1, c2 *Change) bool {
+		return c1.lines < c2.lines
+	}
+	decreasingLines := func(c1, c2 *Change) bool {
+		return c1.lines > c2.lines // Note: > orders downwards.
+	}
+
+	// Simple use: Sort by user.
+	OrderedBy(user).Sort(changes)
+	fmt.Println("By user:", changes)
+
+	// multiSorter implements the Sort interface, so we can also do this.
+	sort.Sort(OrderedBy(user, increasingLines))
+	fmt.Println("By user,<lines:", changes)
+
+	// More examples.
+	OrderedBy(user, decreasingLines).Sort(changes)
+	fmt.Println("By user,>lines:", changes)
+
+	OrderedBy(language, increasingLines).Sort(changes)
+	fmt.Println("By language,<lines:", changes)
+
+	OrderedBy(language, increasingLines, user).Sort(changes)
+	fmt.Println("By language,<lines,user:", changes)
+
+	// Output:
+	//By user: [{dmr C 100} {glenda Go 200} {gri Smalltalk 80} {gri Go 100} {ken Go 200} {ken C 150} {r Go 100} {r C 150} {rsc Go 200}]
+	//By user,<lines: [{dmr C 100} {glenda Go 200} {gri Smalltalk 80} {gri Go 100} {ken C 150} {ken Go 200} {r Go 100} {r C 150} {rsc Go 200}]
+	//By user,>lines: [{dmr C 100} {glenda Go 200} {gri Go 100} {gri Smalltalk 80} {ken Go 200} {ken C 150} {r C 150} {r Go 100} {rsc Go 200}]
+	//By language,<lines: [{dmr C 100} {ken C 150} {r C 150} {gri Go 100} {r Go 100} {ken Go 200} {glenda Go 200} {rsc Go 200} {gri Smalltalk 80}]
+	//By language,<lines,user: [{dmr C 100} {ken C 150} {r C 150} {gri Go 100} {r Go 100} {glenda Go 200} {ken Go 200} {rsc Go 200} {gri Smalltalk 80}]
+
+}
diff --git a/src/pkg/strconv/strconv_test.go b/src/pkg/strconv/strconv_test.go
index 3cd7835..40ab4ce 100644
--- a/src/pkg/strconv/strconv_test.go
+++ b/src/pkg/strconv/strconv_test.go
@@ -20,14 +20,12 @@ var (
 		desc  string
 		fn    func()
 	}{
-		// TODO(bradfitz): this might be 0, once escape analysis is better
-		{1, `AppendInt(localBuf[:0], 123, 10)`, func() {
+		{0, `AppendInt(localBuf[:0], 123, 10)`, func() {
 			var localBuf [64]byte
 			AppendInt(localBuf[:0], 123, 10)
 		}},
 		{0, `AppendInt(globalBuf[:0], 123, 10)`, func() { AppendInt(globalBuf[:0], 123, 10) }},
-		// TODO(bradfitz): this might be 0, once escape analysis is better
-		{1, `AppendFloat(localBuf[:0], 1.23, 'g', 5, 64)`, func() {
+		{0, `AppendFloat(localBuf[:0], 1.23, 'g', 5, 64)`, func() {
 			var localBuf [64]byte
 			AppendFloat(localBuf[:0], 1.23, 'g', 5, 64)
 		}},
diff --git a/src/pkg/sync/atomic/asm_arm.s b/src/pkg/sync/atomic/asm_arm.s
index 4faf5b5..a052588 100644
--- a/src/pkg/sync/atomic/asm_arm.s
+++ b/src/pkg/sync/atomic/asm_arm.s
@@ -29,6 +29,10 @@ casfail:
 TEXT ·armCompareAndSwapUint64(SB),7,$0
 	BL	fastCheck64<>(SB)
 	MOVW	addr+0(FP), R1
+	// make unaligned atomic access panic
+	AND.S	$7, R1, R2
+	BEQ 	2(PC)
+	MOVW	R2, (R2)
 	MOVW	oldlo+4(FP), R2
 	MOVW	oldhi+8(FP), R3
 	MOVW	newlo+12(FP), R4
@@ -67,6 +71,10 @@ addloop:
 TEXT ·armAddUint64(SB),7,$0
 	BL	fastCheck64<>(SB)
 	MOVW	addr+0(FP), R1
+	// make unaligned atomic access panic
+	AND.S	$7, R1, R2
+	BEQ 	2(PC)
+	MOVW	R2, (R2)
 	MOVW	deltalo+4(FP), R2
 	MOVW	deltahi+8(FP), R3
 add64loop:
@@ -84,6 +92,10 @@ add64loop:
 TEXT ·armLoadUint64(SB),7,$0
 	BL	fastCheck64<>(SB)
 	MOVW	addr+0(FP), R1
+	// make unaligned atomic access panic
+	AND.S	$7, R1, R2
+	BEQ 	2(PC)
+	MOVW	R2, (R2)
 load64loop:
 	LDREXD	(R1), R2	// loads R2 and R3
 	STREXD	R2, (R1), R0	// stores R2 and R3
@@ -96,6 +108,10 @@ load64loop:
 TEXT ·armStoreUint64(SB),7,$0
 	BL	fastCheck64<>(SB)
 	MOVW	addr+0(FP), R1
+	// make unaligned atomic access panic
+	AND.S	$7, R1, R2
+	BEQ 	2(PC)
+	MOVW	R2, (R2)
 	MOVW	vallo+4(FP), R2
 	MOVW	valhi+8(FP), R3
 store64loop:
diff --git a/src/pkg/sync/atomic/asm_linux_arm.s b/src/pkg/sync/atomic/asm_linux_arm.s
index 098acf3..5b16894 100644
--- a/src/pkg/sync/atomic/asm_linux_arm.s
+++ b/src/pkg/sync/atomic/asm_linux_arm.s
@@ -80,6 +80,10 @@ TEXT cas64<>(SB),7,$0
 TEXT kernelCAS64<>(SB),7,$0
 	// int (*__kuser_cmpxchg64_t)(const int64_t *oldval, const int64_t *newval, volatile int64_t *ptr);
 	MOVW	addr+0(FP), R2 // ptr
+	// make unaligned atomic access panic
+	AND.S	$7, R2, R1
+	BEQ 	2(PC)
+	MOVW	R1, (R1)
 	MOVW	$4(FP), R0 // oldval
 	MOVW	$12(FP), R1 // newval
 	BL		cas64<>(SB)
@@ -91,6 +95,10 @@ TEXT kernelCAS64<>(SB),7,$0
 TEXT generalCAS64<>(SB),7,$20
 	// bool runtime·cas64(uint64 volatile *addr, uint64 *old, uint64 new)
 	MOVW	addr+0(FP), R0
+	// make unaligned atomic access panic
+	AND.S	$7, R0, R1
+	BEQ 	2(PC)
+	MOVW	R1, (R1)
 	MOVW	R0, 4(R13)
 	MOVW	$4(FP), R1 // oldval
 	MOVW	R1, 8(R13)
diff --git a/src/pkg/sync/atomic/atomic_test.go b/src/pkg/sync/atomic/atomic_test.go
index 72f3030..b392df5 100644
--- a/src/pkg/sync/atomic/atomic_test.go
+++ b/src/pkg/sync/atomic/atomic_test.go
@@ -1189,10 +1189,10 @@ func shouldPanic(t *testing.T, name string, f func()) {
 
 func TestUnaligned64(t *testing.T) {
 	// Unaligned 64-bit atomics on 32-bit systems are
-	// a continual source of pain. Test that on 386 they crash
+	// a continual source of pain. Test that on 32-bit systems they crash
 	// instead of failing silently.
-	if runtime.GOARCH != "386" {
-		t.Skip("test only runs on 386")
+	if unsafe.Sizeof(int(0)) != 4 {
+		t.Skip("test only runs on 32-bit systems")
 	}
 
 	x := make([]uint32, 4)
diff --git a/src/pkg/syscall/passfd_test.go b/src/pkg/syscall/passfd_test.go
index a0e5909..e16deba 100644
--- a/src/pkg/syscall/passfd_test.go
+++ b/src/pkg/syscall/passfd_test.go
@@ -49,7 +49,7 @@ func TestPassFD(t *testing.T) {
 	defer readFile.Close()
 
 	cmd := exec.Command(os.Args[0], "-test.run=^TestPassFD$", "--", tempDir)
-	cmd.Env = append([]string{"GO_WANT_HELPER_PROCESS=1"}, os.Environ()...)
+	cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"}
 	cmd.ExtraFiles = []*os.File{writeFile}
 
 	out, err := cmd.CombinedOutput()
diff --git a/src/pkg/testing/testing.go b/src/pkg/testing/testing.go
index 86cd46c..312d287 100644
--- a/src/pkg/testing/testing.go
+++ b/src/pkg/testing/testing.go
@@ -18,6 +18,8 @@
 //         ...
 //     }
 //
+// Benchmarks
+//
 // Functions of the form
 //     func BenchmarkXxx(*testing.B)
 // are considered benchmarks, and are executed by the "go test" command when
@@ -49,6 +51,8 @@
 //         }
 //     }
 //
+// Examples
+//
 // The package also runs and verifies example code. Example functions may
 // include a concluding line comment that begins with "Output:" and is compared with
 // the standard output of the function when the tests are run. (The comparison
@@ -246,11 +250,13 @@ func (c *common) log(s string) {
 }
 
 // Log formats its arguments using default formatting, analogous to Println,
-// and records the text in the error log.
+// and records the text in the error log. The text will be printed only if
+// the test fails or the -test.v flag is set.
 func (c *common) Log(args ...interface{}) { c.log(fmt.Sprintln(args...)) }
 
 // Logf formats its arguments according to the format, analogous to Printf,
-// and records the text in the error log.
+// and records the text in the error log. The text will be printed only if
+// the test fails or the -test.v flag is set.
 func (c *common) Logf(format string, args ...interface{}) { c.log(fmt.Sprintf(format, args...)) }
 
 // Error is equivalent to Log followed by Fail.
@@ -337,6 +343,7 @@ func tRunner(t *T, test *InternalTest) {
 		t.duration = time.Now().Sub(t.start)
 		// If the test panicked, print any test output before dying.
 		if err := recover(); err != nil {
+			t.Fail()
 			t.report()
 			panic(err)
 		}
diff --git a/src/pkg/text/template/exec.go b/src/pkg/text/template/exec.go
index 12c40b7..8ec8174 100644
--- a/src/pkg/text/template/exec.go
+++ b/src/pkg/text/template/exec.go
@@ -619,6 +619,8 @@ func (s *state) evalArg(dot reflect.Value, typ reflect.Type, n parse.Node) refle
 		return s.validateType(s.evalVariableNode(dot, arg, nil, zero), typ)
 	case *parse.PipeNode:
 		return s.validateType(s.evalPipeline(dot, arg), typ)
+	case *parse.IdentifierNode:
+		return s.evalFunction(dot, arg, arg, nil, zero)
 	}
 	switch typ.Kind() {
 	case reflect.Bool:
diff --git a/src/pkg/text/template/exec_test.go b/src/pkg/text/template/exec_test.go
index 0f8beec..0ab20ac 100644
--- a/src/pkg/text/template/exec_test.go
+++ b/src/pkg/text/template/exec_test.go
@@ -499,6 +499,8 @@ var execTests = []execTest{
 	{"bug8b", "{{4|dddArg 3}}", "", tVal, false},
 	// A bug was introduced that broke map lookups for lower-case names.
 	{"bug9", "{{.cause}}", "neglect", map[string]string{"cause": "neglect"}, true},
+	// Field chain starting with function did not work.
+	{"bug10", "{{mapOfThree.three}}-{{(mapOfThree).three}}", "3-3", 0, true},
 }
 
 func zeroArgs() string {
@@ -560,19 +562,24 @@ func stringer(s fmt.Stringer) string {
 	return s.String()
 }
 
+func mapOfThree() interface{} {
+	return map[string]int{"three": 3}
+}
+
 func testExecute(execTests []execTest, template *Template, t *testing.T) {
 	b := new(bytes.Buffer)
 	funcs := FuncMap{
-		"add":      add,
-		"count":    count,
-		"dddArg":   dddArg,
-		"echo":     echo,
-		"makemap":  makemap,
-		"oneArg":   oneArg,
-		"typeOf":   typeOf,
-		"vfunc":    vfunc,
-		"zeroArgs": zeroArgs,
-		"stringer": stringer,
+		"add":        add,
+		"count":      count,
+		"dddArg":     dddArg,
+		"echo":       echo,
+		"makemap":    makemap,
+		"mapOfThree": mapOfThree,
+		"oneArg":     oneArg,
+		"stringer":   stringer,
+		"typeOf":     typeOf,
+		"vfunc":      vfunc,
+		"zeroArgs":   zeroArgs,
 	}
 	for _, test := range execTests {
 		var tmpl *Template
diff --git a/src/run.bash b/src/run.bash
index 538d4f6..b197844 100755
--- a/src/run.bash
+++ b/src/run.bash
@@ -35,16 +35,20 @@ fi
 # at least runtime/debug test will fail.
 unset GOROOT_FINAL
 
+# increase timeout for ARM up to 3 times the normal value
+timeout_scale=1
+[ "$GOARCH" == "arm" ] && timeout_scale=3
+
 echo '# Testing packages.'
-time go test std -short -timeout=120s
+time go test std -short -timeout=$(expr 120 \* $timeout_scale)s
 echo
 
 echo '# GOMAXPROCS=2 runtime -cpu=1,2,4'
-GOMAXPROCS=2 go test runtime -short -timeout=240s -cpu=1,2,4
+GOMAXPROCS=2 go test runtime -short -timeout=$(expr 240 \* $timeout_scale)s -cpu=1,2,4
 echo
 
 echo '# sync -cpu=10'
-go test sync -short -timeout=120s -cpu=10
+go test sync -short -timeout=$(expr 120 \* $timeout_scale)s -cpu=10
 
 # Race detector only supported on Linux and OS X,
 # and only on amd64, and only when cgo is enabled.
@@ -75,11 +79,26 @@ go run $GOROOT/test/run.go - .
 
 [ "$CGO_ENABLED" != 1 ] ||
 (xcd ../misc/cgo/test
+set -e
 go test -ldflags '-linkmode=auto'
 go test -ldflags '-linkmode=internal'
 case "$GOHOSTOS-$GOARCH" in
-darwin-386 | darwin-amd64 | freebsd-386 | freebsd-amd64 | linux-386 | linux-amd64 | netbsd-386 | netbsd-amd64 | openbsd-386 | openbsd-amd64)
+openbsd-386 | openbsd-amd64)
+	# test linkmode=external, but __thread not supported, so skip testtls.
+	go test -ldflags '-linkmode=external'
+	;;
+darwin-386 | darwin-amd64)
+	# linkmode=external fails on OS X 10.6 and earlier == Darwin
+	# 10.8 and earlier.
+	case $(uname -r) in
+	[0-9].* | 10.*) ;;
+	*) go test -ldflags '-linkmode=external' ;;
+	esac
+	;;
+freebsd-386 | freebsd-amd64 | linux-386 | linux-amd64 | netbsd-386 | netbsd-amd64)
 	go test -ldflags '-linkmode=external'
+	go test -ldflags '-linkmode=auto' ../testtls
+	go test -ldflags '-linkmode=external' ../testtls
 esac
 ) || exit $?
 
diff --git a/src/run.bat b/src/run.bat
index 3f950f5..1a68eb5 100644
--- a/src/run.bat
+++ b/src/run.bat
@@ -74,12 +74,12 @@ echo.
 :: cgo tests
 if x%CGO_ENABLED% == x0 goto nocgo
 echo # ..\misc\cgo\life
-go run %GOROOT%\test\run.go - ..\misc\cgo\life
+go run "%GOROOT%\test\run.go" - ..\misc\cgo\life
 if errorlevel 1 goto fail
 echo.
 
 echo # ..\misc\cgo\stdio
-go run %GOROOT%\test\run.go - ..\misc\cgo\stdio
+go run "%GOROOT%\test\run.go" - ..\misc\cgo\stdio
 if errorlevel 1 goto fail
 echo.
 
@@ -90,7 +90,7 @@ echo.
 :nocgo
 
 echo # ..\doc\progs
-go run %GOROOT%\test\run.go - ..\doc\progs
+go run "%GOROOT%\test\run.go" - ..\doc\progs
 if errorlevel 1 goto fail
 echo.
 
diff --git a/test/fixedbugs/issue5105.dir/a.go b/test/fixedbugs/issue5105.dir/a.go
new file mode 100644
index 0000000..f20abb9
--- /dev/null
+++ b/test/fixedbugs/issue5105.dir/a.go
@@ -0,0 +1,7 @@
+// Copyright 2013 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.
+
+package a
+
+var A = [2]string{"hello", "world"}
diff --git a/test/fixedbugs/issue5105.dir/b.go b/test/fixedbugs/issue5105.dir/b.go
new file mode 100644
index 0000000..b12e739
--- /dev/null
+++ b/test/fixedbugs/issue5105.dir/b.go
@@ -0,0 +1,15 @@
+// Copyright 2013 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.
+
+package main
+
+import "./a"
+
+var B = [2]string{"world", "hello"}
+
+func main() {
+	if a.A[0] != B[1] {
+		panic("bad hello")
+	}
+}
diff --git a/test/fixedbugs/issue5105.go b/test/fixedbugs/issue5105.go
new file mode 100644
index 0000000..e3e5e5c
--- /dev/null
+++ b/test/fixedbugs/issue5105.go
@@ -0,0 +1,10 @@
+// rundir
+
+// Copyright 2013 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.
+
+// Issue 5105: linker segfaults on duplicate definition
+// of a type..hash.* function.
+
+package ignored
diff --git a/test/fixedbugs/issue5125.dir/bug.go b/test/fixedbugs/issue5125.dir/bug.go
new file mode 100644
index 0000000..2fdf0f9
--- /dev/null
+++ b/test/fixedbugs/issue5125.dir/bug.go
@@ -0,0 +1,17 @@
+// Copyright 2013 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.
+
+package bug
+
+type Node interface {
+	Eval(s *Scene)
+}
+
+type plug struct {
+	node Node
+}
+
+type Scene struct {
+	changed map[plug]bool
+}
diff --git a/test/fixedbugs/issue5125.dir/main.go b/test/fixedbugs/issue5125.dir/main.go
new file mode 100644
index 0000000..47acdeb
--- /dev/null
+++ b/test/fixedbugs/issue5125.dir/main.go
@@ -0,0 +1,10 @@
+// Copyright 2013 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.
+
+package main
+
+import _ "./bug"
+
+func main() {
+}
diff --git a/test/fixedbugs/issue5125.go b/test/fixedbugs/issue5125.go
new file mode 100644
index 0000000..c049df3
--- /dev/null
+++ b/test/fixedbugs/issue5125.go
@@ -0,0 +1,10 @@
+// compiledir
+
+// Copyright 2013 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.
+
+// Issue 5125: cyclic dependencies between types confuse
+// the hashability test during import.
+
+package ignored
diff --git a/test/fixedbugs/issue5162.go b/test/fixedbugs/issue5162.go
new file mode 100644
index 0000000..b14eae7
--- /dev/null
+++ b/test/fixedbugs/issue5162.go
@@ -0,0 +1,88 @@
+// runoutput
+
+// Copyright 2013 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.
+
+// issue 5162: bad array equality when multiple comparisons
+// happen in the same expression.
+
+package main
+
+import (
+	"fmt"
+	"strings"
+)
+
+const template = `
+func CheckEqNNN_TTT() {
+	onesA := [NNN]ttt{ONES}
+	onesB := [NNN]ttt{ONES}
+	twos := [NNN]ttt{TWOS}
+	if onesA != onesB {
+		println("onesA != onesB in CheckEqNNN_TTT")
+	}
+	if onesA == twos {
+		println("onesA == twos in CheckEqNNN_TTT")
+	}
+	if onesB == twos {
+		println("onesB == twos in CheckEqNNN_TTT")
+	}
+	if s := fmt.Sprint(onesA == onesB, onesA != twos, onesB != twos); s != "true true true" {
+		println("fail in CheckEqNNN_TTT:", s)
+	}
+}
+
+func CheckEqNNN_TTTExtraVar() {
+	onesA := [NNN]ttt{ONES}
+	onesB := [NNN]ttt{ONES}
+	twos := [NNN]ttt{TWOS}
+	onesX := onesA
+	if onesA != onesB {
+		println("onesA != onesB in CheckEqNNN_TTTExtraVar")
+	}
+	if onesA == twos {
+		println("onesA == twos in CheckEqNNN_TTTExtraVar")
+	}
+	if onesB == twos {
+		println("onesB == twos in CheckEqNNN_TTTExtraVar")
+	}
+	if s := fmt.Sprint(onesA == onesB, onesA != twos, onesB != twos); s != "true true true" {
+		println("fail in CheckEqNNN_TTTExtraVar:", s)
+	}
+	if s := fmt.Sprint(onesB == onesX); s != "true" {
+		println("extra var fail in CheckEqNNN_TTTExtraVar")
+	}
+}
+`
+
+func main() {
+	fmt.Print("// run\n\n")
+	fmt.Print("// THIS FILE IS AUTO-GENERATED\n\n")
+	fmt.Print("package main\n\n")
+	fmt.Println(`import "fmt"`)
+
+	types := []string{
+		"int", "int8", "int16", "int32", "int64",
+		"uint", "uint8", "uint16", "uint32", "uint64",
+		"float32", "float64"}
+	tocall := make([]string, 0, 32*len(types))
+	for i := 1; i <= 32; i++ {
+		for _, typ := range types {
+			src := template
+			src = strings.Replace(src, "NNN", fmt.Sprint(i), -1)
+			src = strings.Replace(src, "TTT", strings.Title(typ), -1)
+			src = strings.Replace(src, "ttt", typ, -1)
+			src = strings.Replace(src, "ONES", "1"+strings.Repeat(", 1", i-1), -1)
+			src = strings.Replace(src, "TWOS", "2"+strings.Repeat(", 2", i-1), -1)
+			fmt.Print(src)
+			tocall = append(tocall, fmt.Sprintf("CheckEq%d_%s", i, strings.Title(typ)))
+		}
+	}
+	fmt.Println("func main() {")
+	for _, fun := range tocall {
+		fmt.Printf("\t%s()\n", fun)
+		fmt.Printf("\t%sExtraVar()\n", fun)
+	}
+	fmt.Println("}")
+}

-- 
Packaging for Google Go



More information about the pkg-golang-commits mailing list