[SCM] Packaging for Google Go branch, debian-sid, updated. debian/2011.04.13-2_exp1-22-g8a0ab0d

Ondřej Surý ondrej at sury.org
Tue May 3 15:50:07 UTC 2011


The following commit has been merged in the debian-sid branch:
commit 912927f743d96110c4270794358f2082258a4199
Author: Ondřej Surý <ondrej at sury.org>
Date:   Thu Apr 28 10:35:15 2011 +0200

    Imported Upstream version 2011.04.27

diff --git a/AUTHORS b/AUTHORS
index 33f3013..7366be1 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -110,6 +110,7 @@ Peter Froehlich <peter.hans.froehlich at gmail.com>
 Peter Mundy <go.peter.90 at gmail.com>
 Peter Williams <pwil3058 at gmail.com>
 Pieter Droogendijk <pieter at binky.org.uk>
+Quan Yong Zhai <qyzhai at gmail.com>
 Raif S. Naffah <go at naffah-raif.name>
 Risto Jaakko Saarelma <rsaarelm at gmail.com>
 Robert Hencke <robert.hencke at gmail.com>
@@ -130,6 +131,7 @@ Tarmigan Casebolt <tarmigan at gmail.com>
 Timo Savola <timo.savola at gmail.com>
 Tor Andersson <tor.andersson at gmail.com>
 Vincent Ambo <tazjin at googlemail.com>
+Vincent Vanackere <vincent.vanackere at gmail.com>
 Vinu Rajashekhar <vinutheraj at gmail.com>
 Wei Guangjing <vcc.163 at gmail.com>
 William Josephson <wjosephson at gmail.com>
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index 57a5f66..c2ebaf3 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -77,12 +77,14 @@ Daniel Nadasi <dnadasi at google.com>
 Daniel Theophanes <kardianos at gmail.com>
 Dave Cheney <dave at cheney.net>
 David Anderson <danderson at google.com>
+David Crawshaw <david.crawshaw at zentus.com>
 David Forsythe <dforsythe at gmail.com>
 David G. Andersen <dave.andersen at gmail.com>
 David Symonds <dsymonds at golang.org>
 David Titarenco <david.titarenco at gmail.com>
 Dean Prichard <dean.prichard at gmail.com>
 Devon H. O'Dell <devon.odell at gmail.com>
+Dmitriy Vyukov <dvyukov at google.com>
 Dmitry Chestnykh <dchest at gmail.com>
 Eden Li <eden.li at gmail.com>
 Eoghan Sherry <ejsherry at gmail.com>
@@ -165,7 +167,9 @@ Péter Szabó <pts at google.com>
 Peter Williams <pwil3058 at gmail.com>
 Phil Pennock <pdp at golang.org>
 Pieter Droogendijk <pieter at binky.org.uk>
+Quan Yong Zhai <qyzhai at gmail.com>
 Raif S. Naffah <go at naffah-raif.name>
+Raph Levien <raph at google.com>
 Risto Jaakko Saarelma <rsaarelm at gmail.com>
 Rob Pike <r at golang.org>
 Robert Griesemer <gri at golang.org>
@@ -194,6 +198,7 @@ Tom Szymanski <tgs at google.com>
 Tor Andersson <tor.andersson at gmail.com>
 Trevor Strohman <trevor.strohman at gmail.com>
 Vincent Ambo <tazjin at googlemail.com>
+Vincent Vanackere <vincent.vanackere at gmail.com>
 Vinu Rajashekhar <vinutheraj at gmail.com>
 Vish Subramanian <vish at google.com>
 Wei Guangjing <vcc.163 at gmail.com>
diff --git a/doc/all.css b/doc/all.css
index b1d55cf..dd00d1a 100644
--- a/doc/all.css
+++ b/doc/all.css
@@ -96,7 +96,7 @@ h1#title {
   color: #999;
 }
 #search {
-  width: 100px;
+  width: 120px;
   margin-left: 0.5em;
 }
 #search.inactive {
diff --git a/doc/devel/release.html b/doc/devel/release.html
index f75cbf2..0b70f03 100644
--- a/doc/devel/release.html
+++ b/doc/devel/release.html
@@ -5,6 +5,139 @@
 <p>This page summarizes the changes between tagged releases of Go.
 For full details, see the <a href="http://code.google.com/p/go/source/list">Mercurial change log</a>.</p>
 
+<h3 id="2011-04-27">2011-04-27</h3>
+
+<pre>
+This release includes revisions to the reflect package to make it more
+efficient, after last the weekly’s major API update. If your code uses reflect
+it may require further changes, not all of which can be made automatically by
+gofix. For the full details of the change, see
+	http://codereview.appspot.com/4435042
+Also, the Typeof and NewValue functions have been renamed to TypeOf and ValueOf.
+
+Other changes:
+* 5c: make alignment rules match 5g, just like 6c matches 6g.
+* 8g, 8l: fix "set but not used" gcc error (thanks Fazlul Shahriar).
+* all-qemu.bash: remove DISABLE_NET_TESTS.
+* build: remove DISABLE_NET_TESTS.
+* builder: build multiple targets in parallel.
+* cgo: avoid "incompatible pointer type" warning (thanks Albert Strasheim).
+* codereview: add 'hg undo' command, various other fixes.
+* compress/flate: dictionary support.
+* compress/zlib: add FDICT flag in Reader/Writer (thanks Ross Light).
+* container/heap: fix circular dependency in test.
+* crypto/openpgp: better handling of keyrings.
+* crypto/rsa: support > 3 primes.
+* crypto/tls: add server-side OCSP stapling support.
+* crypto/x509: memorize chain building.
+* crypto: move certificate verification into x509.
+* dashboard: build most recent revision first.
+* doc: mention make version in install.html.
+* expvar: add Func for functions that return values that are JSON marshalable.
+* fmt: decrease recursion depth in tests to permit them to run under gccgo,
+	tweak the doc for %U.
+* gc: allow complex types to be receiver types (thanks Robert Hencke),
+	correct handling of unexported method names in embedded interfaces,
+	explain why invalid receiver types are invalid,
+	fix copy([]int, string) error message (thanks Quan Yong Zhai),
+	fix 'invalid recursive type' error (thanks Lorenzo Stoakes),
+	many bug fixes.
+* go spec: attempt at clarifying language for "append",
+	for map types, mention indexing operations.
+* go/types: update for export data format change.
+* gob: fix handling of indirect receivers for GobDecoders,
+	fix trivial bug in map marshaling,
+	have errorf always prefix the message with "gob: ",
+	test case for indirection to large field,
+	use new Implements and AssignableTo methods in reflect,
+	when decoding a string, allocate a string, not a []byte.
+* gobuilder: permit builders of the form goos-goarch-foo,
+	respect MAKEFLAGS if provided (thanks Dave Cheney).
+* godoc: use "search" input type for search box (thanks Dmitry Chestnykh).
+* gofix: add support for reflect rename.
+* gofmt: add -d (diff) (thanks David Crawshaw),
+	don't crash when rewriting nil interfaces in AST,
+	exclude test case that doesn't compile w/o errors,
+	gofmt test harness bug fix.
+* goinstall: support GOPATH; building and installing outside the Go tree,
+	support building executable commands.
+* gopack: fix prefix bug,
+	preserve safe flag when not adding unsafe objects to archive.
+* gotest: add timing, respect $GOARCH,
+	generate gofmt-compliant code.
+* http/cgi: copy some PATH environment variables to child,
+	improve Location response handling,
+	pass some default environment variables.
+* http/fcgi: new package (thanks Evan Shaw).
+* http: add NewRequest helper,
+	add MultipartForm, ParseMultipartForm, and FormFile to Request,
+	be clear when failing to connect to a proxy,
+	bug fixes and new tests,
+	consume request bodies before replying,
+	don't quote Set-Cookie Domain and Path (thanks Petar Maymounkov),
+	fix IP confusion in TestServerTimeouts,
+	handler timeout support,
+	ServerConn, ClientConn: add real Close (thanks Petar Maymounkov),
+	make Client redirect policy configurable,
+	put a limit on POST size,
+	reverse proxy handler.
+* image/jpeg: add an encoder,
+	decode to a YCbCr image instead of an RGBA image.
+* ioutil: add Discard.
+* json: keep track of error offset in SyntaxError.
+* ld: defend against some broken object files,
+	do not emit empty dwarf pe sections (thanks Alex Brainman),
+	fix 6l -d on Mac, diagnose invalid use of -d,
+	fix Plan 9 symbol table (thanks Anthony Martin),
+	remove MachoLoad limit.
+* make: prevent rm provoking 'text file busy' errors (thanks Lorenzo Stoakes).
+* mime/multipart: add ReadForm for parsing multipart forms,
+	limit line length to prevent abuse.
+* mime: RFC 2231 continuation / non-ASCII support,
+	bunch more tests, few minor parsing fixes.
+* misc/goplay: fix Tab and Shift+Enter in Firefox (thanks Dmitry Chestnykh).
+* net: disable one more external network test,
+	fix EAI_BADFLAGS error on freebsd (thanks Mikio Hara),
+	fix ParseIP (thanks Quan Yong Zhai),
+	fix dialgoogle_test.go (thanks Quan Yong Zhai),
+	try /etc/hosts before loading DNS config (thanks Dmitry Chestnykh),
+	use C library resolver on FreeBSD, Linux, OS X / amd64, 386.
+* os/user: new package to look up users.
+* os: Open with O_APPEND|O_CREATE to append on Windows (thanks Alex Brainman),
+	fix race in ReadAt/WriteAt on Windows (thanks Alex Brainman),
+	turn EPIPE exit into panic.
+* rc/env.bash: fix to build on windows under msys (thanks Joe Poirier).
+* reflect: allow Slice of arrays,
+	fix Copy of arrays (thanks Gustavo Niemeyer),
+	require package qualifiers to match during interface check,
+	add Type.Implements, Type.AssignableTo, Value.CallSlice,
+	make Set match Go.
+* rpc: allow the first argument of a method to be a value rather than a pointer,
+	run benchmarks over HTTP as well as direct network connections.
+* run.bash: remove redundant rebuilds.
+* runtime/plan9: warning remediation for Plan 9 (thanks Lucio De Re),
+* runtime: many bug fixes,
+	fix GOMAXPROCS vs garbage collection bug (thanks Dmitriy Vyukov),
+	fix mkversion to output valid path separators (thanks Peter Mundy),
+	more graceful out-of-memory crash,
+	require package qualifiers to match during interface check,
+	skip functions with no lines when building src line table,
+	turn "too many EPIPE" into real SIGPIPE.
+* src/pkg: make package doc comments consistently start with "Package foo".
+* syscall: Madvise and Mprotect for Linux (thanks Albert Strasheim),
+	Mlock, Munlock, Mlockall, Munlockall on Linux (thanks Albert Strasheim),
+	add BPF support for darwin/386, darwin/amd64 (thanks Mikio Hara),
+	correct Windows CreateProcess input parameters (thanks Alex Brainman),
+	fix Ftruncate under linux/arm5 (thanks Dave Cheney),
+	permit StartProcess to hide the executed program on windows (thanks Vincent Vanackere).
+* test/bench: update timings; moving to new machine.
+* time: support Irix 6 location for zoneinfo files.
+* tutorial: modernize the definition and use of Open,
+	replace the forever loops with finite counts in sieve programs.
+* websocket: include *http.Request in websocket.Conn.
+* xml: Parser hook for non-UTF-8 charset converters.
+</pre>
+
 <h3 id="2011-04-13">2011-04-13</h3>
 
 <pre>
diff --git a/doc/effective_go.html b/doc/effective_go.html
index 27bfd1b..a7e6b7b 100644
--- a/doc/effective_go.html
+++ b/doc/effective_go.html
@@ -159,7 +159,7 @@ should set up the detailed documentation that follows.
 
 <pre>
 /*
-    The regexp package implements a simple library for
+    Package regexp implements a simple library for
     regular expressions.
 
     The syntax of the regular expressions accepted is:
@@ -186,7 +186,7 @@ If the package is simple, the package comment can be brief.
 </p>
 
 <pre>
-// The path package implements utility routines for
+// Package path implements utility routines for
 // manipulating slash-separated filename paths.
 </pre>
 
diff --git a/doc/go_spec.html b/doc/go_spec.html
index f8fe597..886f89d 100644
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1,5 +1,5 @@
 <!-- title The Go Programming Language Specification -->
-<!-- subtitle Version of Apr 5, 2011 -->
+<!-- subtitle Version of Apr 22, 2011 -->
 
 <!--
 TODO
@@ -1155,8 +1155,9 @@ map [string] interface {}
 The number of map elements is called its length.
 For a map <code>m</code>, it can be discovered using the
 built-in function <a href="#Length_and_capacity"><code>len(m)</code></a>
-and may change during execution. Values may be added and removed
-during execution using special forms of <a href="#Assignments">assignment</a>.
+and may change during execution. Elements may be added and removed
+during execution using special forms of <a href="#Assignments">assignment</a>;
+and they may be accessed with <a href="#Indexes">index</a> expressions.
 </p>
 <p>
 A new, empty map value is made using the built-in
@@ -4541,13 +4542,14 @@ Two built-in functions assist in common slice operations.
 
 <p>
 The function <code>append</code> appends zero or more values <code>x</code>
-to a slice <code>s</code> and returns the resulting slice, with the same type
-as s. Each value must be <a href="#Assignability">assignable</a> to the slice's
-element type.
+to <code>s</code> of type <code>S</code>, which must be a slice type, and
+returns the resulting slice, also of type <code>S</code>.
+Each value <code>x</code> must be <a href="#Assignability">assignable</a> to
+the <a href="#Slice_types">element type</a> of <code>S</code>.
 </p>
 
 <pre class="grammar">
-append(s S, x ...T) S  // S is assignable to []T
+append(s S, x ...T) S  // T is the element type of S
 </pre>
 
 <p>
@@ -4562,6 +4564,9 @@ s0 := []int{0, 0}
 s1 := append(s0, 2)        // append a single element     s1 == []int{0, 0, 2}
 s2 := append(s1, 3, 5, 7)  // append multiple elements    s2 == []int{0, 0, 2, 3, 5, 7}
 s3 := append(s2, s0...)    // append a slice              s3 == []int{0, 0, 2, 3, 5, 7, 0, 0}
+
+var t []interface{}
+t = append(t, 42, 3.1415, "foo")                          t == []interface{}{42, 3.1415, "foo"}
 </pre>
 
 <p>
diff --git a/doc/go_tutorial.html b/doc/go_tutorial.html
index e3d946f..c87254e 100644
--- a/doc/go_tutorial.html
+++ b/doc/go_tutorial.html
@@ -474,8 +474,8 @@ assigned to a variable.
 <p>
 <h2>An I/O Package</h2>
 <p>
-Next we'll look at a simple package for doing file I/O with the usual
-sort of open/close/read/write interface.  Here's the start of <code>file.go</code>:
+Next we'll look at a simple package for doing file I/O with an
+open/close/read/write interface.  Here's the start of <code>file.go</code>:
 <p>
 <pre> <!-- progs/file.go /package/ /^}/ -->
 05    package file
@@ -554,10 +554,10 @@ We can use the factory to construct some familiar, exported variables of type <c
 </pre>
 <p>
 The <code>newFile</code> function was not exported because it's internal. The proper,
-exported factory to use is <code>Open</code>:
+exported factory to use is <code>OpenFile</code> (we'll explain that name in a moment):
 <p>
-<pre> <!-- progs/file.go /func.Open/ /^}/ -->
-30    func Open(name string, mode int, perm uint32) (file *File, err os.Error) {
+<pre> <!-- progs/file.go /func.OpenFile/ /^}/ -->
+30    func OpenFile(name string, mode int, perm uint32) (file *File, err os.Error) {
 31        r, e := syscall.Open(name, mode, perm)
 32        if e != 0 {
 33            err = os.Errno(e)
@@ -566,7 +566,7 @@ exported factory to use is <code>Open</code>:
 36    }
 </pre>
 <p>
-There are a number of new things in these few lines.  First, <code>Open</code> returns
+There are a number of new things in these few lines.  First, <code>OpenFile</code> returns
 multiple values, a <code>File</code> and an error (more about errors in a moment).
 We declare the
 multi-value return as a parenthesized list of declarations; syntactically
@@ -585,6 +585,35 @@ consistent error handling throughout Go code.   In <code>Open</code> we use a
 conversion to translate Unix's integer <code>errno</code> value into the integer type
 <code>os.Errno</code>, which implements <code>os.Error</code>.
 <p>
+Why <code>OpenFile</code> and not <code>Open</code>? To mimic Go's <code>os</code> package, which
+our exercise is emulating. The <code>os</code> package takes the opportunity
+to make the two commonest cases - open for read and create for
+write - the simplest, just <code>Open</code> and <code>Create</code>.  <code>OpenFile</code> is the
+general case, analogous to the Unix system call <code>Open</code>.  Here is
+the implementation of our <code>Open</code> and <code>Create</code>; they're trivial
+wrappers that eliminate common errors by capturing
+the tricky standard arguments to open and, especially, to create a file:
+<p>
+<pre> <!-- progs/file.go /^const/ /^}/ -->
+38    const (
+39        O_RDONLY = syscall.O_RDONLY
+40        O_RDWR   = syscall.O_RDWR
+41        O_CREATE = syscall.O_CREAT
+42        O_TRUNC  = syscall.O_TRUNC
+43    )
+<p>
+45    func Open(name string) (file *File, err os.Error) {
+46        return OpenFile(name, O_RDONLY, 0)
+47    }
+</pre>
+<p>
+<pre> <!-- progs/file.go /func.Create/ /^}/ -->
+49    func Create(name string) (file *File, err os.Error) {
+50        return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
+51    }
+</pre>
+<p>
+Back to our main story.
 Now that we can build <code>Files</code>, we can write methods for them. To declare
 a method of a type, we define a function to have an explicit receiver
 of that type, placed
@@ -592,43 +621,43 @@ in parentheses before the function name. Here are some methods for <code>*File</
 each of which declares a receiver variable <code>file</code>.
 <p>
 <pre> <!-- progs/file.go /Close/ END -->
-38    func (file *File) Close() os.Error {
-39        if file == nil {
-40            return os.EINVAL
-41        }
-42        e := syscall.Close(file.fd)
-43        file.fd = -1 // so it can't be closed again
-44        if e != 0 {
-45            return os.Errno(e)
-46        }
-47        return nil
-48    }
-<p>
-50    func (file *File) Read(b []byte) (ret int, err os.Error) {
-51        if file == nil {
-52            return -1, os.EINVAL
-53        }
-54        r, e := syscall.Read(file.fd, b)
-55        if e != 0 {
-56            err = os.Errno(e)
-57        }
-58        return int(r), err
-59    }
-<p>
-61    func (file *File) Write(b []byte) (ret int, err os.Error) {
-62        if file == nil {
-63            return -1, os.EINVAL
-64        }
-65        r, e := syscall.Write(file.fd, b)
-66        if e != 0 {
-67            err = os.Errno(e)
+53    func (file *File) Close() os.Error {
+54        if file == nil {
+55            return os.EINVAL
+56        }
+57        e := syscall.Close(file.fd)
+58        file.fd = -1 // so it can't be closed again
+59        if e != 0 {
+60            return os.Errno(e)
+61        }
+62        return nil
+63    }
+<p>
+65    func (file *File) Read(b []byte) (ret int, err os.Error) {
+66        if file == nil {
+67            return -1, os.EINVAL
 68        }
-69        return int(r), err
-70    }
-<p>
-72    func (file *File) String() string {
-73        return file.name
+69        r, e := syscall.Read(file.fd, b)
+70        if e != 0 {
+71            err = os.Errno(e)
+72        }
+73        return int(r), err
 74    }
+<p>
+76    func (file *File) Write(b []byte) (ret int, err os.Error) {
+77        if file == nil {
+78            return -1, os.EINVAL
+79        }
+80        r, e := syscall.Write(file.fd, b)
+81        if e != 0 {
+82            err = os.Errno(e)
+83        }
+84        return int(r), err
+85    }
+<p>
+87    func (file *File) String() string {
+88        return file.name
+89    }
 </pre>
 <p>
 There is no implicit <code>this</code> and the receiver variable must be used to access
@@ -658,7 +687,7 @@ We can now use our new package:
 13    func main() {
 14        hello := []byte(&quot;hello, world\n&quot;)
 15        file.Stdout.Write(hello)
-16        f, err := file.Open(&quot;/does/not/exist&quot;,  0,  0)
+16        f, err := file.Open(&quot;/does/not/exist&quot;)
 17        if f == nil {
 18            fmt.Printf(&quot;can't open file; err=%s\n&quot;,  err.String())
 19            os.Exit(1)
@@ -712,26 +741,27 @@ Building on the <code>file</code> package, here's a simple version of the Unix u
 24            case nr &gt; 0:
 25                if nw, ew := file.Stdout.Write(buf[0:nr]); nw != nr {
 26                    fmt.Fprintf(os.Stderr, &quot;cat: error writing from %s: %s\n&quot;, f.String(), ew.String())
-27                }
-28            }
-29        }
-30    }
+27                    os.Exit(1)
+28                }
+29            }
+30        }
+31    }
 <p>
-32    func main() {
-33        flag.Parse() // Scans the arg list and sets up flags
-34        if flag.NArg() == 0 {
-35            cat(file.Stdin)
-36        }
-37        for i := 0; i &lt; flag.NArg(); i++ {
-38            f, err := file.Open(flag.Arg(i), 0, 0)
-39            if f == nil {
-40                fmt.Fprintf(os.Stderr, &quot;cat: can't open %s: error %s\n&quot;, flag.Arg(i), err)
-41                os.Exit(1)
-42            }
-43            cat(f)
-44            f.Close()
-45        }
-46    }
+33    func main() {
+34        flag.Parse() // Scans the arg list and sets up flags
+35        if flag.NArg() == 0 {
+36            cat(file.Stdin)
+37        }
+38        for i := 0; i &lt; flag.NArg(); i++ {
+39            f, err := file.Open(flag.Arg(i))
+40            if f == nil {
+41                fmt.Fprintf(os.Stderr, &quot;cat: can't open %s: error %s\n&quot;, flag.Arg(i), err)
+42                os.Exit(1)
+43            }
+44            cat(f)
+45            f.Close()
+46        }
+47    }
 </pre>
 <p>
 By now this should be easy to follow, but the <code>switch</code> statement introduces some
@@ -829,10 +859,11 @@ and use it from within a mostly unchanged <code>cat()</code> function:
 67                nw, ew := file.Stdout.Write(buf[0:nr])
 68                if nw != nr {
 69                    fmt.Fprintf(os.Stderr, &quot;cat: error writing from %s: %s\n&quot;, r.String(), ew.String())
-70                }
-71            }
-72        }
-73    }
+70                    os.Exit(1)
+71                }
+72            }
+73        }
+74    }
 </pre>
 <p>
 (We could also do the wrapping in <code>main</code> and leave <code>cat()</code> mostly alone, except
@@ -1209,7 +1240,7 @@ together:
 28    func main() {
 29        ch := make(chan int)  // Create a new channel.
 30        go generate(ch)  // Start generate() as a goroutine.
-31        for {
+31        for i := 0; i &lt; 100; i++ { // Print the first hundred primes.
 32            prime := &lt;-ch
 33            fmt.Println(prime)
 34            ch1 := make(chan int)
@@ -1289,7 +1320,7 @@ Now <code>main</code>'s interface to the prime sieve is a channel of primes:
 <pre> <!-- progs/sieve1.go /func.main/ /^}/ -->
 46    func main() {
 47        primes := sieve()
-48        for {
+48        for i := 0; i &lt; 100; i++ { // Print the first hundred primes.
 49            fmt.Println(&lt;-primes)
 50        }
 51    }
diff --git a/doc/go_tutorial.txt b/doc/go_tutorial.txt
index 2b2a0cd..ab02baf 100644
--- a/doc/go_tutorial.txt
+++ b/doc/go_tutorial.txt
@@ -384,8 +384,8 @@ assigned to a variable.
 An I/O Package
 ----
 
-Next we'll look at a simple package for doing file I/O with the usual
-sort of open/close/read/write interface.  Here's the start of "file.go":
+Next we'll look at a simple package for doing file I/O with an
+open/close/read/write interface.  Here's the start of "file.go":
 
 --PROG progs/file.go /package/ /^}/
 
@@ -437,11 +437,11 @@ We can use the factory to construct some familiar, exported variables of type "*
 --PROG progs/file.go /var/ /^.$/
 
 The "newFile" function was not exported because it's internal. The proper,
-exported factory to use is "Open":
+exported factory to use is "OpenFile" (we'll explain that name in a moment):
 
---PROG progs/file.go /func.Open/ /^}/
+--PROG progs/file.go /func.OpenFile/ /^}/
 
-There are a number of new things in these few lines.  First, "Open" returns
+There are a number of new things in these few lines.  First, "OpenFile" returns
 multiple values, a "File" and an error (more about errors in a moment).
 We declare the
 multi-value return as a parenthesized list of declarations; syntactically
@@ -460,6 +460,20 @@ consistent error handling throughout Go code.   In "Open" we use a
 conversion to translate Unix's integer "errno" value into the integer type
 "os.Errno", which implements "os.Error".
 
+Why "OpenFile" and not "Open"? To mimic Go's "os" package, which
+our exercise is emulating. The "os" package takes the opportunity
+to make the two commonest cases - open for read and create for
+write - the simplest, just "Open" and "Create".  "OpenFile" is the
+general case, analogous to the Unix system call "Open".  Here is
+the implementation of our "Open" and "Create"; they're trivial
+wrappers that eliminate common errors by capturing
+the tricky standard arguments to open and, especially, to create a file:
+
+--PROG progs/file.go /^const/ /^}/
+
+--PROG progs/file.go /func.Create/ /^}/
+
+Back to our main story.
 Now that we can build "Files", we can write methods for them. To declare
 a method of a type, we define a function to have an explicit receiver
 of that type, placed
diff --git a/doc/godocs.js b/doc/godocs.js
index 8b45154..2b3ab06 100644
--- a/doc/godocs.js
+++ b/doc/godocs.js
@@ -34,7 +34,18 @@ function godocs_bindSearchEvents() {
       search.className = "";
     }
   }
+  function restoreInactive() {
+    if (search.value != "") {
+      return;
+    }
+    if (search.type != "search") {
+      search.value = search.getAttribute("placeholder");
+    }
+    search.className = "inactive";
+  }
+  restoreInactive();
   bindEvent(search, 'focus', clearInactive);
+  bindEvent(search, 'blur', restoreInactive);
 }
 
 /* Generates a table of contents: looks for h2 and h3 elements and generates
diff --git a/doc/install.html b/doc/install.html
index 843e064..b989416 100644
--- a/doc/install.html
+++ b/doc/install.html
@@ -80,7 +80,7 @@ To build it, you need these programs installed:
 <li>GCC, 
 <li>the standard C libraries, 
 <li>the parser generator Bison,
-<li><tt>make</tt>, 
+<li>GNU <tt>make</tt> (version 3.81 or later),
 <li><tt>awk</tt>, and 
 <li>the text editor <tt>ed</tt>.
 </ul>
diff --git a/doc/progs/cat.go b/doc/progs/cat.go
index 697e5f7..9f0b8d4 100644
--- a/doc/progs/cat.go
+++ b/doc/progs/cat.go
@@ -24,6 +24,7 @@ func cat(f *file.File) {
 		case nr > 0:
 			if nw, ew := file.Stdout.Write(buf[0:nr]); nw != nr {
 				fmt.Fprintf(os.Stderr, "cat: error writing from %s: %s\n", f.String(), ew.String())
+				os.Exit(1)
 			}
 		}
 	}
@@ -35,7 +36,7 @@ func main() {
 		cat(file.Stdin)
 	}
 	for i := 0; i < flag.NArg(); i++ {
-		f, err := file.Open(flag.Arg(i), 0, 0)
+		f, err := file.Open(flag.Arg(i))
 		if f == nil {
 			fmt.Fprintf(os.Stderr, "cat: can't open %s: error %s\n", flag.Arg(i), err)
 			os.Exit(1)
diff --git a/doc/progs/cat_rot13.go b/doc/progs/cat_rot13.go
index 03fc022..0eefe7c 100644
--- a/doc/progs/cat_rot13.go
+++ b/doc/progs/cat_rot13.go
@@ -67,6 +67,7 @@ func cat(r reader) {
 			nw, ew := file.Stdout.Write(buf[0:nr])
 			if nw != nr {
 				fmt.Fprintf(os.Stderr, "cat: error writing from %s: %s\n", r.String(), ew.String())
+				os.Exit(1)
 			}
 		}
 	}
@@ -78,7 +79,7 @@ func main() {
 		cat(file.Stdin)
 	}
 	for i := 0; i < flag.NArg(); i++ {
-		f, err := file.Open(flag.Arg(i), 0, 0)
+		f, err := file.Open(flag.Arg(i))
 		if f == nil {
 			fmt.Fprintf(os.Stderr, "cat: can't open %s: error %s\n", flag.Arg(i), err)
 			os.Exit(1)
diff --git a/doc/progs/file.go b/doc/progs/file.go
index df3a3cf..2875ce7 100644
--- a/doc/progs/file.go
+++ b/doc/progs/file.go
@@ -27,7 +27,7 @@ var (
 	Stderr = newFile(syscall.Stderr, "/dev/stderr")
 )
 
-func Open(name string, mode int, perm uint32) (file *File, err os.Error) {
+func OpenFile(name string, mode int, perm uint32) (file *File, err os.Error) {
 	r, e := syscall.Open(name, mode, perm)
 	if e != 0 {
 		err = os.Errno(e)
@@ -35,6 +35,21 @@ func Open(name string, mode int, perm uint32) (file *File, err os.Error) {
 	return newFile(r, name), err
 }
 
+const (
+	O_RDONLY = syscall.O_RDONLY
+	O_RDWR   = syscall.O_RDWR
+	O_CREATE = syscall.O_CREAT
+	O_TRUNC  = syscall.O_TRUNC
+)
+
+func Open(name string) (file *File, err os.Error) {
+	return OpenFile(name, O_RDONLY, 0)
+}
+
+func Create(name string) (file *File, err os.Error) {
+	return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
+}
+
 func (file *File) Close() os.Error {
 	if file == nil {
 		return os.EINVAL
diff --git a/doc/progs/helloworld3.go b/doc/progs/helloworld3.go
index adbcea3..5bb0be2 100644
--- a/doc/progs/helloworld3.go
+++ b/doc/progs/helloworld3.go
@@ -13,7 +13,7 @@ import (
 func main() {
 	hello := []byte("hello, world\n")
 	file.Stdout.Write(hello)
-	f, err := file.Open("/does/not/exist",  0,  0)
+	f, err := file.Open("/does/not/exist")
 	if f == nil {
 		fmt.Printf("can't open file; err=%s\n",  err.String())
 		os.Exit(1)
diff --git a/doc/progs/sieve.go b/doc/progs/sieve.go
index fb649e0..c7c3e78 100644
--- a/doc/progs/sieve.go
+++ b/doc/progs/sieve.go
@@ -28,7 +28,7 @@ func filter(in, out chan int, prime int) {
 func main() {
 	ch := make(chan int)  // Create a new channel.
 	go generate(ch)  // Start generate() as a goroutine.
-	for {
+	for i := 0; i < 100; i++ { // Print the first hundred primes.
 		prime := <-ch
 		fmt.Println(prime)
 		ch1 := make(chan int)
diff --git a/doc/progs/sieve1.go b/doc/progs/sieve1.go
index 71468d0..e785e20 100644
--- a/doc/progs/sieve1.go
+++ b/doc/progs/sieve1.go
@@ -45,7 +45,7 @@ func sieve() chan int {
 
 func main() {
 	primes := sieve()
-	for {
+	for i := 0; i < 100; i++ { // Print the first hundred primes.
 		fmt.Println(<-primes)
 	}
 }
diff --git a/lib/codereview/codereview.py b/lib/codereview/codereview.py
index 766e827..bfa69fc 100644
--- a/lib/codereview/codereview.py
+++ b/lib/codereview/codereview.py
@@ -111,6 +111,7 @@ server_url_base = None
 defaultcc = None
 contributors = {}
 missing_codereview = None
+real_rollback = None
 
 #######################################################################
 # RE: UNICODE STRING HANDLING
@@ -196,12 +197,15 @@ class CL(object):
 		self.web = False
 		self.copied_from = None	# None means current user
 		self.mailed = False
+		self.private = False
 
 	def DiskText(self):
 		cl = self
 		s = ""
 		if cl.copied_from:
 			s += "Author: " + cl.copied_from + "\n\n"
+		if cl.private:
+			s += "Private: " + str(self.private) + "\n"
 		s += "Mailed: " + str(self.mailed) + "\n"
 		s += "Description:\n"
 		s += Indent(cl.desc, "\t")
@@ -219,6 +223,8 @@ class CL(object):
 			s += "Author: " + cl.copied_from + "\n"
 		if cl.url != '':
 			s += 'URL: ' + cl.url + '	# cannot edit\n\n'
+		if cl.private:
+			s += "Private: True\n"
 		s += "Reviewer: " + JoinComma(cl.reviewer) + "\n"
 		s += "CC: " + JoinComma(cl.cc) + "\n"
 		s += "\n"
@@ -264,7 +270,8 @@ class CL(object):
 		os.rename(path+'!', path)
 		if self.web and not self.copied_from:
 			EditDesc(self.name, desc=self.desc,
-				reviewers=JoinComma(self.reviewer), cc=JoinComma(self.cc))
+				reviewers=JoinComma(self.reviewer), cc=JoinComma(self.cc),
+				private=self.private)
 
 	def Delete(self, ui, repo):
 		dir = CodeReviewDir(ui, repo)
@@ -389,6 +396,7 @@ def ParseCL(text, name):
 		'Reviewer': '',
 		'CC': '',
 		'Mailed': '',
+		'Private': '',
 	}
 	for line in text.split('\n'):
 		lineno += 1
@@ -435,6 +443,8 @@ def ParseCL(text, name):
 		# CLs created with this update will always have 
 		# Mailed: False on disk.
 		cl.mailed = True
+	if sections['Private'] in ('True', 'true', 'Yes', 'yes'):
+		cl.private = True
 	if cl.desc == '<enter description here>':
 		cl.desc = ''
 	return cl, 0, ''
@@ -779,7 +789,7 @@ def Incoming(ui, repo, opts):
 	_, incoming, _ = findcommonincoming(repo, getremote(ui, repo, opts))
 	return incoming
 
-desc_re = '^(.+: |(tag )?(release|weekly)\.|fix build)'
+desc_re = '^(.+: |(tag )?(release|weekly)\.|fix build|undo CL)'
 
 desc_msg = '''Your CL description appears not to use the standard form.
 
@@ -827,6 +837,9 @@ def EditCL(ui, repo, cl):
 		if clx.desc == '':
 			if promptyesno(ui, "change list should have a description\nre-edit (y/n)?"):
 				continue
+		elif re.search('<enter reason for undo>', clx.desc):
+			if promptyesno(ui, "change list description omits reason for undo\nre-edit (y/n)?"):
+				continue
 		elif not re.match(desc_re, clx.desc.split('\n')[0]):
 			if promptyesno(ui, desc_msg + "re-edit (y/n)?"):
 				continue
@@ -870,6 +883,7 @@ def EditCL(ui, repo, cl):
 		cl.reviewer = clx.reviewer
 		cl.cc = clx.cc
 		cl.files = clx.files
+		cl.private = clx.private
 		break
 	return ""
 
@@ -983,7 +997,10 @@ def CheckTabfmt(ui, repo, files, just_warn):
 	for f in files:
 		try:
 			for line in open(f, 'r'):
-				if line.startswith('    '):
+				# Four leading spaces is enough to complain about,
+				# except that some Plan 9 code uses four spaces as the label indent,
+				# so allow that.
+				if line.startswith('    ') and not re.match('    [A-Za-z0-9_]+:', line):
 					badfiles.append(f)
 					break
 		except:
@@ -1066,7 +1083,7 @@ def change(ui, repo, *pats, **opts):
 			if cl.copied_from:
 				return "original author must delete CL; hg change -D will remove locally"
 			PostMessage(ui, cl.name, "*** Abandoned ***", send_mail=cl.mailed)
-			EditDesc(cl.name, closed="checked")
+			EditDesc(cl.name, closed=True, private=cl.private)
 		cl.Delete(ui, repo)
 		return
 
@@ -1087,6 +1104,9 @@ def change(ui, repo, *pats, **opts):
 		if clx.files is not None:
 			cl.files = clx.files
 			dirty[cl] = True
+		if clx.private != cl.private:
+			cl.private = clx.private
+			dirty[cl] = True
 
 	if not opts["stdin"] and not opts["stdout"]:
 		if name == "new":
@@ -1104,6 +1124,8 @@ def change(ui, repo, *pats, **opts):
 
 	if opts["stdout"]:
 		ui.write(cl.EditorText())
+	elif opts["pending"]:
+		ui.write(cl.PendingText())
 	elif name == "new":
 		if ui.quiet:
 			ui.write(cl.name)
@@ -1132,17 +1154,90 @@ def clpatch(ui, repo, clname, **opts):
 	Submitting an imported patch will keep the original author's
 	name as the Author: line but add your own name to a Committer: line.
 	"""
+	return clpatch_or_undo(ui, repo, clname, opts)
+
+def undo(ui, repo, clname, **opts):
+	"""undo the effect of a CL
+	
+	Creates a new CL that undoes an earlier CL.
+	After creating the CL, opens the CL text for editing so that
+	you can add the reason for the undo to the description.
+	"""
+	return clpatch_or_undo(ui, repo, clname, opts, undo=True)
+
+def rev2clname(rev):
+	# Extract CL name from revision description.
+	# The last line in the description that is a codereview URL is the real one.
+	# Earlier lines might be part of the user-written description.
+	all = re.findall('(?m)^http://codereview.appspot.com/([0-9]+)$', rev.description())
+	if len(all) > 0:
+		return all[-1]
+	return ""
+
+undoHeader = """undo CL %s / %s
+
+<enter reason for undo>
+
+««« original CL description
+"""
+
+undoFooter = """
+»»»
+"""
+
+# Implementation of clpatch/undo.
+def clpatch_or_undo(ui, repo, clname, opts, undo=False):
 	if missing_codereview:
 		return missing_codereview
 
-	cl, vers, patch, err = DownloadCL(ui, repo, clname)
-	if err != "":
-		return err
-	if patch == emptydiff:
-		return "codereview issue %s has no diff" % clname
+	if undo:
+		if hgversion < '1.4':
+			# Don't have cmdutil.match (see implementation of sync command).
+			return "hg is too old to run hg undo - update to 1.4 or newer"
+
+		# Find revision in Mercurial repository.
+		# Assume CL number is 7+ decimal digits.
+		# Otherwise is either change log sequence number (fewer decimal digits),
+		# hexadecimal hash, or tag name.
+		# Mercurial will fall over long before the change log
+		# sequence numbers get to be 7 digits long.
+		if re.match('^[0-9]{7,}$', clname):
+			found = False
+			matchfn = cmdutil.match(repo, [], {'rev': None})
+			def prep(ctx, fns):
+				pass
+			for ctx in cmdutil.walkchangerevs(repo, matchfn, {'rev': None}, prep):
+				rev = repo[ctx.rev()]
+				# Last line with a code review URL is the actual review URL.
+				# Earlier ones might be part of the CL description.
+				n = rev2clname(rev)
+				if n == clname:
+					found = True
+					break
+			if not found:
+				return "cannot find CL %s in local repository" % clname
+		else:
+			rev = repo[clname]
+			if not rev:
+				return "unknown revision %s" % clname
+			clname = rev2clname(rev)
+			if clname == "":
+				return "cannot find CL name in revision description"
+		
+		# Create fresh CL and start with patch that would reverse the change.
+		vers = short(rev.node())
+		cl = CL("new")
+		cl.desc = (undoHeader % (clname, vers)) + rev.description() + undoFooter
+		patch = RunShell(["hg", "diff", "--git", "-r", vers + ":" + short(rev.parents()[0].node())])
 
-	if not repo[vers]:
-		return "codereview issue %s is newer than the current repository; hg sync" % clname
+	else:  # clpatch
+		cl, vers, patch, err = DownloadCL(ui, repo, clname)
+		if err != "":
+			return err
+		if patch == emptydiff:
+			return "codereview issue %s has no diff" % clname
+		if not repo[vers]:
+			return "codereview issue %s is newer than the current repository; hg sync" % clname
 
 	# find current hg version (hg identify)
 	ctx = repo[None]
@@ -1170,13 +1265,19 @@ def clpatch(ui, repo, clname, **opts):
 	cl.local = True
 	cl.files = out.strip().split()
 	if not cl.files:
-		return "codereview issue %s has no diff" % clname
+		return "codereview issue %s has no changed files" % clname
 	files = ChangedFiles(ui, repo, [], opts)
 	extra = Sub(cl.files, files)
 	if extra:
 		ui.warn("warning: these files were listed in the patch but not changed:\n\t" + "\n\t".join(extra) + "\n")
 	cl.Flush(ui, repo)
-	ui.write(cl.PendingText() + "\n")
+	if undo:
+		err = EditCL(ui, repo, cl)
+		if err != "":
+			return "CL created, but error editing: " + err
+		cl.Flush(ui, repo)
+	else:
+		ui.write(cl.PendingText() + "\n")
 
 # portPatch rewrites patch from being a patch against
 # oldver to being a patch against newver.
@@ -1373,10 +1474,6 @@ def mail(ui, repo, *pats, **opts):
 
 	cl.Mail(ui, repo)		
 
-def nocommit(ui, repo, *pats, **opts):
-	"""(disabled when using this extension)"""
-	return "The codereview extension is enabled; do not use commit."
-
 def pending(ui, repo, *pats, **opts):
 	"""show pending changes
 
@@ -1533,7 +1630,7 @@ def submit(ui, repo, *pats, **opts):
 		if r == 0:
 			raise util.Abort("local repository out of date; must sync before submit")
 	except:
-		repo.rollback()
+		real_rollback()
 		raise
 
 	# we're committed. upload final patch, close review, add commit message
@@ -1551,7 +1648,7 @@ def submit(ui, repo, *pats, **opts):
 	PostMessage(ui, cl.name, pmsg, reviewers="", cc=JoinComma(cl.reviewer+cl.cc))
 
 	if not cl.copied_from:
-		EditDesc(cl.name, closed="checked")
+		EditDesc(cl.name, closed=True, private=cl.private)
 	cl.Delete(ui, repo)
 
 def sync(ui, repo, **opts):
@@ -1601,7 +1698,7 @@ def sync_changes(ui, repo):
 					ui.warn("loading CL %s: %s\n" % (clname, err))
 					continue
 				if not cl.copied_from:
-					EditDesc(cl.name, closed="checked")
+					EditDesc(cl.name, closed=True, private=cl.private)
 				cl.Delete(ui, repo)
 
 	if hgversion < '1.4':
@@ -1675,6 +1772,7 @@ cmdtable = {
 			('D', 'deletelocal', None, 'delete locally, but do not change CL on server'),
 			('i', 'stdin', None, 'read change list from standard input'),
 			('o', 'stdout', None, 'print change list to standard output'),
+			('p', 'pending', None, 'print pending summary to standard output'),
 		],
 		"[-d | -D] [-i] [-o] change# or FILE ..."
 	),
@@ -1739,6 +1837,14 @@ cmdtable = {
 		],
 		"[--local]",
 	),
+	"^undo": (
+		undo,
+		[
+			('', 'ignore_hgpatch_failure', None, 'create CL metadata even if hgpatch fails'),
+			('', 'no_incoming', None, 'disable check for incoming changes'),
+		],
+		"change#"
+	),
 	"^upload": (
 		upload,
 		[],
@@ -1813,6 +1919,16 @@ def IsRietveldSubmitted(ui, clname, hex):
 			return True
 	return False
 
+def IsRietveldMailed(ui, clname):
+	feed = XMLGet(ui, "/rss/issue/" + clname)
+	if feed is None:
+		return False
+	for sum in feed.findall("{http://www.w3.org/2005/Atom}entry/{http://www.w3.org/2005/Atom}summary"):
+		text = sum.text.strip()
+		if re.match("I'd like you to review this change", text):
+			return True
+	return False
+
 def DownloadCL(ui, repo, clname):
 	set_status("downloading CL " + clname)
 	cl, err = LoadCL(ui, repo, clname)
@@ -1875,7 +1991,9 @@ def DownloadCL(ui, repo, clname):
 	# Print warning if email is not in CONTRIBUTORS file.
 	him = FindContributor(ui, repo, email)
 	me = FindContributor(ui, repo, None)
-	if him != me:
+	if him == me:
+		cl.mailed = IsRietveldMailed(ui, clname)
+	else:
 		cl.copied_from = email
 
 	return cl, vers, diffdata, ""
@@ -1992,7 +2110,7 @@ def GetSettings(issue):
 		f['description'] = MySend("/"+issue+"/description", force_auth=False)
 	return f
 
-def EditDesc(issue, subject=None, desc=None, reviewers=None, cc=None, closed=None):
+def EditDesc(issue, subject=None, desc=None, reviewers=None, cc=None, closed=False, private=False):
 	set_status("uploading change to description")
 	form_fields = GetForm("/" + issue + "/edit")
 	if subject is not None:
@@ -2003,8 +2121,10 @@ def EditDesc(issue, subject=None, desc=None, reviewers=None, cc=None, closed=Non
 		form_fields['reviewers'] = reviewers
 	if cc is not None:
 		form_fields['cc'] = cc
-	if closed is not None:
-		form_fields['closed'] = closed
+	if closed:
+		form_fields['closed'] = "checked"
+	if private:
+		form_fields['private'] = "checked"
 	ctype, body = EncodeMultipartFormData(form_fields.items(), [])
 	response = MySend("/" + issue + "/edit", body, content_type=ctype)
 	if response != "":
@@ -2039,8 +2159,17 @@ def PostMessage(ui, issue, message, reviewers=None, cc=None, send_mail=True, sub
 class opt(object):
 	pass
 
-def disabled(*opts, **kwopts):
-	raise util.Abort("commit is disabled when codereview is in use")
+def nocommit(*pats, **opts):
+	"""(disabled when using this extension)"""
+	raise util.Abort("codereview extension enabled; use mail, upload, or submit instead of commit")
+
+def nobackout(*pats, **opts):
+	"""(disabled when using this extension)"""
+	raise util.Abort("codereview extension enabled; use undo instead of backout")
+
+def norollback(*pats, **opts):
+	"""(disabled when using this extension)"""
+	raise util.Abort("codereview extension enabled; use undo instead of rollback")
 
 def RietveldSetup(ui, repo):
 	global defaultcc, upload_options, rpc, server, server_url_base, force_google_account, verbosity, contributors
@@ -2068,7 +2197,11 @@ def RietveldSetup(ui, repo):
 	# Should only modify repository with hg submit.
 	# Disable the built-in Mercurial commands that might
 	# trip things up.
-	cmdutil.commit = disabled
+	cmdutil.commit = nocommit
+	global real_rollback
+	real_rollback = repo.rollback
+	repo.rollback = norollback
+	# would install nobackout if we could; oh well
 
 	try:
 		f = open(repo.root + '/CONTRIBUTORS', 'r')
diff --git a/lib/godoc/godoc.html b/lib/godoc/godoc.html
index f1d9c2a..837f53c 100644
--- a/lib/godoc/godoc.html
+++ b/lib/godoc/godoc.html
@@ -33,7 +33,7 @@
         <a href="/pkg/">Packages</a> <span class="sep">|</span>
         <a href="/cmd/">Commands</a> <span class="sep">|</span>
         <a href="/doc/go_spec.html">Specification</a>
-        <input id="search" type="text" name="q" value="{.section Query}{Query|html-esc}{.or}code search{.end}" class="{.section Query}{.or}inactive{.end}" />
+        <input id="search" type="search" name="q" value="{.section Query}{Query|html-esc}{.end}" class="{.section Query}{.or}inactive{.end}" placeholder="code search" results="0" />
         </form>
       </div>
     </div>
diff --git a/misc/dashboard/builder/main.go b/misc/dashboard/builder/main.go
index 735717e..d11cbb1 100644
--- a/misc/dashboard/builder/main.go
+++ b/misc/dashboard/builder/main.go
@@ -34,6 +34,7 @@ var extraEnv = []string{
 	"GOHOSTARCH",
 	"PATH",
 	"DISABLE_NET_TESTS",
+	"MAKEFLAGS",
 	"GOARM",
 }
 
@@ -59,6 +60,7 @@ var (
 	buildRevision = flag.String("rev", "", "Build specified revision and exit")
 	buildCmd      = flag.String("cmd", "./all.bash", "Build command (specify absolute or relative to go/src/)")
 	external      = flag.Bool("external", false, "Build external packages")
+	parallel      = flag.Bool("parallel", false, "Build multiple targets in parallel")
 	verbose       = flag.Bool("v", false, "verbose")
 )
 
@@ -132,9 +134,19 @@ func main() {
 			continue
 		}
 		built := false
-		for _, b := range builders {
-			if b.build() {
-				built = true
+		if *parallel {
+			done := make(chan bool)
+			for _, b := range builders {
+				go func(b *Builder) {
+					done <- b.build()
+				}(b)
+			}
+			for _ = range builders {
+				built = <-done || built
+			}
+		} else {
+			for _, b := range builders {
+				built = b.build() || built
 			}
 		}
 		// only run benchmarks if we didn't build anything
@@ -185,7 +197,7 @@ func NewBuilder(builder string) (*Builder, os.Error) {
 
 	// get goos/goarch from builder string
 	s := strings.Split(builder, "-", 3)
-	if len(s) == 2 {
+	if len(s) >= 2 {
 		b.goos, b.goarch = s[0], s[1]
 	} else {
 		return nil, fmt.Errorf("unsupported builder form: %s", builder)
diff --git a/misc/dashboard/godashboard/benchmark1.html b/misc/dashboard/godashboard/benchmark1.html
deleted file mode 100644
index 2d49e72..0000000
--- a/misc/dashboard/godashboard/benchmark1.html
+++ /dev/null
@@ -1,62 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-  <head>
-    <title>{{benchmark}} - Benchmarks - Go Dashboard</title>
-    <link rel="stylesheet" type="text/css" href="/static/style.css">
-  </head>
-
-  <body>
-    <ul class="menu">
-      <li><a href="/">Build Status</a></li>
-      <li><a href="/package">Packages</a></li>
-      <li><a href="/project">Projects</a></li>
-      <li><a href="/benchmarks">Benchmarks</a></li>
-      <li><a href="http://golang.org/">golang.org</a></li>
-    </ul>
-
-    <h1>Go Dashboard</h1>
-
-    <h2>{{benchmark}}</h2>
-
-    <a href="{{benchmark}}?fmt=json">json</a>
-
-    {% for g in graphs %}
-      <h3>{{g.builder}}</h3>
-      {% if g.url %}
-        <img src="{{g.url}}&chs=600x150&chf=bg,s,00000000&chco=000000ff&chls=1,1,0">
-      {% else %}
-        (no data available)
-      {% endif %}
-    {% endfor %}
-    
-    <br><br>
-    
-    <table class="alternate" cellpadding="0" cellspacing="0">
-      <tr>
-        <th></th>
-        {% for b in builders %}
-          <th class="builder">{{b.goos}}<br>{{b.goarch}}<br>{{b.note}}</th>
-        {% endfor %}
-        <th></th>
-        <th></th>
-        <th></th>
-      </tr>
-
-      {% for r in revs %}
-      <tr>
-        <td class="revision"><span class="hash"><a href="https://code.google.com/p/go/source/detail?r={{r.node}}">{{r.node|slice:":12"}}</a></span></td>
-
-        {% for ns in r.ns_by_builder %}
-          <td class="result">
-          {% if ns %}
-            {{ns}}
-          {% endif %}
-          </td>
-        {% endfor %}
-        <td class="user">{{r.user|escape}}</td>
-        <td class="date">{{r.date|escape}}</td>
-        <td class="desc">{{r.shortdesc|escape}}</td>
-      </tr>
-      {% endfor %}
-  </body>
-</html>
diff --git a/misc/dashboard/godashboard/benchmarks.html b/misc/dashboard/godashboard/benchmarks.html
deleted file mode 100644
index d42fcfe..0000000
--- a/misc/dashboard/godashboard/benchmarks.html
+++ /dev/null
@@ -1,46 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-  <head>
-    <title>Benchmarks - Go Dashboard</title>
-    <link rel="stylesheet" type="text/css" href="/static/style.css">
-  </head>
-
-  <body>
-    <ul class="menu">
-      <li><a href="/">Build Status</a></li>
-      <li><a href="/package">Packages</a></li>
-      <li><a href="/project">Projects</a></li>
-      <li>Benchmarks</li>
-      <li><a href="http://golang.org/">golang.org</a></li>
-    </ul>
-
-    <h1>Go Dashboard</h1>
-    
-    <h2>Benchmarks</h2>
-
-    <table class="alternate" cellpadding="0" cellspacing="0">
-      <tr>
-        <th></th>
-        {% for b in builders %}
-          <th class="builder">{{b.goos}}<br>{{b.goarch}}<br>{{b.note}}</th>
-        {% endfor %}
-      </tr>
-
-      {% for bm in rows %}
-      <tr>
-        <td class="name"><a href="/benchmarks/{{bm.name}}">{{bm.name}}</a></td>
-
-        {% for bl in bm.builders %}
-          <td class="result">
-	    {% if bl.url %}
-	    <img src="{{bl.url}}" />
-	    {% else %}
-	    <img src="/benchmarks/single?benchmark={{bm.name}}&builder={{bl.name}}" />
-	    {% endif %}
-          </td>
-        {% endfor %}
-      </tr>
-      {% endfor %}
-    </table>
-  </body>
-</html>
diff --git a/misc/dashboard/godashboard/gobuild.py b/misc/dashboard/godashboard/gobuild.py
index 1eacdb3..035bf84 100644
--- a/misc/dashboard/godashboard/gobuild.py
+++ b/misc/dashboard/godashboard/gobuild.py
@@ -44,21 +44,12 @@ class Commit(db.Model):
     desc = db.BlobProperty()
 
     # This is the list of builds. Each element is a string of the form <builder
-    # name> "`" <log hash>. If the log hash is empty, then the build was
+    # name> '`' <log hash>. If the log hash is empty, then the build was
     # successful.
     builds = db.StringListProperty()
 
     fail_notification_sent = db.BooleanProperty()
 
-class Benchmark(db.Model):		
-    name = db.StringProperty()		
-    version = db.IntegerProperty()	
-
-class BenchmarkResults(db.Model):
-    builder = db.StringProperty()
-    benchmark = db.StringProperty()
-    data = db.ListProperty(long)	# encoded as [-1, num, iterations, nsperop]*
-
 class Cache(db.Model):
     data = db.BlobProperty()
     expire = db.IntegerProperty()
@@ -69,12 +60,6 @@ class Cache(db.Model):
 class CompressedLog(db.Model):
     log = db.BlobProperty()
 
-# For each builder, we store the last revision that it built. So, if it
-# crashes, it knows where to start up from. The key names for these objects are
-# "hw-" <builder name>
-class Highwater(db.Model):
-    commit = db.StringProperty()
-
 N = 30
 
 def cache_get(key):
@@ -165,34 +150,40 @@ class MainPage(webapp.RequestHandler):
 class GetHighwater(webapp.RequestHandler):
     def get(self):
         builder = self.request.get('builder')
-        
-        key = 'hw-%s' % builder
-        node = memcache.get(key)
-        if node is None:
-            hw = Highwater.get_by_key_name('hw-%s' % builder)
-            if hw is None:
-                # If no highwater has been recorded for this builder,
-                # we go back N+1 commits and return that.
-                q = Commit.all()
-                q.order('-__key__')
-                c = q.fetch(N+1)[-1]
-                node = c.node
-            else:
-                # if the proposed hw is too old, bump it forward
-                node = hw.commit
-                found = False
-                q = Commit.all()
-                q.order('-__key__')
-                recent = q.fetch(N+1)
-                for c in recent:
-                    if c.node == node:
-                        found = True
-                        break
-                if not found:
-                    node = recent[-1].node
-            memcache.set(key, node, 3600)
+        key = 'todo-%s' % builder
+        response = memcache.get(key)
+        if response is None:
+            # Fell out of memcache.  Rebuild from datastore results.
+            # We walk the commit list looking for nodes that have not
+            # been built by this builder and record the *parents* of those
+            # nodes, because each builder builds the revision *after* the
+            # one return (because we might not know about the latest
+            # revision).
+            q = Commit.all()
+            q.order('-__key__')
+            todo = []
+            need = False
+            first = None
+            for c in q.fetch(N+1):
+                if first is None:
+                    first = c
+                if need:
+                    todo.append(c.node)
+                need = not built(c, builder)
+            if not todo:
+                todo.append(first.node)
+            response = ' '.join(todo)
+            memcache.set(key, response, 3600)
         self.response.set_status(200)
-        self.response.out.write(node)
+        if self.request.get('all') != 'yes':
+            response = response.split()[0]
+        self.response.out.write(response)
+
+def built(c, builder):
+    for b in c.builds:
+        if b.startswith(builder+'`'):
+            return True
+    return False
 
 def auth(req):
     k = req.get('key')
@@ -204,32 +195,10 @@ class SetHighwater(webapp.RequestHandler):
             self.response.set_status(403)
             return
 
-        builder = self.request.get('builder')
-        newhw = self.request.get('hw')
-        q = Commit.all()
-        q.filter('node =', newhw)
-        c = q.get()
-        if c is None:
-            self.response.set_status(404)
-            return
-        
-        # if the proposed hw is too old, bump it forward
-        found = False
-        q = Commit.all()
-        q.order('-__key__')
-        recent = q.fetch(N+1)
-        for c in recent:
-            if c.node == newhw:
-                found = True
-                break
-        if not found:
-            c = recent[-1]
-
-        key = 'hw-%s' % builder
-        memcache.delete(key)
-        hw = Highwater(key_name = key)
-        hw.commit = c.node
-        hw.put()
+        # Allow for old builders.
+        # This is a no-op now: we figure out what to build based
+        # on the current dashboard status.
+        return
 
 class LogHandler(webapp.RequestHandler):
     def get(self):
@@ -330,14 +299,8 @@ class Build(webapp.RequestHandler):
 
         db.run_in_transaction(add_build)
 
-        key = 'hw-%s' % builder
-        hw = Highwater.get_by_key_name(key)
-        if hw is None:
-            hw = Highwater(key_name = key)
-        hw.commit = node
-        hw.put()
+        key = 'todo-%s' % builder
         memcache.delete(key)
-        memcache.delete('hw')
 
         def mark_sent():
             n = Commit.get_by_key_name(key_name)
@@ -373,279 +336,12 @@ def failed(c, builder):
             return len(p[1]) > 0
     return False
 
-class Benchmarks(webapp.RequestHandler):
-    def json(self):
-        q = Benchmark.all()
-        q.filter('__key__ >', Benchmark.get_or_insert('v002.').key())
-        bs = q.fetch(10000)
-
-        self.response.set_status(200)
-        self.response.headers['Content-Type'] = 'text/plain; charset=utf-8'
-        self.response.out.write('{"benchmarks": [')
-
-        sep = "\n\t"
-        for b in bs:
-            self.response.out.write('%s"%s"' % (sep, b.name))
-            sep = ",\n\t"
-        self.response.out.write('\n]}\n')
-
-    def get(self):
-        if self.request.get('fmt') == 'json':
-            return self.json()
-
-        self.response.set_status(200)
-        self.response.headers['Content-Type'] = 'text/html; charset=utf-8'
-        page = memcache.get('bench')
-        if not page:
-            # use datastore as cache to avoid computation even
-            # if memcache starts dropping things on the floor
-            logging.error("memcache dropped bench")
-            page = cache_get('bench')
-            if not page:
-                logging.error("cache dropped bench")
-                num = memcache.get('hw')
-                if num is None:
-                    q = Commit.all()
-                    q.order('-__key__')
-                    n = q.fetch(1)[0]
-                    num = n.num
-                    memcache.set('hw', num)
-                page = self.compute(num)
-                cache_set('bench', page, 600)
-            memcache.set('bench', page, 600)
-        self.response.out.write(page)
-
-    def compute(self, num):
-        benchmarks, builders = benchmark_list()
-
-        rows = []
-        for bm in benchmarks:
-            row = {'name':bm, 'builders': []}
-            for bl in builders:
-                key = "single-%s-%s" % (bm, bl)
-                url = memcache.get(key)
-                row['builders'].append({'name': bl, 'url': url})
-            rows.append(row)
-
-        path = os.path.join(os.path.dirname(__file__), 'benchmarks.html')
-        data = {
-            "builders": [builderInfo(b) for b in builders],
-            "rows": rows,
-        }
-        return template.render(path, data)
-
-    def post(self):
-        if not auth(self.request):
-            self.response.set_status(403)
-            return
-
-        builder = self.request.get('builder')
-        node = self.request.get('node')
-        if not validNode(node):
-            logging.error("Not valid node ('%s')", node)
-            self.response.set_status(500)
-            return
-
-        benchmarkdata = self.request.get('benchmarkdata')
-        benchmarkdata = binascii.a2b_base64(benchmarkdata)
-
-        def get_string(i):
-            l, = struct.unpack('>H', i[:2])
-            s = i[2:2+l]
-            if len(s) != l:
-                return None, None
-            return s, i[2+l:]
-
-        benchmarks = {}
-        while len(benchmarkdata) > 0:
-            name, benchmarkdata = get_string(benchmarkdata)
-            iterations_str, benchmarkdata = get_string(benchmarkdata)
-            time_str, benchmarkdata = get_string(benchmarkdata)
-            iterations = int(iterations_str)
-            time = int(time_str)
-
-            benchmarks[name] = (iterations, time)
-
-        q = Commit.all()
-        q.filter('node =', node)
-        n = q.get()
-        if n is None:
-            logging.error('Client asked for unknown commit while uploading benchmarks')
-            self.response.set_status(404)
-            return
-
-        for (benchmark, (iterations, time)) in benchmarks.items():
-            b = Benchmark.get_or_insert('v002.' + benchmark.encode('base64'), name = benchmark, version = 2)
-            key = '%s;%s' % (builder, benchmark)
-            r1 = BenchmarkResults.get_by_key_name(key)
-            if r1 is not None and (len(r1.data) < 4 or r1.data[-4] != -1 or r1.data[-3] != n.num):
-                r1.data += [-1L, long(n.num), long(iterations), long(time)]
-                r1.put()            
-            key = "bench(%s,%s,%d)" % (benchmark, builder, n.num)
-            memcache.delete(key)
-
-        self.response.set_status(200)
-
-class SingleBenchmark(webapp.RequestHandler):
-    """
-    Fetch data for single benchmark/builder combination 
-    and return sparkline url as HTTP redirect, also set memcache entry.
-    """
-    def get(self):
-        benchmark = self.request.get('benchmark')
-        builder = self.request.get('builder')
-        key = "single-%s-%s" % (benchmark, builder)
-
-        url = memcache.get(key)
-
-        if url is None:
-            minr, maxr, bybuilder = benchmark_data(benchmark)
-            for bb in bybuilder:
-                if bb[0] != builder:
-                    continue
-                url = benchmark_sparkline(bb[2])
-
-        if url is None:
-            self.response.set_status(500, "No data found")
-            return
-
-        memcache.set(key, url, 700) # slightly longer than bench timeout 
-
-        self.response.set_status(302)
-        self.response.headers.add_header("Location", url)
-
 def node(num):
     q = Commit.all()
     q.filter('num =', num)
     n = q.get()
     return n
 
-def benchmark_data(benchmark):
-    q = BenchmarkResults.all()
-    q.order('__key__')
-    q.filter('benchmark =', benchmark)
-    results = q.fetch(100)
-
-    minr = 100000000
-    maxr = 0
-    for r in results:
-        if r.benchmark != benchmark:
-            continue
-        # data is [-1, num, iters, nsperop, -1, num, iters, nsperop, ...]
-        d = r.data
-        if not d:
-            continue
-        if [x for x in d[::4] if x != -1]:
-            # unexpected data framing
-            logging.error("bad framing for data in %s;%s" % (r.builder, r.benchmark))
-            continue
-        revs = d[1::4]
-        minr = min(minr, min(revs))
-        maxr = max(maxr, max(revs))
-    if minr > maxr:
-        return 0, 0, []
-
-    bybuilder = []
-    for r in results:
-        if r.benchmark != benchmark:
-            continue
-        d = r.data
-        if not d:
-            continue
-        nsbyrev = [-1 for x in range(minr, maxr+1)]
-        iterbyrev = [-1 for x in range(minr, maxr+1)]
-        for num, iter, ns in zip(d[1::4], d[2::4], d[3::4]):
-            iterbyrev[num - minr] = iter
-            nsbyrev[num - minr] = ns
-        bybuilder.append((r.builder, iterbyrev, nsbyrev))
-
-    return minr, maxr, bybuilder
-
-def benchmark_graph(builder, minhash, maxhash, ns):
-    valid = [x for x in ns if x >= 0]
-    if not valid:
-        return ""
-    m = max(max(valid), 2*sum(valid)/len(valid))
-    s = ""
-    encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.-"
-    for val in ns:
-        if val < 0:
-            s += "__"
-            continue
-        val = int(val*4095.0/m)
-        s += encoding[val/64] + encoding[val%64]
-    return ("http://chart.apis.google.com/chart?cht=lc&chxt=x,y&chxl=0:|%s|%s|1:|0|%g ns|%g ns&chd=e:%s" %
-        (minhash[0:12], maxhash[0:12], m/2, m, s))
-
-def benchmark_sparkline(ns):
-    valid = [x for x in ns if x >= 0]
-    if not valid:
-        return ""
-    m = max(max(valid), 2*sum(valid)/len(valid))
-    # Encoding is 0-61, which is fine enough granularity for our tiny graphs.  _ means missing.
-    encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
-    s = ''.join([x < 0 and "_" or encoding[int((len(encoding)-1)*x/m)] for x in ns])
-    url = "http://chart.apis.google.com/chart?cht=ls&chd=s:"+s+"&chs=80x20&chf=bg,s,00000000&chco=000000ff&chls=1,1,0"
-    return url
-
-def benchmark_list():
-    q = BenchmarkResults.all()
-    q.order('__key__')
-    q.filter('builder = ', u'darwin-amd64')
-    benchmarks = [r.benchmark for r in q]
-    
-    q = BenchmarkResults.all()
-    q.order('__key__')
-    q.filter('benchmark =', u'math_test.BenchmarkSqrt')
-    builders = [r.builder for r in q.fetch(20)]
-    
-    return benchmarks, builders
-    
-class GetBenchmarks(webapp.RequestHandler):
-    def get(self):
-        benchmark = self.request.path[12:]
-        minr, maxr, bybuilder = benchmark_data(benchmark)
-        minhash = node(minr).node
-        maxhash = node(maxr).node
-
-        if self.request.get('fmt') == 'json':
-            self.response.headers['Content-Type'] = 'text/plain; charset=utf-8'
-            self.response.out.write('{ "min": "%s", "max": "%s", "data": {' % (minhash, maxhash))
-            sep = "\n\t"
-            for builder, iter, ns in bybuilder:
-                self.response.out.write('%s{ "builder": "%s", "iterations": %s, "nsperop": %s }' %
-                    (sep, builder, str(iter).replace("L", ""), str(ns).replace("L", "")))
-                sep = ",\n\t"
-            self.response.out.write('\n}\n')
-            return
-        
-        graphs = []
-        for builder, iter, ns in bybuilder:
-            graphs.append({"builder": builder, "url": benchmark_graph(builder, minhash, maxhash, ns)})
-
-        revs = []
-        for i in range(minr, maxr+1):
-            r = nodeInfo(node(i))
-            x = []
-            for _, _, ns in bybuilder:
-                t = ns[i - minr]
-                if t < 0:
-                    t = None
-                x.append(t)
-            r["ns_by_builder"] = x
-            revs.append(r)
-        revs.reverse()  # same order as front page
-        
-        path = os.path.join(os.path.dirname(__file__), 'benchmark1.html')
-        data = {
-            "benchmark": benchmark,
-            "builders": [builderInfo(b) for b,_,_ in bybuilder],
-            "graphs": graphs,
-            "revs": revs,
-        }
-        self.response.out.write(template.render(path, data))
-        
-        
 class FixedOffset(datetime.tzinfo):
     """Fixed offset in minutes east from UTC."""
 
@@ -731,9 +427,6 @@ application = webapp.WSGIApplication(
 
                                       ('/init', Init),
                                       ('/build', Build),
-                                      ('/benchmarks', Benchmarks),
-                                      ('/benchmarks/single', SingleBenchmark),
-                                      ('/benchmarks/.*', GetBenchmarks),
                                      ], debug=True)
 
 def main():
diff --git a/misc/dashboard/godashboard/main.html b/misc/dashboard/godashboard/main.html
index 9572f18..5390afc 100644
--- a/misc/dashboard/godashboard/main.html
+++ b/misc/dashboard/godashboard/main.html
@@ -12,7 +12,6 @@
       <li>Build Status</li>
       <li><a href="/package">Packages</a></li>
       <li><a href="/project">Projects</a></li>
-<!--      <li><a href="/benchmarks">Benchmarks</a></li> -->
       <li><a href="http://golang.org/">golang.org</a></li>
     </ul>
     
diff --git a/misc/dashboard/godashboard/package.html b/misc/dashboard/godashboard/package.html
index 13640c8..9332b5a 100644
--- a/misc/dashboard/godashboard/package.html
+++ b/misc/dashboard/godashboard/package.html
@@ -10,7 +10,6 @@
       <li><a href="/">Build Status</a></li>
       <li>Packages</li>
       <li><a href="/project">Projects</a></li>
-<!--      <li><a href="/benchmarks">Benchmarks</a></li> -->
       <li><a href="http://golang.org/">golang.org</a></li>
     </ul>
 
diff --git a/misc/dashboard/godashboard/project.html b/misc/dashboard/godashboard/project.html
index f1cf7c0..4fe1741 100644
--- a/misc/dashboard/godashboard/project.html
+++ b/misc/dashboard/godashboard/project.html
@@ -14,7 +14,6 @@
       <li><a href="/">Build Status</a></li>
       <li><a href="/package">Packages</a></li>
       <li>Projects</li>
-<!--      <li><a href="/benchmarks">Benchmarks</a></li> -->
       <li><a href="http://golang.org/">golang.org</a></li>
     </ul>
 
diff --git a/misc/goplay/goplay.go b/misc/goplay/goplay.go
index f887fbb..f3e2ff5 100644
--- a/misc/goplay/goplay.go
+++ b/misc/goplay/goplay.go
@@ -235,8 +235,8 @@ function autoindent(el) {
 	}, 1);
 }
 
-function keyHandler() {
-	var e = window.event;
+function keyHandler(event) {
+	var e = window.event || event;
 	if (e.keyCode == 9) { // tab
 		insertTabs(1);
 		e.preventDefault();
@@ -290,7 +290,7 @@ function compileUpdate() {
 </head>
 <body>
 <table width="100%"><tr><td width="60%" valign="top">
-<textarea autofocus="true" id="edit" spellcheck="false" onkeydown="keyHandler();" onkeyup="autocompile();">«@|html»</textarea>
+<textarea autofocus="true" id="edit" spellcheck="false" onkeydown="keyHandler(event);" onkeyup="autocompile();">«@|html»</textarea>
 <div class="hints">
 (Shift-Enter to compile and run.)&nbsp;&nbsp;&nbsp;&nbsp;
 <input type="checkbox" id="autocompile" value="checked" /> Compile and run after each keystroke
diff --git a/src/Make.cmd b/src/Make.cmd
index 6f88e5c..e769e30 100644
--- a/src/Make.cmd
+++ b/src/Make.cmd
@@ -6,6 +6,10 @@ ifeq ($(GOOS),windows)
 TARG:=$(TARG).exe
 endif
 
+ifeq ($(TARGDIR),)
+TARGDIR:=$(QUOTED_GOBIN)
+endif
+
 all: $(TARG)
 
 include $(QUOTED_GOROOT)/src/Make.common
@@ -13,20 +17,20 @@ include $(QUOTED_GOROOT)/src/Make.common
 PREREQ+=$(patsubst %,%.make,$(DEPS))
 
 $(TARG): _go_.$O
-	$(LD) -o $@ _go_.$O
+	$(LD) $(LDIMPORTS) -o $@ _go_.$O
 
 _go_.$O: $(GOFILES) $(PREREQ)
-	$(GC) -o $@ $(GOFILES)
+	$(GC) $(GCIMPORTS) -o $@ $(GOFILES)
 
-install: $(QUOTED_GOBIN)/$(TARG)
+install: $(TARGDIR)/$(TARG)
 
-$(QUOTED_GOBIN)/$(TARG): $(TARG)
-	cp -f $(TARG) $(QUOTED_GOBIN)
+$(TARGDIR)/$(TARG): $(TARG)
+	cp -f $(TARG) $(TARGDIR)
 
 CLEANFILES+=$(TARG) _test _testmain.go
 
 nuke: clean
-	rm -f $(QUOTED_GOBIN)/$(TARG)
+	rm -f $(TARGDIR)/$(TARG)
 
 # for gotest
 testpackage: _test/main.a
@@ -40,7 +44,7 @@ _test/main.a: _gotest_.$O
 	gopack grc $@ _gotest_.$O
 
 _gotest_.$O: $(GOFILES) $(GOTESTFILES)
-	$(GC) -o $@ $(GOFILES) $(GOTESTFILES)
+	$(GC) $(GCIMPORTS) -o $@ $(GOFILES) $(GOTESTFILES)
 
 importpath:
 	echo main
diff --git a/src/Make.common b/src/Make.common
index 34d7016..0b27d07 100644
--- a/src/Make.common
+++ b/src/Make.common
@@ -6,13 +6,13 @@ clean:
 	rm -rf *.o *.a *.[$(OS)] [$(OS)].out $(CLEANFILES)
 
 install.clean: install
-	rm -rf *.o *.a *.[$(OS)] [$(OS)].out $(CLEANFILES)
+	rm -rf *.o *.a *.[$(OS)] [$(OS)].out $(CLEANFILES) || true
 
 test.clean: test
-	rm -rf *.o *.a *.[$(OS)] [$(OS)].out $(CLEANFILES)
+	rm -rf *.o *.a *.[$(OS)] [$(OS)].out $(CLEANFILES) || true
 
 testshort.clean: testshort
-	rm -rf *.o *.a *.[$(OS)] [$(OS)].out $(CLEANFILES)
+	rm -rf *.o *.a *.[$(OS)] [$(OS)].out $(CLEANFILES) || true
 
 %.make:
 	$(MAKE) -C $* install
diff --git a/src/Make.pkg b/src/Make.pkg
index 59ce56a..966bc61 100644
--- a/src/Make.pkg
+++ b/src/Make.pkg
@@ -31,7 +31,11 @@ endif
 
 pkgdir=$(QUOTED_GOROOT)/pkg/$(GOOS)_$(GOARCH)
 
-INSTALLFILES+=$(pkgdir)/$(TARG).a
+ifeq ($(TARGDIR),)
+TARGDIR:=$(pkgdir)
+endif
+
+INSTALLFILES+=$(TARGDIR)/$(TARG).a
 
 # The rest of the cgo rules are below, but these variable updates
 # must be done here so they apply to the main rules.
@@ -46,7 +50,7 @@ GOFILES+=$(patsubst %.swig,_obj/%.go,$(patsubst %.swigcxx,%.swig,$(SWIGFILES)))
 OFILES+=$(patsubst %.swig,_obj/%_gc.$O,$(patsubst %.swigcxx,%.swig,$(SWIGFILES)))
 SWIG_PREFIX=$(subst /,-,$(TARG))
 SWIG_SOS+=$(patsubst %.swig,_obj/$(SWIG_PREFIX)-%.so,$(patsubst %.swigcxx,%.swig,$(SWIGFILES)))
-INSTALLFILES+=$(patsubst %.swig,$(pkgdir)/swig/$(SWIG_PREFIX)-%.so,$(patsubst %.swigcxx,%.swig,$(SWIGFILES)))
+INSTALLFILES+=$(patsubst %.swig,$(TARGDIR)/swig/$(SWIG_PREFIX)-%.so,$(patsubst %.swigcxx,%.swig,$(SWIGFILES)))
 endif
 
 PREREQ+=$(patsubst %,%.make,$(DEPS))
@@ -67,22 +71,22 @@ bench:
 	gotest -test.bench=. -test.run="Do not run tests"
 
 nuke: clean
-	rm -f $(pkgdir)/$(TARG).a
+	rm -f $(TARGDIR)/$(TARG).a
 
 testpackage-clean:
 	rm -f _test/$(TARG).a
 
 install: $(INSTALLFILES)
 
-$(pkgdir)/$(TARG).a: _obj/$(TARG).a
-	@test -d $(QUOTED_GOROOT)/pkg && mkdir -p $(pkgdir)/$(dir)
+$(TARGDIR)/$(TARG).a: _obj/$(TARG).a
+	@test -d $(QUOTED_GOROOT)/pkg && mkdir -p $(TARGDIR)/$(dir)
 	cp _obj/$(TARG).a "$@"
 
 _go_.$O: $(GOFILES) $(PREREQ)
-	$(GC) -o $@ $(GOFILES)
+	$(GC) $(GCIMPORTS) -o $@ $(GOFILES)
 
 _gotest_.$O: $(GOFILES) $(GOTESTFILES) $(PREREQ)
-	$(GC) -o $@ $(GOFILES) $(GOTESTFILES)
+	$(GC) $(GCIMPORTS) -o $@ $(GOFILES) $(GOTESTFILES)
 
 _obj/$(TARG).a: _go_.$O $(OFILES)
 	@mkdir -p _obj/$(dir)
@@ -222,13 +226,13 @@ _obj/$(SWIG_PREFIX)-%.so: _obj/%_wrap.o
 _obj/$(SWIG_PREFIX)-%.so: _obj/%_wrapcxx.o
 	$(HOST_CXX) $(_CGO_CFLAGS_$(GOARCH)) -o $@ $^ $(SWIG_LDFLAGS) $(_CGO_LDFLAGS_$(GOOS)) $(_SWIG_LDFLAGS_$(GOOS))
 
-$(pkgdir)/swig/$(SWIG_PREFIX)-%.so: _obj/$(SWIG_PREFIX)-%.so
-	@test -d $(QUOTED_GOROOT)/pkg && mkdir -p $(pkgdir)/swig
+$(TARGDIR)/swig/$(SWIG_PREFIX)-%.so: _obj/$(SWIG_PREFIX)-%.so
+	@test -d $(QUOTED_GOROOT)/pkg && mkdir -p $(TARGDIR)/swig
 	cp $< "$@"
 
 all: $(SWIG_SOS)
 
-SWIG_RPATH=-r $(pkgdir)/swig
+SWIG_RPATH=-r $(TARGDIR)/swig
 
 endif
 
diff --git a/src/all-qemu.bash b/src/all-qemu.bash
index b2be15a..6d5cd6e 100755
--- a/src/all-qemu.bash
+++ b/src/all-qemu.bash
@@ -6,7 +6,6 @@
 # Run all.bash but exclude tests that depend on functionality
 # missing in QEMU's system call emulation.
 
-export DISABLE_NET_TESTS=1  # no external network
 export NOTEST=""
 
 NOTEST="$NOTEST big" # xxx
diff --git a/src/cmd/5c/swt.c b/src/cmd/5c/swt.c
index d45aabc..431f048 100644
--- a/src/cmd/5c/swt.c
+++ b/src/cmd/5c/swt.c
@@ -665,7 +665,9 @@ align(int32 i, Type *t, int op, int32 *maxalign)
 
 	case Aarg2:	/* width of a parameter */
 		o += t->width;
-		w = SZ_LONG;
+		w = t->width;
+		if(w > SZ_LONG)
+			w = SZ_LONG;
 		break;
 
 	case Aaut3:	/* total align of automatic */
diff --git a/src/cmd/5g/cgen.c b/src/cmd/5g/cgen.c
index 032409b..4e5f7eb 100644
--- a/src/cmd/5g/cgen.c
+++ b/src/cmd/5g/cgen.c
@@ -43,6 +43,8 @@ cgen(Node *n, Node *res)
 	}
 
 	if(isfat(n->type)) {
+		if(n->type->width < 0)
+			fatal("forgot to compute width for %T", n->type);
 		sgen(n, res, n->type->width);
 		goto ret;
 	}
@@ -960,7 +962,7 @@ bgen(Node *n, int true, Prog *to)
 		}
 
 		// make simplest on right
-		if(nl->op == OLITERAL || nl->ullman < nr->ullman) {
+		if(nl->op == OLITERAL || (nl->ullman < UINF && nl->ullman < nr->ullman)) {
 			a = brrev(a);
 			r = nl;
 			nl = nr;
@@ -1071,18 +1073,18 @@ bgen(Node *n, int true, Prog *to)
 		a = optoas(a, nr->type);
 
 		if(nr->ullman >= UINF) {
-			regalloc(&n1, nr->type, N);
-			cgen(nr, &n1);
+			regalloc(&n1, nl->type, N);
+			cgen(nl, &n1);
 
-			tempname(&tmp, nr->type);
+			tempname(&tmp, nl->type);
 			gmove(&n1, &tmp);
 			regfree(&n1);
 
-			regalloc(&n1, nl->type, N);
-			cgen(nl, &n1);
-
 			regalloc(&n2, nr->type, N);
-			cgen(&tmp, &n2);
+			cgen(nr, &n2);
+
+			regalloc(&n1, nl->type, N);
+			cgen(&tmp, &n1);
 
 			gcmp(optoas(OCMP, nr->type), &n1, &n2);
 			patch(gbranch(a, nr->type), to);
diff --git a/src/cmd/5g/gg.h b/src/cmd/5g/gg.h
index ce4575b..78e6833 100644
--- a/src/cmd/5g/gg.h
+++ b/src/cmd/5g/gg.h
@@ -52,7 +52,7 @@ struct	Prog
 
 EXTERN	Biobuf*	bout;
 EXTERN	int32	dynloc;
-EXTERN	uchar	reg[REGALLOC_FMAX];
+EXTERN	uchar	reg[REGALLOC_FMAX+1];
 EXTERN	int32	pcloc;		// instruction counter
 EXTERN	Strlit	emptystring;
 extern	char*	anames[];
diff --git a/src/cmd/5g/peep.c b/src/cmd/5g/peep.c
index ca12d70..6f36e12 100644
--- a/src/cmd/5g/peep.c
+++ b/src/cmd/5g/peep.c
@@ -1134,7 +1134,7 @@ copyu(Prog *p, Adr *v, Adr *s)
 		if(v->type == D_REG) {
 			if(v->reg <= REGEXT && v->reg > exregoffset)
 				return 2;
-			if(v->reg == REGARG)
+			if(v->reg == (uchar)REGARG)
 				return 2;
 		}
 		if(v->type == D_FREG)
@@ -1152,7 +1152,7 @@ copyu(Prog *p, Adr *v, Adr *s)
 
 	case ATEXT:	/* funny */
 		if(v->type == D_REG)
-			if(v->reg == REGARG)
+			if(v->reg == (uchar)REGARG)
 				return 3;
 		return 0;
 	}
diff --git a/src/cmd/5l/l.h b/src/cmd/5l/l.h
index cf5a999..f3c9d83 100644
--- a/src/cmd/5l/l.h
+++ b/src/cmd/5l/l.h
@@ -156,6 +156,7 @@ struct	Sym
 	char*	file;
 	char*	dynimpname;
 	char*	dynimplib;
+	char*	dynimpvers;
 	
 	// STEXT
 	Auto*	autom;
diff --git a/src/cmd/5l/obj.c b/src/cmd/5l/obj.c
index f252f9f..c4a2bfc 100644
--- a/src/cmd/5l/obj.c
+++ b/src/cmd/5l/obj.c
@@ -317,7 +317,7 @@ zaddr(Biobuf *f, Adr *a, Sym *h[])
 	a->sym = h[c];
 	a->name = Bgetc(f);
 
-	if(a->reg < 0 || a->reg > NREG) {
+	if((schar)a->reg < 0 || a->reg > NREG) {
 		print("register out of range %d\n", a->reg);
 		Bputc(f, ALAST+1);
 		return;	/*  force real diagnostic */
@@ -581,7 +581,7 @@ loop:
 			diag("multiple initialization for %s: in both %s and %s", s->name, s->file, pn);
 			errorexit();
 		}
-		savedata(s, p);
+		savedata(s, p, pn);
 		unmal(p, sizeof *p);
 		break;
 
diff --git a/src/cmd/6g/cgen.c b/src/cmd/6g/cgen.c
index 47f3374..75dc4fe 100644
--- a/src/cmd/6g/cgen.c
+++ b/src/cmd/6g/cgen.c
@@ -47,6 +47,8 @@ cgen(Node *n, Node *res)
 	}
 
 	if(isfat(n->type)) {
+		if(n->type->width < 0)
+			fatal("forgot to compute width for %T", n->type);
 		sgen(n, res, n->type->width);
 		goto ret;
 	}
@@ -827,7 +829,7 @@ bgen(Node *n, int true, Prog *to)
 		}
 
 		// make simplest on right
-		if(nl->op == OLITERAL || nl->ullman < nr->ullman) {
+		if(nl->op == OLITERAL || (nl->ullman < nr->ullman && nl->ullman < UINF)) {
 			a = brrev(a);
 			r = nl;
 			nl = nr;
@@ -877,18 +879,18 @@ bgen(Node *n, int true, Prog *to)
 		}
 
 		if(nr->ullman >= UINF) {
-			regalloc(&n1, nr->type, N);
-			cgen(nr, &n1);
+			regalloc(&n1, nl->type, N);
+			cgen(nl, &n1);
 
-			tempname(&tmp, nr->type);
+			tempname(&tmp, nl->type);
 			gmove(&n1, &tmp);
 			regfree(&n1);
 
-			regalloc(&n1, nl->type, N);
-			cgen(nl, &n1);
+			regalloc(&n2, nr->type, N);
+			cgen(nr, &n2);
 
-			regalloc(&n2, nr->type, &n2);
-			cgen(&tmp, &n2);
+			regalloc(&n1, nl->type, N);
+			cgen(&tmp, &n1);
 
 			goto cmp;
 		}
diff --git a/src/cmd/6g/reg.c b/src/cmd/6g/reg.c
index 1e1d64c..ed8bac3 100644
--- a/src/cmd/6g/reg.c
+++ b/src/cmd/6g/reg.c
@@ -1193,7 +1193,6 @@ void
 paint1(Reg *r, int bn)
 {
 	Reg *r1;
-	Prog *p;
 	int z;
 	uint32 bb;
 
@@ -1219,7 +1218,6 @@ paint1(Reg *r, int bn)
 	}
 	for(;;) {
 		r->act.b[z] |= bb;
-		p = r->prog;
 
 		if(r->use1.b[z] & bb) {
 			change += CREF * r->loop;
diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c
index ba2074f..dda19e4 100644
--- a/src/cmd/6l/asm.c
+++ b/src/cmd/6l/asm.c
@@ -95,6 +95,8 @@ enum {
 	ElfStrStrtab,
 	ElfStrRelaPlt,
 	ElfStrPlt,
+	ElfStrGnuVersion,
+	ElfStrGnuVersionR,
 	NElfStr
 };
 
@@ -436,6 +438,7 @@ adddynsym(Sym *s)
 		s->dynid = nelfsym++;
 
 		d = lookup(".dynsym", 0);
+
 		name = s->dynimpname;
 		if(name == nil)
 			name = s->name;
@@ -586,6 +589,8 @@ doelf(void)
 		elfstr[ElfStrRela] = addstring(shstrtab, ".rela");
 		elfstr[ElfStrRelaPlt] = addstring(shstrtab, ".rela.plt");
 		elfstr[ElfStrPlt] = addstring(shstrtab, ".plt");
+		elfstr[ElfStrGnuVersion] = addstring(shstrtab, ".gnu.version");
+		elfstr[ElfStrGnuVersionR] = addstring(shstrtab, ".gnu.version_r");
 
 		/* dynamic symbol table - first entry all zeros */
 		s = lookup(".dynsym", 0);
@@ -629,6 +634,14 @@ doelf(void)
 		s = lookup(".rela.plt", 0);
 		s->reachable = 1;
 		s->type = SELFDATA;
+		
+		s = lookup(".gnu.version", 0);
+		s->reachable = 1;
+		s->type = SELFDATA;
+		
+		s = lookup(".gnu.version_r", 0);
+		s->reachable = 1;
+		s->type = SELFDATA;
 
 		/* define dynamic elf table */
 		s = lookup(".dynamic", 0);
@@ -653,7 +666,8 @@ doelf(void)
 		elfwritedynent(s, DT_PLTREL, DT_RELA);
 		elfwritedynentsymsize(s, DT_PLTRELSZ, lookup(".rela.plt", 0));
 		elfwritedynentsym(s, DT_JMPREL, lookup(".rela.plt", 0));
-		elfwritedynent(s, DT_NULL, 0);
+		
+		// Do not write DT_NULL.  elfdynhash will finish it.
 	}
 }
 
@@ -681,7 +695,7 @@ asmb(void)
 {
 	int32 magic;
 	int a, dynsym;
-	vlong vl, va, startva, fo, w, symo, elfsymo, elfstro, elfsymsize, machlink;
+	vlong vl, startva, symo, elfsymo, elfstro, elfsymsize, machlink;
 	ElfEhdr *eh;
 	ElfPhdr *ph, *pph;
 	ElfShdr *sh;
@@ -735,8 +749,11 @@ asmb(void)
 		/* index of elf text section; needed by asmelfsym, double-checked below */
 		/* !debug['d'] causes extra sections before the .text section */
 		elftextsh = 1;
-		if(!debug['d'])
+		if(!debug['d']) {
 			elftextsh += 10;
+			if(elfverneed)
+				elftextsh += 2;
+		}
 		break;
 	case Hwindows:
 		break;
@@ -846,10 +863,7 @@ asmb(void)
 		/* elf amd-64 */
 
 		eh = getElfEhdr();
-		fo = HEADR;
 		startva = INITTEXT - HEADR;
-		va = startva + fo;
-		w = segtext.filelen;
 
 		/* This null SHdr must appear before all others */
 		sh = newElfShdr(elfstr[ElfStrEmpty]);
@@ -923,6 +937,24 @@ asmb(void)
 			sh->addralign = 1;
 			shsym(sh, lookup(".dynstr", 0));
 
+			if(elfverneed) {
+				sh = newElfShdr(elfstr[ElfStrGnuVersion]);
+				sh->type = SHT_GNU_VERSYM;
+				sh->flags = SHF_ALLOC;
+				sh->addralign = 2;
+				sh->link = dynsym;
+				sh->entsize = 2;
+				shsym(sh, lookup(".gnu.version", 0));
+				
+				sh = newElfShdr(elfstr[ElfStrGnuVersionR]);
+				sh->type = SHT_GNU_VERNEED;
+				sh->flags = SHF_ALLOC;
+				sh->addralign = 8;
+				sh->info = elfverneed;
+				sh->link = dynsym+1;  // dynstr
+				shsym(sh, lookup(".gnu.version_r", 0));
+			}
+
 			sh = newElfShdr(elfstr[ElfStrRelaPlt]);
 			sh->type = SHT_RELA;
 			sh->flags = SHF_ALLOC;
diff --git a/src/cmd/6l/l.h b/src/cmd/6l/l.h
index 4fc13b9..33ca51b 100644
--- a/src/cmd/6l/l.h
+++ b/src/cmd/6l/l.h
@@ -148,6 +148,7 @@ struct	Sym
 	char*	file;
 	char*	dynimpname;
 	char*	dynimplib;
+	char*	dynimpvers;
 	
 	// STEXT
 	Auto*	autom;
diff --git a/src/cmd/6l/obj.c b/src/cmd/6l/obj.c
index 6b43d2d..d53814a 100644
--- a/src/cmd/6l/obj.c
+++ b/src/cmd/6l/obj.c
@@ -356,6 +356,15 @@ zaddr(char *pn, Biobuf *f, Adr *a, Sym *h[])
 			return;
 		}
 	}
+	
+	switch(t) {
+	case D_FILE:
+	case D_FILE1:
+	case D_AUTO:
+	case D_PARAM:
+		if(s == S)
+			mangle(pn);
+	}
 
 	u = mal(sizeof(*u));
 	u->link = curauto;
@@ -380,7 +389,7 @@ ldobj1(Biobuf *f, char *pkg, int64 len, char *pn)
 	vlong ipc;
 	Prog *p;
 	int v, o, r, skip, mode;
-	Sym *h[NSYM], *s, *di;
+	Sym *h[NSYM], *s;
 	uint32 sig;
 	char *name, *x;
 	int ntext;
@@ -391,7 +400,6 @@ ldobj1(Biobuf *f, char *pkg, int64 len, char *pn)
 	lastp = nil;
 	ntext = 0;
 	eof = Boffset(f) + len;
-	di = S;
 	src[0] = 0;
 
 newloop:
@@ -559,7 +567,7 @@ loop:
 			diag("multiple initialization for %s: in both %s and %s", s->name, s->file, pn);
 			errorexit();
 		}
-		savedata(s, p);
+		savedata(s, p, pn);
 		unmal(p, sizeof *p);
 		goto loop;
 
diff --git a/src/cmd/8g/cgen.c b/src/cmd/8g/cgen.c
index 9c326e8..596824a 100644
--- a/src/cmd/8g/cgen.c
+++ b/src/cmd/8g/cgen.c
@@ -78,6 +78,8 @@ cgen(Node *n, Node *res)
 
 	// structs etc get handled specially
 	if(isfat(n->type)) {
+		if(n->type->width < 0)
+			fatal("forgot to compute width for %T", n->type);
 		sgen(n, res, n->type->width);
 		return;
 	}
@@ -898,7 +900,7 @@ bgen(Node *n, int true, Prog *to)
 		}
 
 		// make simplest on right
-		if(nl->op == OLITERAL || nl->ullman < nr->ullman) {
+		if(nl->op == OLITERAL || (nl->ullman < nr->ullman && nl->ullman < UINF)) {
 			a = brrev(a);
 			r = nl;
 			nl = nr;
@@ -1023,8 +1025,8 @@ bgen(Node *n, int true, Prog *to)
 		if(nr->ullman >= UINF) {
 			tempname(&n1, nl->type);
 			tempname(&tmp, nr->type);
-			cgen(nr, &tmp);
 			cgen(nl, &n1);
+			cgen(nr, &tmp);
 			regalloc(&n2, nr->type, N);
 			cgen(&tmp, &n2);
 			goto cmp;
diff --git a/src/cmd/8g/ggen.c b/src/cmd/8g/ggen.c
index 8db5524..920725c 100644
--- a/src/cmd/8g/ggen.c
+++ b/src/cmd/8g/ggen.c
@@ -625,12 +625,8 @@ void
 cgen_div(int op, Node *nl, Node *nr, Node *res)
 {
 	Node ax, dx, oldax, olddx;
-	int rax, rdx;
 	Type *t;
 
-	rax = reg[D_AX];
-	rdx = reg[D_DX];
-
 	if(is64(nl->type))
 		fatal("cgen_div %T", nl->type);
 
diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c
index b9bd0da..f28b8d9 100644
--- a/src/cmd/8l/asm.c
+++ b/src/cmd/8l/asm.c
@@ -91,6 +91,8 @@ enum {
 	ElfStrStrtab,
 	ElfStrRelPlt,
 	ElfStrPlt,
+	ElfStrGnuVersion,
+	ElfStrGnuVersionR,
 	NElfStr
 };
 
@@ -420,7 +422,7 @@ adddynsym(Sym *s)
 		s->dynid = nelfsym++;
 		
 		d = lookup(".dynsym", 0);
-		
+
 		/* name */
 		name = s->dynimpname;
 		if(name == nil)
@@ -545,6 +547,8 @@ doelf(void)
 		elfstr[ElfStrRel] = addstring(shstrtab, ".rel");
 		elfstr[ElfStrRelPlt] = addstring(shstrtab, ".rel.plt");
 		elfstr[ElfStrPlt] = addstring(shstrtab, ".plt");
+		elfstr[ElfStrGnuVersion] = addstring(shstrtab, ".gnu.version");
+		elfstr[ElfStrGnuVersionR] = addstring(shstrtab, ".gnu.version_r");
 
 		/* interpreter string */
 		s = lookup(".interp", 0);
@@ -592,6 +596,14 @@ doelf(void)
 		s = lookup(".rel.plt", 0);
 		s->reachable = 1;
 		s->type = SELFDATA;
+		
+		s = lookup(".gnu.version", 0);
+		s->reachable = 1;
+		s->type = SELFDATA;
+		
+		s = lookup(".gnu.version_r", 0);
+		s->reachable = 1;
+		s->type = SELFDATA;
 
 		elfsetupplt();
 
@@ -617,7 +629,8 @@ doelf(void)
 		elfwritedynent(s, DT_PLTREL, DT_REL);
 		elfwritedynentsymsize(s, DT_PLTRELSZ, lookup(".rel.plt", 0));
 		elfwritedynentsym(s, DT_JMPREL, lookup(".rel.plt", 0));
-		elfwritedynent(s, DT_NULL, 0);
+
+		// Do not write DT_NULL.  elfdynhash will finish it.
 	}
 }
 
@@ -681,8 +694,11 @@ asmb(void)
 		/* index of elf text section; needed by asmelfsym, double-checked below */
 		/* !debug['d'] causes extra sections before the .text section */
 		elftextsh = 1;
-		if(!debug['d'])
+		if(!debug['d']) {
 			elftextsh += 10;
+			if(elfverneed)
+				elftextsh += 2;
+		}
 	}
 
 	symsize = 0;
@@ -966,6 +982,24 @@ asmb(void)
 			sh->addralign = 1;
 			shsym(sh, lookup(".dynstr", 0));
 			
+			if(elfverneed) {
+				sh = newElfShdr(elfstr[ElfStrGnuVersion]);
+				sh->type = SHT_GNU_VERSYM;
+				sh->flags = SHF_ALLOC;
+				sh->addralign = 2;
+				sh->link = dynsym;
+				sh->entsize = 2;
+				shsym(sh, lookup(".gnu.version", 0));
+
+				sh = newElfShdr(elfstr[ElfStrGnuVersionR]);
+				sh->type = SHT_GNU_VERNEED;
+				sh->flags = SHF_ALLOC;
+				sh->addralign = 4;
+				sh->info = elfverneed;
+				sh->link = dynsym+1;  // dynstr
+				shsym(sh, lookup(".gnu.version_r", 0));
+			}
+
 			sh = newElfShdr(elfstr[ElfStrRelPlt]);
 			sh->type = SHT_REL;
 			sh->flags = SHF_ALLOC;
diff --git a/src/cmd/8l/l.h b/src/cmd/8l/l.h
index ac0f395..8f39ef5 100644
--- a/src/cmd/8l/l.h
+++ b/src/cmd/8l/l.h
@@ -147,6 +147,7 @@ struct	Sym
 	char*	file;
 	char*	dynimpname;
 	char*	dynimplib;
+	char*	dynimpvers;
 	
 	// STEXT
 	Auto*	autom;
diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c
index d505dc1..2a38f7e 100644
--- a/src/cmd/8l/obj.c
+++ b/src/cmd/8l/obj.c
@@ -431,7 +431,7 @@ ldobj1(Biobuf *f, char *pkg, int64 len, char *pn)
 	int32 ipc;
 	Prog *p;
 	int v, o, r, skip;
-	Sym *h[NSYM], *s, *di;
+	Sym *h[NSYM], *s;
 	uint32 sig;
 	int ntext;
 	int32 eof;
@@ -442,7 +442,6 @@ ldobj1(Biobuf *f, char *pkg, int64 len, char *pn)
 	lastp = nil;
 	ntext = 0;
 	eof = Boffset(f) + len;
-	di = S;
 	src[0] = 0;
 
 
@@ -600,7 +599,7 @@ loop:
 			diag("multiple initialization for %s: in both %s and %s", s->name, s->file, pn);
 			errorexit();
 		}
-		savedata(s, p);
+		savedata(s, p, pn);
 		unmal(p, sizeof *p);
 		goto loop;
 
diff --git a/src/cmd/8l/prof.c b/src/cmd/8l/prof.c
index 4e95fad..d99c5e4 100644
--- a/src/cmd/8l/prof.c
+++ b/src/cmd/8l/prof.c
@@ -36,7 +36,7 @@
 void
 doprof1(void)
 {
-#if 0	// TODO(rsc)
+#ifdef	NOTDEF  // TODO(rsc)
 	Sym *s;
 	int32 n;
 	Prog *p, *q;
diff --git a/src/cmd/cc/dpchk.c b/src/cmd/cc/dpchk.c
index d78a72a..0e51101 100644
--- a/src/cmd/cc/dpchk.c
+++ b/src/cmd/cc/dpchk.c
@@ -534,6 +534,32 @@ out:
 		print("%s incomplete\n", s->name);
 }
 
+Sym*
+getimpsym(void)
+{
+	int c;
+	char *cp;
+
+	c = getnsc();
+	if(isspace(c) || c == '"') {
+		unget(c);
+		return S;
+	}
+	for(cp = symb;;) {
+		if(cp <= symb+NSYMB-4)
+			*cp++ = c;
+		c = getc();
+		if(c > 0 && !isspace(c) && c != '"')
+			continue;
+		unget(c);
+		break;
+	}
+	*cp = 0;
+	if(cp > symb+NSYMB-4)
+		yyerror("symbol too large: %s", symb);
+	return lookup();
+}
+
 void
 pragdynimport(void)
 {
@@ -541,11 +567,11 @@ pragdynimport(void)
 	char *path;
 	Dynimp *f;
 
-	local = getsym();
+	local = getimpsym();
 	if(local == nil)
 		goto err;
 
-	remote = getsym();
+	remote = getimpsym();
 	if(remote == nil)
 		goto err;
 
diff --git a/src/cmd/cc/macbody b/src/cmd/cc/macbody
index 35740e9..ca8a54c 100644
--- a/src/cmd/cc/macbody
+++ b/src/cmd/cc/macbody
@@ -63,7 +63,7 @@ getsym(void)
 		if(cp <= symb+NSYMB-4)
 			*cp++ = c;
 		c = getc();
-		if(isalnum(c) || c == '_' || c >= 0x80 || c == '$')
+		if(isalnum(c) || c == '_' || c >= 0x80)
 			continue;
 		unget(c);
 		break;
diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go
index 00ffc45..84aeccc 100644
--- a/src/cmd/cgo/main.go
+++ b/src/cmd/cgo/main.go
@@ -20,7 +20,6 @@ import (
 	"os"
 	"reflect"
 	"strings"
-	"runtime"
 )
 
 // A Package collects information about the package we're going to write.
@@ -135,20 +134,7 @@ func main() {
 		// instead of needing to make the linkers duplicate all the
 		// specialized knowledge gcc has about where to look for imported
 		// symbols and which ones to use.
-		syms, imports := dynimport(*dynobj)
-		if runtime.GOOS == "windows" {
-			for _, sym := range syms {
-				ss := strings.Split(sym, ":", -1)
-				fmt.Printf("#pragma dynimport %s %s %q\n", ss[0], ss[0], strings.ToLower(ss[1]))
-			}
-			return
-		}
-		for _, sym := range syms {
-			fmt.Printf("#pragma dynimport %s %s %q\n", sym, sym, "")
-		}
-		for _, p := range imports {
-			fmt.Printf("#pragma dynimport %s %s %q\n", "_", "_", p)
-		}
+		dynimport(*dynobj)
 		return
 	}
 
diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go
index abf8c8b..bc031cc 100644
--- a/src/cmd/cgo/out.go
+++ b/src/cmd/cgo/out.go
@@ -95,42 +95,63 @@ func (p *Package) writeDefs() {
 	fc.Close()
 }
 
-func dynimport(obj string) (syms, imports []string) {
-	var f interface {
-		ImportedLibraries() ([]string, os.Error)
-		ImportedSymbols() ([]string, os.Error)
-	}
-	var isMacho bool
-	var err1, err2, err3 os.Error
-	if f, err1 = elf.Open(obj); err1 != nil {
-		if f, err2 = pe.Open(obj); err2 != nil {
-			if f, err3 = macho.Open(obj); err3 != nil {
-				fatalf("cannot parse %s as ELF (%v) or PE (%v) or Mach-O (%v)", obj, err1, err2, err3)
+func dynimport(obj string) {
+	if f, err := elf.Open(obj); err == nil {
+		sym, err := f.ImportedSymbols()
+		if err != nil {
+			fatalf("cannot load imported symbols from ELF file %s: %v", obj, err)
+		}
+		for _, s := range sym {
+			targ := s.Name
+			if s.Version != "" {
+				targ += "@" + s.Version
 			}
-			isMacho = true
+			fmt.Printf("#pragma dynimport %s %s %q\n", s.Name, targ, s.Library)
+		}
+		lib, err := f.ImportedLibraries()
+		if err != nil {
+			fatalf("cannot load imported libraries from ELF file %s: %v", obj, err)
+		}
+		for _, l := range lib {
+			fmt.Printf("#pragma dynimport _ _ %q\n", l)
 		}
+		return
 	}
 
-	var err os.Error
-	syms, err = f.ImportedSymbols()
-	if err != nil {
-		fatalf("cannot load dynamic symbols: %v", err)
-	}
-	if isMacho {
-		// remove leading _ that OS X insists on
-		for i, s := range syms {
-			if len(s) >= 2 && s[0] == '_' {
-				syms[i] = s[1:]
+	if f, err := macho.Open(obj); err == nil {
+		sym, err := f.ImportedSymbols()
+		if err != nil {
+			fatalf("cannot load imported symbols from Mach-O file %s: %v", obj, err)
+		}
+		for _, s := range sym {
+			if len(s) > 0 && s[0] == '_' {
+				s = s[1:]
 			}
+			fmt.Printf("#pragma dynimport %s %s %q\n", s, s, "")
+		}
+		lib, err := f.ImportedLibraries()
+		if err != nil {
+			fatalf("cannot load imported libraries from Mach-O file %s: %v", obj, err)
 		}
+		for _, l := range lib {
+			fmt.Printf("#pragma dynimport _ _ %q\n", l)
+		}
+		return
 	}
 
-	imports, err = f.ImportedLibraries()
-	if err != nil {
-		fatalf("cannot load dynamic imports: %v", err)
+	if f, err := pe.Open(obj); err == nil {
+		sym, err := f.ImportedSymbols()
+		if err != nil {
+			fatalf("cannot load imported symbols from PE file %s: v", obj, err)
+		}
+		for _, s := range sym {
+			ss := strings.Split(s, ":", -1)
+			fmt.Printf("#pragma dynimport %s %s %q\n", ss[0], ss[0], strings.ToLower(ss[1]))
+		}
+		return
 	}
 
-	return
+	fatalf("cannot parse %s as ELF, Mach-O or PE", obj)
 }
 
 // Construct a gcc struct matching the 6c argument frame.
@@ -312,8 +333,11 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
 	}
 	fmt.Fprintf(fgcc, "\t%s *a = v;\n", ctype)
 	fmt.Fprintf(fgcc, "\t")
-	if n.FuncType.Result != nil {
+	if t := n.FuncType.Result; t != nil {
 		fmt.Fprintf(fgcc, "a->r = ")
+		if c := t.C.String(); c[len(c)-1] == '*' {
+			fmt.Fprintf(fgcc, "(const %s) ", t.C)
+		}
 	}
 	fmt.Fprintf(fgcc, "%s(", n.C)
 	for i := range n.FuncType.Params {
diff --git a/src/cmd/gc/align.c b/src/cmd/gc/align.c
index a01e2ea..a8454bf 100644
--- a/src/cmd/gc/align.c
+++ b/src/cmd/gc/align.c
@@ -468,7 +468,7 @@ typeinit(void)
 			okforadd[i] = 1;
 			okforarith[i] = 1;
 			okforconst[i] = 1;
-//			issimple[i] = 1;
+			issimple[i] = 1;
 		}
 	}
 
@@ -530,7 +530,7 @@ typeinit(void)
 	okfor[OCOM] = okforand;
 	okfor[OMINUS] = okforarith;
 	okfor[ONOT] = okforbool;
-	okfor[OPLUS] = okforadd;
+	okfor[OPLUS] = okforarith;
 
 	// special
 	okfor[OCAP] = okforcap;
diff --git a/src/cmd/gc/cplx.c b/src/cmd/gc/cplx.c
index 3ec9fe5..890cf7f 100644
--- a/src/cmd/gc/cplx.c
+++ b/src/cmd/gc/cplx.c
@@ -12,6 +12,19 @@ static	void	minus(Node *nl, Node *res);
 
 #define	CASE(a,b)	(((a)<<16)|((b)<<0))
 
+static int
+overlap(Node *f, Node *t)
+{
+	// check whether f and t could be overlapping stack references.
+	// not exact, because it's hard to check for the stack register
+	// in portable code.  close enough: worst case we will allocate
+	// an extra temporary and the registerizer will clean it up.
+	return f->op == OINDREG &&
+		t->op == OINDREG &&
+		f->xoffset+f->type->width >= t->xoffset &&
+		t->xoffset+t->type->width >= f->xoffset;
+}
+
 /*
  * generate:
  *	res = n;
@@ -43,9 +56,10 @@ complexmove(Node *f, Node *t)
 	case CASE(TCOMPLEX64,TCOMPLEX128):
 	case CASE(TCOMPLEX128,TCOMPLEX64):
 	case CASE(TCOMPLEX128,TCOMPLEX128):
-		// complex to complex move/convert
-		// make from addable
-		if(!f->addable) {
+		// complex to complex move/convert.
+		// make f addable.
+		// also use temporary if possible stack overlap.
+		if(!f->addable || overlap(f, t)) {
 			tempname(&n1, f->type);
 			complexmove(f, &n1);
 			f = &n1;
diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c
index 3089a23..99af18d 100644
--- a/src/cmd/gc/dcl.c
+++ b/src/cmd/gc/dcl.c
@@ -560,6 +560,7 @@ funcargs(Node *nt)
 {
 	Node *n;
 	NodeList *l;
+	int gen;
 
 	if(nt->op != OTFUNC)
 		fatal("funcargs %O", nt->op);
@@ -589,6 +590,7 @@ funcargs(Node *nt)
 	}
 
 	// declare the out arguments.
+	gen = 0;
 	for(l=nt->rlist; l; l=l->next) {
 		n = l->n;
 		if(n->op != ODCLFIELD)
@@ -596,6 +598,11 @@ funcargs(Node *nt)
 		if(n->left != N) {
 			n->left->op = ONAME;
 			n->left->ntype = n->right;
+			if(isblank(n->left)) {
+				// Give it a name so we can assign to it during return.
+				snprint(namebuf, sizeof(namebuf), ".anon%d", gen++);
+				n->left->sym = lookup(namebuf);
+			}
 			declare(n->left, PPARAMOUT);
 		}
 	}
@@ -672,10 +679,10 @@ typedcl2(Type *pt, Type *t)
 
 ok:
 	n = pt->nod;
-	*pt = *t;
-	pt->method = nil;
+	copytype(pt->nod, t);
+	// unzero nod
 	pt->nod = n;
-	pt->sym = n->sym;
+
 	pt->sym->lastlineno = parserline();
 	declare(n, PEXTERN);
 
@@ -697,12 +704,10 @@ stotype(NodeList *l, int et, Type **t, int funarg)
 	Type *f, *t1, *t2, **t0;
 	Strlit *note;
 	int lno;
-	NodeList *init;
 	Node *n, *left;
 	char *what;
 
 	t0 = t;
-	init = nil;
 	lno = lineno;
 	what = "field";
 	if(et == TINTER)
@@ -1130,6 +1135,32 @@ addmethod(Sym *sf, Type *t, int local)
 	pa = pa->type;
 	f = methtype(pa);
 	if(f == T) {
+		t = pa;
+		if(t != T) {
+			if(isptr[t->etype]) {
+				if(t->sym != S) {
+					yyerror("invalid receiver type %T (%T is a pointer type)", pa, t);
+					return;
+				}
+				t = t->type;
+			}
+		}
+		if(t != T) {
+			if(t->sym == S) {
+				yyerror("invalid receiver type %T (%T is an unnamed type)", pa, t);
+				return;
+			}
+			if(isptr[t->etype]) {
+				yyerror("invalid receiver type %T (%T is a pointer type)", pa, t);
+				return;
+			}
+			if(t->etype == TINTER) {
+				yyerror("invalid receiver type %T (%T is an interface type)", pa, t);
+				return;
+			}
+		}
+		// Should have picked off all the reasons above,
+		// but just in case, fall back to generic error.
 		yyerror("invalid receiver type %T", pa);
 		return;
 	}
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index bb258a1..f58b767 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -315,6 +315,7 @@ struct	Pkg
 {
 	char*	name;
 	Strlit*	path;
+	Sym*	pathsym;
 	char*	prefix;
 	Pkg*	link;
 	char	exported;	// import line written in export data
@@ -581,6 +582,7 @@ struct	Io
 	Biobuf*	bin;
 	int32	ilineno;
 	int	nlsemi;
+	int	eofnl;
 	int	peekc;
 	int	peekc1;	// second peekc for ...
 	char*	cp;	// used for content when bin==nil
@@ -1170,9 +1172,12 @@ Node*	unsafenmagic(Node *n);
  */
 Node*	callnew(Type *t);
 Node*	chanfn(char *name, int n, Type *t);
+void	copytype(Node *n, Type *t);
+void	defertypecopy(Node *n, Type *t);
 Node*	mkcall(char *name, Type *t, NodeList **init, ...);
 Node*	mkcall1(Node *fn, Type *t, NodeList **init, ...);
 void	queuemethod(Node *n);
+void	resumetypecopy(void);
 int	vmatch1(Node *l, Node *r);
 void	walk(Node *fn);
 Node*	walkdef(Node *n);
diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y
index 89899ae..7adfd00 100644
--- a/src/cmd/gc/go.y
+++ b/src/cmd/gc/go.y
@@ -1853,6 +1853,10 @@ hidden_interfacedcl:
 	{
 		$$ = nod(ODCLFIELD, newname($1), typenod(functype(fakethis(), $3, $5)));
 	}
+|	hidden_importsym '(' ohidden_funarg_list ')' ohidden_funres
+	{
+		$$ = nod(ODCLFIELD, newname($1), typenod(functype(fakethis(), $3, $5)));
+	}
 
 ohidden_funres:
 	{
diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c
index bfd9627..04dd0d5 100644
--- a/src/cmd/gc/lex.c
+++ b/src/cmd/gc/lex.c
@@ -249,6 +249,7 @@ main(int argc, char *argv[])
 	for(l=xtop; l; l=l->next)
 		if(l->n->op == ODCL || l->n->op == OAS)
 			typecheck(&l->n, Etop);
+	resumetypecopy();
 	resumecheckwidth();
 	for(l=xtop; l; l=l->next)
 		if(l->n->op == ODCLFUNC)
@@ -1310,7 +1311,7 @@ getc(void)
 			lexlineno++;
 		return c;
 	}
-
+	
 	if(curio.bin == nil) {
 		c = *curio.cp & 0xff;
 		if(c != 0)
@@ -1325,8 +1326,11 @@ getc(void)
 			break;
 		}
 	case EOF:
-		return EOF;
-
+		// insert \n at EOF
+		if(curio.eofnl)
+			return EOF;
+		curio.eofnl = 1;
+		c = '\n';
 	case '\n':
 		if(pushedio.bin == nil)
 			lexlineno++;
diff --git a/src/cmd/gc/print.c b/src/cmd/gc/print.c
index fee37f6..e03a140 100644
--- a/src/cmd/gc/print.c
+++ b/src/cmd/gc/print.c
@@ -242,6 +242,17 @@ exprfmt(Fmt *f, Node *n, int prec)
 		exprfmt(f, n->right, 0);
 		break;
 
+	case OAS2:
+	case OAS2DOTTYPE:
+	case OAS2FUNC:
+	case OAS2MAPR:
+	case OAS2MAPW:
+	case OAS2RECV:
+		exprlistfmt(f, n->list);
+		fmtprint(f, " = ");
+		exprlistfmt(f, n->rlist);
+		break;
+
 	case OADD:
 	case OANDAND:
 	case OANDNOT:
diff --git a/src/cmd/gc/reflect.c b/src/cmd/gc/reflect.c
index b98e820..810787d 100644
--- a/src/cmd/gc/reflect.c
+++ b/src/cmd/gc/reflect.c
@@ -137,7 +137,6 @@ methodfunc(Type *f, Type *receiver)
 static Sig*
 methods(Type *t)
 {
-	int o;
 	Type *f, *mt, *it, *this;
 	Sig *a, *b;
 	Sym *method;
@@ -157,7 +156,6 @@ methods(Type *t)
 	// make list of methods for t,
 	// generating code if necessary.
 	a = nil;
-	o = 0;
 	oldlist = nil;
 	for(f=mt->xmethod; f; f=f->down) {
 		if(f->type->etype != TFUNC)
@@ -184,6 +182,11 @@ methods(Type *t)
 		a = b;
 
 		a->name = method->name;
+		if(!exportname(method->name)) {
+			if(method->pkg == nil)
+				fatal("methods: missing package");
+			a->pkg = method->pkg;
+		}
 		a->isym = methodsym(method, it, 1);
 		a->tsym = methodsym(method, t, 0);
 		a->type = methodfunc(f->type, t);
@@ -240,14 +243,12 @@ static Sig*
 imethods(Type *t)
 {
 	Sig *a, *all, *last;
-	int o;
 	Type *f;
 	Sym *method, *isym;
 	Prog *oldlist;
 
 	all = nil;
 	last = nil;
-	o = 0;
 	oldlist = nil;
 	for(f=t->type; f; f=f->down) {
 		if(f->etype != TFIELD)
@@ -257,8 +258,11 @@ imethods(Type *t)
 		method = f->sym;
 		a = mal(sizeof(*a));
 		a->name = method->name;
-		if(!exportname(method->name))
+		if(!exportname(method->name)) {
+			if(method->pkg == nil)
+				fatal("imethods: missing package");
 			a->pkg = method->pkg;
+		}
 		a->mtype = f->type;
 		a->offset = 0;
 		a->type = methodfunc(f->type, nil);
@@ -301,26 +305,6 @@ imethods(Type *t)
 	return all;
 }
 
-static int
-dgopkgpath(Sym *s, int ot, Pkg *pkg)
-{
-	if(pkg == nil)
-		return dgostringptr(s, ot, nil);
-
-	// Emit reference to go.importpath.""., which 6l will
-	// rewrite using the correct import path.  Every package
-	// that imports this one directly defines the symbol.
-	if(pkg == localpkg) {
-		static Sym *ns;
-		
-		if(ns == nil)
-			ns = pkglookup("importpath.\"\".", mkpkg(strlit("go")));
-		return dsymptr(s, ot, ns, 0);
-	}
-
-	return dgostringptr(s, ot, pkg->name);
-}
-
 static void
 dimportpath(Pkg *p)
 {
@@ -328,6 +312,9 @@ dimportpath(Pkg *p)
 	char *nam;
 	Node *n;
 	
+	if(p->pathsym != S)
+		return;
+
 	if(gopkg == nil) {
 		gopkg = mkpkg(strlit("go"));
 		gopkg->name = "go";
@@ -339,11 +326,33 @@ dimportpath(Pkg *p)
 	free(nam);
 	n->class = PEXTERN;
 	n->xoffset = 0;
+	p->pathsym = n->sym;
 	
 	gdatastring(n, p->path);
 	ggloblsym(n->sym, types[TSTRING]->width, 1);
 }
 
+static int
+dgopkgpath(Sym *s, int ot, Pkg *pkg)
+{
+	if(pkg == nil)
+		return dgostringptr(s, ot, nil);
+
+	// Emit reference to go.importpath.""., which 6l will
+	// rewrite using the correct import path.  Every package
+	// that imports this one directly defines the symbol.
+	if(pkg == localpkg) {
+		static Sym *ns;
+		
+		if(ns == nil)
+			ns = pkglookup("importpath.\"\".", mkpkg(strlit("go")));
+		return dsymptr(s, ot, ns, 0);
+	}
+
+	dimportpath(pkg);
+	return dsymptr(s, ot, pkg->pathsym, 0);
+}
+
 /*
  * uncommonType
  * ../../pkg/runtime/type.go:/uncommonType
@@ -694,7 +703,7 @@ dtypesym(Type *t)
 	int ot, xt, n, isddd, dupok;
 	Sym *s, *s1, *s2;
 	Sig *a, *m;
-	Type *t1, *tbase;
+	Type *t1, *tbase, *t2;
 
 	if(isideal(t))
 		fatal("dtypesym %T", t);
@@ -731,15 +740,25 @@ ok:
 		break;
 
 	case TARRAY:
-		// ../../pkg/runtime/type.go:/ArrayType
-		s1 = dtypesym(t->type);
-		ot = dcommontype(s, ot, t);
-		xt = ot - 2*widthptr;
-		ot = dsymptr(s, ot, s1, 0);
-		if(t->bound < 0)
-			ot = duintptr(s, ot, -1);
-		else
+		if(t->bound >= 0) {
+			// ../../pkg/runtime/type.go:/ArrayType
+			s1 = dtypesym(t->type);
+			t2 = typ(TARRAY);
+			t2->type = t->type;
+			t2->bound = -1;  // slice
+			s2 = dtypesym(t2);
+			ot = dcommontype(s, ot, t);
+			xt = ot - 2*widthptr;
+			ot = dsymptr(s, ot, s1, 0);
+			ot = dsymptr(s, ot, s2, 0);
 			ot = duintptr(s, ot, t->bound);
+		} else {
+			// ../../pkg/runtime/type.go:/SliceType
+			s1 = dtypesym(t->type);
+			ot = dcommontype(s, ot, t);
+			xt = ot - 2*widthptr;
+			ot = dsymptr(s, ot, s1, 0);
+		}
 		break;
 
 	case TCHAN:
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index 2098794..bb25056 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -488,7 +488,7 @@ algtype(Type *t)
 {
 	int a;
 
-	if(issimple[t->etype] || isptr[t->etype] || iscomplex[t->etype] ||
+	if(issimple[t->etype] || isptr[t->etype] ||
 		t->etype == TCHAN || t->etype == TFUNC || t->etype == TMAP) {
 		if(t->width == widthptr)
 			a = AMEMWORD;
@@ -660,12 +660,10 @@ nodbool(int b)
 Type*
 aindex(Node *b, Type *t)
 {
-	NodeList *init;
 	Type *r;
 	int bound;
 
 	bound = -1;	// open bound
-	init = nil;
 	typecheck(&b, Erv);
 	if(b != nil) {
 		switch(consttype(b)) {
@@ -1266,7 +1264,12 @@ Tpretty(Fmt *fp, Type *t)
 	case TINTER:
 		fmtprint(fp, "interface {");
 		for(t1=t->type; t1!=T; t1=t1->down) {
-			fmtprint(fp, " %hS%hhT", t1->sym, t1->type);
+			fmtprint(fp, " ");
+			if(exportname(t1->sym->name))
+				fmtprint(fp, "%hS", t1->sym);
+			else
+				fmtprint(fp, "%S", t1->sym);
+			fmtprint(fp, "%hhT", t1->type);
 			if(t1->down)
 				fmtprint(fp, ";");
 		}
@@ -1728,17 +1731,13 @@ isideal(Type *t)
 Type*
 methtype(Type *t)
 {
-	int ptr;
-
 	if(t == T)
 		return T;
 
 	// strip away pointer if it's there
-	ptr = 0;
 	if(isptr[t->etype]) {
 		if(t->sym != S)
 			return T;
-		ptr = 1;
 		t = t->type;
 		if(t == T)
 			return T;
@@ -1929,13 +1928,14 @@ assignop(Type *src, Type *dst, char **why)
 		}
 		return 0;
 	}
+	if(isptrto(dst, TINTER)) {
+		if(why != nil)
+			*why = smprint(":\n\t%T is pointer to interface, not interface", dst);
+		return 0;
+	}
 	if(src->etype == TINTER && dst->etype != TBLANK) {
-		if(why != nil) {
-			if(isptrto(dst, TINTER))
-				*why = smprint(":\n\t%T is interface, not pointer to interface", src);
-			else	
-				*why = ": need type assertion";
-		}
+		if(why != nil)
+			*why = ": need type assertion";
 		return 0;
 	}
 
diff --git a/src/cmd/gc/swt.c b/src/cmd/gc/swt.c
index fbc9c49..6e8436c 100644
--- a/src/cmd/gc/swt.c
+++ b/src/cmd/gc/swt.c
@@ -250,7 +250,7 @@ newlabel(void)
 static void
 casebody(Node *sw, Node *typeswvar)
 {
-	Node *os, *oc, *n, *c, *last;
+	Node *n, *c, *last;
 	Node *def;
 	NodeList *cas, *stat, *l, *lc;
 	Node *go, *br;
@@ -263,8 +263,6 @@ casebody(Node *sw, Node *typeswvar)
 	cas = nil;	// cases
 	stat = nil;	// statements
 	def = N;	// defaults
-	os = N;		// last statement
-	oc = N;		// last case
 	br = nod(OBREAK, N, N);
 
 	for(l=sw->list; l; l=l->next) {
diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c
index 1cc5abd..c48bf7a 100644
--- a/src/cmd/gc/typecheck.c
+++ b/src/cmd/gc/typecheck.c
@@ -31,6 +31,7 @@ static void	checkassign(Node*);
 static void	checkassignlist(NodeList*);
 static void stringtoarraylit(Node**);
 static Node* resolve(Node*);
+static Type*	getforwtype(Node*);
 
 /*
  * resolve ONONAME to definition, if any.
@@ -56,7 +57,7 @@ typechecklist(NodeList *l, int top)
 		typecheck(&l->n, top);
 }
 
-static char* typekind[] = {
+static char* _typekind[] = {
 	[TINT]		= "int",
 	[TUINT]		= "uint",
 	[TINT8]		= "int8",
@@ -82,8 +83,22 @@ static char* typekind[] = {
 	[TMAP]		= "map",
 	[TARRAY]	= "array",
 	[TFUNC]		= "func",
+	[TNIL]		= "nil",
+	[TIDEAL]	= "ideal number",
 };
 
+static char*
+typekind(int et)
+{
+	static char buf[50];
+	char *s;
+	
+	if(0 <= et && et < nelem(_typekind) && (s=_typekind[et]) != nil)
+		return s;
+	snprint(buf, sizeof buf, "etype=%d", et);
+	return buf;
+}
+
 /*
  * type check node *np.
  * replaces *np with a new pointer in some cases.
@@ -96,7 +111,7 @@ typecheck(Node **np, int top)
 	Node *n, *l, *r;
 	NodeList *args;
 	int lno, ok, ntop;
-	Type *t, *tp, *missing, *have;
+	Type *t, *tp, *ft, *missing, *have;
 	Sym *sym;
 	Val v;
 	char *why;
@@ -139,6 +154,11 @@ typecheck(Node **np, int top)
 			yyerror("use of builtin %S not in function call", n->sym);
 			goto error;
 		}
+
+		// a dance to handle forward-declared recursive pointer types.
+		if(n->op == OTYPE && (ft = getforwtype(n->ntype)) != T)
+			defertypecopy(n, ft);
+
 		walkdef(n);
 		n->realtype = n->type;
 		if(n->op == ONONAME)
@@ -406,7 +426,7 @@ reswitch:
 		}
 		if(!okfor[op][et]) {
 		notokfor:
-			yyerror("invalid operation: %#N (operator %#O not defined on %s)", n, op, typekind[et]);
+			yyerror("invalid operation: %#N (operator %#O not defined on %s)", n, op, typekind(et));
 			goto error;
 		}
 		// okfor allows any array == array;
@@ -992,9 +1012,13 @@ reswitch:
 		defaultlit(&n->right, T);
 		
 		// copy([]byte, string)
-		if(isslice(n->left->type) && n->left->type->type == types[TUINT8] && n->right->type->etype == TSTRING)
-			goto ret;
-
+		if(isslice(n->left->type) && n->right->type->etype == TSTRING) {
+		        if (n->left->type->type ==types[TUINT8])
+			        goto ret;
+		        yyerror("arguments to copy have different element types: %lT and string", n->left->type);
+			goto error;
+		}
+			       
 		if(!isslice(n->left->type) || !isslice(n->right->type)) {
 			if(!isslice(n->left->type) && !isslice(n->right->type))
 				yyerror("arguments to copy must be slices; have %lT, %lT", n->left->type, n->right->type);
@@ -2452,3 +2476,24 @@ stringtoarraylit(Node **np)
 	typecheck(&nn, Erv);
 	*np = nn;
 }
+
+static Type*
+getforwtype(Node *n)
+{
+	Node *f1, *f2;
+
+	for(f1=f2=n; ; n=n->ntype) {
+		if((n = resolve(n)) == N || n->op != OTYPE)
+			return T;
+
+		if(n->type != T && n->type->etype == TFORW)
+			return n->type;
+
+		// Check for ntype cycle.
+		if((f2 = resolve(f2)) != N && (f1 = resolve(f2->ntype)) != N) {
+			f2 = resolve(f1->ntype);
+			if(f1 == n || f2 == n)
+				return T;
+		}
+	}
+}
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index b8c6842..278eef4 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -119,6 +119,62 @@ domethod(Node *n)
 	checkwidth(n->type);
 }
 
+typedef struct NodeTypeList NodeTypeList;
+struct NodeTypeList {
+	Node *n;
+	Type *t;
+	NodeTypeList *next;
+};
+
+static	NodeTypeList	*dntq;
+static	NodeTypeList	*dntend;
+
+void
+defertypecopy(Node *n, Type *t)
+{
+	NodeTypeList *ntl;
+
+	if(n == N || t == T)
+		return;
+
+	ntl = mal(sizeof *ntl);
+	ntl->n = n;
+	ntl->t = t;
+	ntl->next = nil;
+
+	if(dntq == nil)
+		dntq = ntl;
+	else
+		dntend->next = ntl;
+
+	dntend = ntl;
+}
+
+void
+resumetypecopy(void)
+{
+	NodeTypeList *l;
+
+	for(l=dntq; l; l=l->next)
+		copytype(l->n, l->t);
+}
+
+void
+copytype(Node *n, Type *t)
+{
+	*n->type = *t;
+
+	t = n->type;
+	t->sym = n->sym;
+	t->local = n->local;
+	t->vargen = n->vargen;
+	t->siggen = 0;
+	t->method = nil;
+	t->nod = N;
+	t->printed = 0;
+	t->deferwidth = 0;
+}
+
 static void
 walkdeftype(Node *n)
 {
@@ -141,20 +197,14 @@ walkdeftype(Node *n)
 		goto ret;
 	}
 
-	// copy new type and clear fields
-	// that don't come along
 	maplineno = n->type->maplineno;
 	embedlineno = n->type->embedlineno;
-	*n->type = *t;
-	t = n->type;
-	t->sym = n->sym;
-	t->local = n->local;
-	t->vargen = n->vargen;
-	t->siggen = 0;
-	t->method = nil;
-	t->nod = N;
-	t->printed = 0;
-	t->deferwidth = 0;
+
+	// copy new type and clear fields
+	// that don't come along.
+	// anything zeroed here must be zeroed in
+	// typedcl2 too.
+	copytype(n, t);
 
 	// double-check use of type as map key.
 	if(maplineno) {
@@ -197,7 +247,6 @@ Node*
 walkdef(Node *n)
 {
 	int lno;
-	NodeList *init;
 	Node *e;
 	Type *t;
 	NodeList *l;
@@ -236,7 +285,6 @@ walkdef(Node *n)
 	if(n->type != T || n->sym == S)	// builtin or no name
 		goto ret;
 
-	init = nil;
 	switch(n->op) {
 	default:
 		fatal("walkdef %O", n->op);
@@ -380,14 +428,13 @@ walkstmt(Node **np)
 {
 	NodeList *init;
 	NodeList *ll, *rl;
-	int cl, lno;
+	int cl;
 	Node *n, *f;
 
 	n = *np;
 	if(n == N)
 		return;
 
-	lno = lineno;
 	setlineno(n);
 
 	switch(n->op) {
@@ -1359,7 +1406,7 @@ walkexpr(Node **np, NodeList **init)
 
 	case OSTRARRAYBYTE:
 		// stringtoslicebyte(string) []byte;
-		n = mkcall("stringtoslicebyte", n->type, init, n->left);
+		n = mkcall("stringtoslicebyte", n->type, init, conv(n->left, types[TSTRING]));
 		goto ret;
 
 	case OSTRARRAYRUNE:
@@ -1788,7 +1835,7 @@ walkprint(Node *nn, NodeList **init, int defer)
 					on = syslook("printiface", 1);
 				argtype(on, n->type);		// any-1
 			}
-		} else if(isptr[et] || et == TCHAN || et == TMAP || et == TFUNC) {
+		} else if(isptr[et] || et == TCHAN || et == TMAP || et == TFUNC || et == TUNSAFEPTR) {
 			if(defer) {
 				fmtprint(&fmt, "%%p");
 			} else {
diff --git a/src/cmd/gofix/doc.go b/src/cmd/gofix/doc.go
index 902fe76..a9790e6 100644
--- a/src/cmd/gofix/doc.go
+++ b/src/cmd/gofix/doc.go
@@ -18,6 +18,9 @@ If the named path is a directory, gofix rewrites all .go files in that
 directory tree.  When gofix rewrites a file, it prints a line to standard
 error giving the name of the file and the rewrite applied.
 
+If the -diff flag is set, no files are rewritten. Instead gofix prints
+the differences a rewrite would introduce.
+
 The -r flag restricts the set of rewrites considered to those in the
 named list.  By default gofix considers all known rewrites.  Gofix's
 rewrites are idempotent, so that it is safe to apply gofix to updated
@@ -29,6 +32,5 @@ to see them, run gofix -?.
 Gofix does not make backup copies of the files that it edits.
 Instead, use a version control system's ``diff'' functionality to inspect
 the changes that gofix makes before committing them.
-
 */
 package documentation
diff --git a/src/cmd/gofix/reflect.go b/src/cmd/gofix/reflect.go
index 74ddb39..3c8beca 100644
--- a/src/cmd/gofix/reflect.go
+++ b/src/cmd/gofix/reflect.go
@@ -21,6 +21,7 @@ var reflectFix = fix{
 	`Adapt code to new reflect API.
 
 http://codereview.appspot.com/4281055
+http://codereview.appspot.com/4433066
 `,
 }
 
@@ -279,6 +280,23 @@ func reflectFn(f *ast.File) bool {
 		fixed = true
 	})
 
+	// Rewrite
+	//	reflect.Typeof -> reflect.TypeOf,
+	walk(f, func(n interface{}) {
+		sel, ok := n.(*ast.SelectorExpr)
+		if !ok {
+			return
+		}
+		if isTopName(sel.X, "reflect") && sel.Sel.Name == "Typeof" {
+			sel.Sel.Name = "TypeOf"
+			fixed = true
+		}
+		if isTopName(sel.X, "reflect") && sel.Sel.Name == "NewValue" {
+			sel.Sel.Name = "ValueOf"
+			fixed = true
+		}
+	})
+
 	return fixed
 }
 
diff --git a/src/cmd/gofix/testdata/reflect.asn1.go.out b/src/cmd/gofix/testdata/reflect.asn1.go.out
index 9026359..f5716f2 100644
--- a/src/cmd/gofix/testdata/reflect.asn1.go.out
+++ b/src/cmd/gofix/testdata/reflect.asn1.go.out
@@ -418,13 +418,13 @@ func parseSequenceOf(bytes []byte, sliceType reflect.Type, elemType reflect.Type
 }
 
 var (
-	bitStringType        = reflect.Typeof(BitString{})
-	objectIdentifierType = reflect.Typeof(ObjectIdentifier{})
-	enumeratedType       = reflect.Typeof(Enumerated(0))
-	flagType             = reflect.Typeof(Flag(false))
-	timeType             = reflect.Typeof(&time.Time{})
-	rawValueType         = reflect.Typeof(RawValue{})
-	rawContentsType      = reflect.Typeof(RawContent(nil))
+	bitStringType        = reflect.TypeOf(BitString{})
+	objectIdentifierType = reflect.TypeOf(ObjectIdentifier{})
+	enumeratedType       = reflect.TypeOf(Enumerated(0))
+	flagType             = reflect.TypeOf(Flag(false))
+	timeType             = reflect.TypeOf(&time.Time{})
+	rawValueType         = reflect.TypeOf(RawValue{})
+	rawContentsType      = reflect.TypeOf(RawContent(nil))
 )
 
 // invalidLength returns true iff offset + length > sliceLength, or if the
@@ -461,7 +461,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
 		}
 		result := RawValue{t.class, t.tag, t.isCompound, bytes[offset : offset+t.length], bytes[initOffset : offset+t.length]}
 		offset += t.length
-		v.Set(reflect.NewValue(result))
+		v.Set(reflect.ValueOf(result))
 		return
 	}
 
@@ -506,7 +506,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
 			return
 		}
 		if result != nil {
-			ifaceValue.Set(reflect.NewValue(result))
+			ifaceValue.Set(reflect.ValueOf(result))
 		}
 		return
 	}
@@ -609,7 +609,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
 		sliceValue := v
 		sliceValue.Set(reflect.MakeSlice(sliceValue.Type(), len(newSlice), len(newSlice)))
 		if err1 == nil {
-			reflect.Copy(sliceValue, reflect.NewValue(newSlice))
+			reflect.Copy(sliceValue, reflect.ValueOf(newSlice))
 		}
 		err = err1
 		return
@@ -617,7 +617,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
 		structValue := v
 		bs, err1 := parseBitString(innerBytes)
 		if err1 == nil {
-			structValue.Set(reflect.NewValue(bs))
+			structValue.Set(reflect.ValueOf(bs))
 		}
 		err = err1
 		return
@@ -631,7 +631,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
 			time, err1 = parseGeneralizedTime(innerBytes)
 		}
 		if err1 == nil {
-			ptrValue.Set(reflect.NewValue(time))
+			ptrValue.Set(reflect.ValueOf(time))
 		}
 		err = err1
 		return
@@ -679,7 +679,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
 		if structType.NumField() > 0 &&
 			structType.Field(0).Type == rawContentsType {
 			bytes := bytes[initOffset:offset]
-			val.Field(0).Set(reflect.NewValue(RawContent(bytes)))
+			val.Field(0).Set(reflect.ValueOf(RawContent(bytes)))
 		}
 
 		innerOffset := 0
@@ -701,7 +701,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
 		sliceType := fieldType
 		if sliceType.Elem().Kind() == reflect.Uint8 {
 			val.Set(reflect.MakeSlice(sliceType, len(innerBytes), len(innerBytes)))
-			reflect.Copy(val, reflect.NewValue(innerBytes))
+			reflect.Copy(val, reflect.ValueOf(innerBytes))
 			return
 		}
 		newSlice, err1 := parseSequenceOf(innerBytes, sliceType, sliceType.Elem())
@@ -806,7 +806,7 @@ func Unmarshal(b []byte, val interface{}) (rest []byte, err os.Error) {
 // UnmarshalWithParams allows field parameters to be specified for the
 // top-level element. The form of the params is the same as the field tags.
 func UnmarshalWithParams(b []byte, val interface{}, params string) (rest []byte, err os.Error) {
-	v := reflect.NewValue(val).Elem()
+	v := reflect.ValueOf(val).Elem()
 	offset, err := parseField(v, b, 0, parseFieldParameters(params))
 	if err != nil {
 		return nil, err
diff --git a/src/cmd/gofix/testdata/reflect.datafmt.go.out b/src/cmd/gofix/testdata/reflect.datafmt.go.out
index 6d816fc..bd7f5fd 100644
--- a/src/cmd/gofix/testdata/reflect.datafmt.go.out
+++ b/src/cmd/gofix/testdata/reflect.datafmt.go.out
@@ -671,7 +671,7 @@ func (f Format) Eval(env Environment, args ...interface{}) ([]byte, os.Error) {
 
 	go func() {
 		for _, v := range args {
-			fld := reflect.NewValue(v)
+			fld := reflect.ValueOf(v)
 			if !fld.IsValid() {
 				errors <- os.NewError("nil argument")
 				return
diff --git a/src/cmd/gofix/testdata/reflect.decode.go.out b/src/cmd/gofix/testdata/reflect.decode.go.out
index a5fd339..feeb7b8 100644
--- a/src/cmd/gofix/testdata/reflect.decode.go.out
+++ b/src/cmd/gofix/testdata/reflect.decode.go.out
@@ -122,11 +122,11 @@ func (d *decodeState) unmarshal(v interface{}) (err os.Error) {
 		}
 	}()
 
-	rv := reflect.NewValue(v)
+	rv := reflect.ValueOf(v)
 	pv := rv
 	if pv.Kind() != reflect.Ptr ||
 		pv.IsNil() {
-		return &InvalidUnmarshalError{reflect.Typeof(v)}
+		return &InvalidUnmarshalError{reflect.TypeOf(v)}
 	}
 
 	d.scan.reset()
@@ -314,7 +314,7 @@ func (d *decodeState) array(v reflect.Value) {
 	iv := v
 	ok := iv.Kind() == reflect.Interface
 	if ok {
-		iv.Set(reflect.NewValue(d.arrayInterface()))
+		iv.Set(reflect.ValueOf(d.arrayInterface()))
 		return
 	}
 
@@ -410,7 +410,7 @@ func (d *decodeState) object(v reflect.Value) {
 	// Decoding into nil interface?  Switch to non-reflect code.
 	iv := v
 	if iv.Kind() == reflect.Interface {
-		iv.Set(reflect.NewValue(d.objectInterface()))
+		iv.Set(reflect.ValueOf(d.objectInterface()))
 		return
 	}
 
@@ -423,7 +423,7 @@ func (d *decodeState) object(v reflect.Value) {
 	case reflect.Map:
 		// map must have string type
 		t := v.Type()
-		if t.Key() != reflect.Typeof("") {
+		if t.Key() != reflect.TypeOf("") {
 			d.saveError(&UnmarshalTypeError{"object", v.Type()})
 			break
 		}
@@ -514,7 +514,7 @@ func (d *decodeState) object(v reflect.Value) {
 		// Write value back to map;
 		// if using struct, subv points into struct already.
 		if mv.IsValid() {
-			mv.SetMapIndex(reflect.NewValue(key), subv)
+			mv.SetMapIndex(reflect.ValueOf(key), subv)
 		}
 
 		// Next token must be , or }.
@@ -570,7 +570,7 @@ func (d *decodeState) literal(v reflect.Value) {
 		case reflect.Bool:
 			v.SetBool(value)
 		case reflect.Interface:
-			v.Set(reflect.NewValue(value))
+			v.Set(reflect.ValueOf(value))
 		}
 
 	case '"': // string
@@ -592,11 +592,11 @@ func (d *decodeState) literal(v reflect.Value) {
 				d.saveError(err)
 				break
 			}
-			v.Set(reflect.NewValue(b[0:n]))
+			v.Set(reflect.ValueOf(b[0:n]))
 		case reflect.String:
 			v.SetString(string(s))
 		case reflect.Interface:
-			v.Set(reflect.NewValue(string(s)))
+			v.Set(reflect.ValueOf(string(s)))
 		}
 
 	default: // number
@@ -613,7 +613,7 @@ func (d *decodeState) literal(v reflect.Value) {
 				d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
 				break
 			}
-			v.Set(reflect.NewValue(n))
+			v.Set(reflect.ValueOf(n))
 
 		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
 			n, err := strconv.Atoi64(s)
@@ -767,7 +767,7 @@ func (d *decodeState) literalInterface() interface{} {
 		}
 		n, err := strconv.Atof64(string(item))
 		if err != nil {
-			d.saveError(&UnmarshalTypeError{"number " + string(item), reflect.Typeof(0.0)})
+			d.saveError(&UnmarshalTypeError{"number " + string(item), reflect.TypeOf(0.0)})
 		}
 		return n
 	}
diff --git a/src/cmd/gofix/testdata/reflect.decoder.go.out b/src/cmd/gofix/testdata/reflect.decoder.go.out
index a631c27..170eedb 100644
--- a/src/cmd/gofix/testdata/reflect.decoder.go.out
+++ b/src/cmd/gofix/testdata/reflect.decoder.go.out
@@ -50,7 +50,7 @@ func (dec *Decoder) recvType(id typeId) {
 
 	// Type:
 	wire := new(wireType)
-	dec.decodeValue(tWireType, reflect.NewValue(wire))
+	dec.decodeValue(tWireType, reflect.ValueOf(wire))
 	if dec.err != nil {
 		return
 	}
@@ -161,7 +161,7 @@ func (dec *Decoder) Decode(e interface{}) os.Error {
 	if e == nil {
 		return dec.DecodeValue(reflect.Value{})
 	}
-	value := reflect.NewValue(e)
+	value := reflect.ValueOf(e)
 	// If e represents a value as opposed to a pointer, the answer won't
 	// get back to the caller.  Make sure it's a pointer.
 	if value.Type().Kind() != reflect.Ptr {
diff --git a/src/cmd/gofix/testdata/reflect.dnsmsg.go.out b/src/cmd/gofix/testdata/reflect.dnsmsg.go.out
index 546e713..12e4c34 100644
--- a/src/cmd/gofix/testdata/reflect.dnsmsg.go.out
+++ b/src/cmd/gofix/testdata/reflect.dnsmsg.go.out
@@ -430,7 +430,7 @@ func packStructValue(val reflect.Value, msg []byte, off int) (off1 int, ok bool)
 			if off+n > len(msg) {
 				return len(msg), false
 			}
-			reflect.Copy(reflect.NewValue(msg[off:off+n]), fv)
+			reflect.Copy(reflect.ValueOf(msg[off:off+n]), fv)
 			off += n
 		case reflect.String:
 			// There are multiple string encodings.
@@ -460,7 +460,7 @@ func packStructValue(val reflect.Value, msg []byte, off int) (off1 int, ok bool)
 }
 
 func structValue(any interface{}) reflect.Value {
-	return reflect.NewValue(any).Elem()
+	return reflect.ValueOf(any).Elem()
 }
 
 func packStruct(any interface{}, msg []byte, off int) (off1 int, ok bool) {
@@ -508,7 +508,7 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, ok boo
 			if off+n > len(msg) {
 				return len(msg), false
 			}
-			reflect.Copy(fv, reflect.NewValue(msg[off:off+n]))
+			reflect.Copy(fv, reflect.ValueOf(msg[off:off+n]))
 			off += n
 		case reflect.String:
 			var s string
diff --git a/src/cmd/gofix/testdata/reflect.encode.go.out b/src/cmd/gofix/testdata/reflect.encode.go.out
index 8c79a27..9a13a75 100644
--- a/src/cmd/gofix/testdata/reflect.encode.go.out
+++ b/src/cmd/gofix/testdata/reflect.encode.go.out
@@ -172,7 +172,7 @@ func (e *encodeState) marshal(v interface{}) (err os.Error) {
 			err = r.(os.Error)
 		}
 	}()
-	e.reflectValue(reflect.NewValue(v))
+	e.reflectValue(reflect.ValueOf(v))
 	return nil
 }
 
@@ -180,7 +180,7 @@ func (e *encodeState) error(err os.Error) {
 	panic(err)
 }
 
-var byteSliceType = reflect.Typeof([]byte(nil))
+var byteSliceType = reflect.TypeOf([]byte(nil))
 
 func (e *encodeState) reflectValue(v reflect.Value) {
 	if !v.IsValid() {
diff --git a/src/cmd/gofix/testdata/reflect.encoder.go.out b/src/cmd/gofix/testdata/reflect.encoder.go.out
index 928f3b2..781ef65 100644
--- a/src/cmd/gofix/testdata/reflect.encoder.go.out
+++ b/src/cmd/gofix/testdata/reflect.encoder.go.out
@@ -97,7 +97,7 @@ func (enc *Encoder) sendActualType(w io.Writer, state *encoderState, ut *userTyp
 	// Id:
 	state.encodeInt(-int64(info.id))
 	// Type:
-	enc.encode(state.b, reflect.NewValue(info.wire), wireTypeUserInfo)
+	enc.encode(state.b, reflect.ValueOf(info.wire), wireTypeUserInfo)
 	enc.writeMessage(w, state.b)
 	if enc.err != nil {
 		return
@@ -162,7 +162,7 @@ func (enc *Encoder) sendType(w io.Writer, state *encoderState, origt reflect.Typ
 // Encode transmits the data item represented by the empty interface value,
 // guaranteeing that all necessary type information has been transmitted first.
 func (enc *Encoder) Encode(e interface{}) os.Error {
-	return enc.EncodeValue(reflect.NewValue(e))
+	return enc.EncodeValue(reflect.ValueOf(e))
 }
 
 // sendTypeDescriptor makes sure the remote side knows about this type.
diff --git a/src/cmd/gofix/testdata/reflect.export.go.out b/src/cmd/gofix/testdata/reflect.export.go.out
index 2209f04..486a812 100644
--- a/src/cmd/gofix/testdata/reflect.export.go.out
+++ b/src/cmd/gofix/testdata/reflect.export.go.out
@@ -111,9 +111,9 @@ func (client *expClient) getChan(hdr *header, dir Dir) *netChan {
 // data arrives from the client.
 func (client *expClient) run() {
 	hdr := new(header)
-	hdrValue := reflect.NewValue(hdr)
+	hdrValue := reflect.ValueOf(hdr)
 	req := new(request)
-	reqValue := reflect.NewValue(req)
+	reqValue := reflect.ValueOf(req)
 	error := new(error)
 	for {
 		*hdr = header{}
@@ -341,7 +341,7 @@ func (exp *Exporter) Sync(timeout int64) os.Error {
 }
 
 func checkChan(chT interface{}, dir Dir) (reflect.Value, os.Error) {
-	chanType := reflect.Typeof(chT)
+	chanType := reflect.TypeOf(chT)
 	if chanType.Kind() != reflect.Chan {
 		return reflect.Value{}, os.ErrorString("not a channel")
 	}
@@ -359,7 +359,7 @@ func checkChan(chT interface{}, dir Dir) (reflect.Value, os.Error) {
 			return reflect.Value{}, os.ErrorString("to import/export with Recv, must provide chan<-")
 		}
 	}
-	return reflect.NewValue(chT), nil
+	return reflect.ValueOf(chT), nil
 }
 
 // Export exports a channel of a given type and specified direction.  The
diff --git a/src/cmd/gofix/testdata/reflect.print.go.out b/src/cmd/gofix/testdata/reflect.print.go.out
index e3dc775..079948c 100644
--- a/src/cmd/gofix/testdata/reflect.print.go.out
+++ b/src/cmd/gofix/testdata/reflect.print.go.out
@@ -260,7 +260,7 @@ func getField(v reflect.Value, i int) reflect.Value {
 	val := v.Field(i)
 	if i := val; i.Kind() == reflect.Interface {
 		if inter := i.Interface(); inter != nil {
-			return reflect.NewValue(inter)
+			return reflect.ValueOf(inter)
 		}
 	}
 	return val
@@ -284,7 +284,7 @@ func (p *pp) unknownType(v interface{}) {
 		return
 	}
 	p.buf.WriteByte('?')
-	p.buf.WriteString(reflect.Typeof(v).String())
+	p.buf.WriteString(reflect.TypeOf(v).String())
 	p.buf.WriteByte('?')
 }
 
@@ -296,7 +296,7 @@ func (p *pp) badVerb(verb int, val interface{}) {
 	if val == nil {
 		p.buf.Write(nilAngleBytes)
 	} else {
-		p.buf.WriteString(reflect.Typeof(val).String())
+		p.buf.WriteString(reflect.TypeOf(val).String())
 		p.add('=')
 		p.printField(val, 'v', false, false, 0)
 	}
@@ -525,7 +525,7 @@ func (p *pp) fmtPointer(field interface{}, value reflect.Value, verb int, goSynt
 	}
 	if goSyntax {
 		p.add('(')
-		p.buf.WriteString(reflect.Typeof(field).String())
+		p.buf.WriteString(reflect.TypeOf(field).String())
 		p.add(')')
 		p.add('(')
 		if u == 0 {
@@ -540,10 +540,10 @@ func (p *pp) fmtPointer(field interface{}, value reflect.Value, verb int, goSynt
 }
 
 var (
-	intBits     = reflect.Typeof(0).Bits()
-	floatBits   = reflect.Typeof(0.0).Bits()
-	complexBits = reflect.Typeof(1i).Bits()
-	uintptrBits = reflect.Typeof(uintptr(0)).Bits()
+	intBits     = reflect.TypeOf(0).Bits()
+	floatBits   = reflect.TypeOf(0.0).Bits()
+	complexBits = reflect.TypeOf(1i).Bits()
+	uintptrBits = reflect.TypeOf(uintptr(0)).Bits()
 )
 
 func (p *pp) printField(field interface{}, verb int, plus, goSyntax bool, depth int) (wasString bool) {
@@ -560,10 +560,10 @@ func (p *pp) printField(field interface{}, verb int, plus, goSyntax bool, depth
 	// %T (the value's type) and %p (its address) are special; we always do them first.
 	switch verb {
 	case 'T':
-		p.printField(reflect.Typeof(field).String(), 's', false, false, 0)
+		p.printField(reflect.TypeOf(field).String(), 's', false, false, 0)
 		return false
 	case 'p':
-		p.fmtPointer(field, reflect.NewValue(field), verb, goSyntax)
+		p.fmtPointer(field, reflect.ValueOf(field), verb, goSyntax)
 		return false
 	}
 	// Is it a Formatter?
@@ -651,7 +651,7 @@ func (p *pp) printField(field interface{}, verb int, plus, goSyntax bool, depth
 	}
 
 	// Need to use reflection
-	value := reflect.NewValue(field)
+	value := reflect.ValueOf(field)
 
 BigSwitch:
 	switch f := value; f.Kind() {
@@ -702,7 +702,7 @@ BigSwitch:
 		}
 	case reflect.Struct:
 		if goSyntax {
-			p.buf.WriteString(reflect.Typeof(field).String())
+			p.buf.WriteString(reflect.TypeOf(field).String())
 		}
 		p.add('{')
 		v := f
@@ -728,7 +728,7 @@ BigSwitch:
 		value := f.Elem()
 		if !value.IsValid() {
 			if goSyntax {
-				p.buf.WriteString(reflect.Typeof(field).String())
+				p.buf.WriteString(reflect.TypeOf(field).String())
 				p.buf.Write(nilParenBytes)
 			} else {
 				p.buf.Write(nilAngleBytes)
@@ -754,7 +754,7 @@ BigSwitch:
 			return verb == 's'
 		}
 		if goSyntax {
-			p.buf.WriteString(reflect.Typeof(field).String())
+			p.buf.WriteString(reflect.TypeOf(field).String())
 			p.buf.WriteByte('{')
 		} else {
 			p.buf.WriteByte('[')
@@ -792,7 +792,7 @@ BigSwitch:
 		}
 		if goSyntax {
 			p.buf.WriteByte('(')
-			p.buf.WriteString(reflect.Typeof(field).String())
+			p.buf.WriteString(reflect.TypeOf(field).String())
 			p.buf.WriteByte(')')
 			p.buf.WriteByte('(')
 			if v == 0 {
@@ -913,7 +913,7 @@ func (p *pp) doPrintf(format string, a []interface{}) {
 		for ; fieldnum < len(a); fieldnum++ {
 			field := a[fieldnum]
 			if field != nil {
-				p.buf.WriteString(reflect.Typeof(field).String())
+				p.buf.WriteString(reflect.TypeOf(field).String())
 				p.buf.WriteByte('=')
 			}
 			p.printField(field, 'v', false, false, 0)
@@ -932,7 +932,7 @@ func (p *pp) doPrint(a []interface{}, addspace, addnewline bool) {
 		// always add spaces if we're doing println
 		field := a[fieldnum]
 		if fieldnum > 0 {
-			isString := field != nil && reflect.Typeof(field).Kind() == reflect.String
+			isString := field != nil && reflect.TypeOf(field).Kind() == reflect.String
 			if addspace || !isString && !prevString {
 				p.buf.WriteByte(' ')
 			}
diff --git a/src/cmd/gofix/testdata/reflect.quick.go.out b/src/cmd/gofix/testdata/reflect.quick.go.out
index 152dbad..c62305b 100644
--- a/src/cmd/gofix/testdata/reflect.quick.go.out
+++ b/src/cmd/gofix/testdata/reflect.quick.go.out
@@ -59,39 +59,39 @@ func Value(t reflect.Type, rand *rand.Rand) (value reflect.Value, ok bool) {
 
 	switch concrete := t; concrete.Kind() {
 	case reflect.Bool:
-		return reflect.NewValue(rand.Int()&1 == 0), true
+		return reflect.ValueOf(rand.Int()&1 == 0), true
 	case reflect.Float32, reflect.Float64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, reflect.Complex64, reflect.Complex128:
 		switch t.Kind() {
 		case reflect.Float32:
-			return reflect.NewValue(randFloat32(rand)), true
+			return reflect.ValueOf(randFloat32(rand)), true
 		case reflect.Float64:
-			return reflect.NewValue(randFloat64(rand)), true
+			return reflect.ValueOf(randFloat64(rand)), true
 		case reflect.Complex64:
-			return reflect.NewValue(complex(randFloat32(rand), randFloat32(rand))), true
+			return reflect.ValueOf(complex(randFloat32(rand), randFloat32(rand))), true
 		case reflect.Complex128:
-			return reflect.NewValue(complex(randFloat64(rand), randFloat64(rand))), true
+			return reflect.ValueOf(complex(randFloat64(rand), randFloat64(rand))), true
 		case reflect.Int16:
-			return reflect.NewValue(int16(randInt64(rand))), true
+			return reflect.ValueOf(int16(randInt64(rand))), true
 		case reflect.Int32:
-			return reflect.NewValue(int32(randInt64(rand))), true
+			return reflect.ValueOf(int32(randInt64(rand))), true
 		case reflect.Int64:
-			return reflect.NewValue(randInt64(rand)), true
+			return reflect.ValueOf(randInt64(rand)), true
 		case reflect.Int8:
-			return reflect.NewValue(int8(randInt64(rand))), true
+			return reflect.ValueOf(int8(randInt64(rand))), true
 		case reflect.Int:
-			return reflect.NewValue(int(randInt64(rand))), true
+			return reflect.ValueOf(int(randInt64(rand))), true
 		case reflect.Uint16:
-			return reflect.NewValue(uint16(randInt64(rand))), true
+			return reflect.ValueOf(uint16(randInt64(rand))), true
 		case reflect.Uint32:
-			return reflect.NewValue(uint32(randInt64(rand))), true
+			return reflect.ValueOf(uint32(randInt64(rand))), true
 		case reflect.Uint64:
-			return reflect.NewValue(uint64(randInt64(rand))), true
+			return reflect.ValueOf(uint64(randInt64(rand))), true
 		case reflect.Uint8:
-			return reflect.NewValue(uint8(randInt64(rand))), true
+			return reflect.ValueOf(uint8(randInt64(rand))), true
 		case reflect.Uint:
-			return reflect.NewValue(uint(randInt64(rand))), true
+			return reflect.ValueOf(uint(randInt64(rand))), true
 		case reflect.Uintptr:
-			return reflect.NewValue(uintptr(randInt64(rand))), true
+			return reflect.ValueOf(uintptr(randInt64(rand))), true
 		}
 	case reflect.Map:
 		numElems := rand.Intn(complexSize)
@@ -130,7 +130,7 @@ func Value(t reflect.Type, rand *rand.Rand) (value reflect.Value, ok bool) {
 		for i := 0; i < numChars; i++ {
 			codePoints[i] = rand.Intn(0x10ffff)
 		}
-		return reflect.NewValue(string(codePoints)), true
+		return reflect.ValueOf(string(codePoints)), true
 	case reflect.Struct:
 		s := reflect.Zero(t)
 		for i := 0; i < s.NumField(); i++ {
@@ -339,7 +339,7 @@ func arbitraryValues(args []reflect.Value, f reflect.Type, config *Config, rand
 }
 
 func functionAndType(f interface{}) (v reflect.Value, t reflect.Type, ok bool) {
-	v = reflect.NewValue(f)
+	v = reflect.ValueOf(f)
 	ok = v.Kind() == reflect.Func
 	if !ok {
 		return
diff --git a/src/cmd/gofix/testdata/reflect.read.go.out b/src/cmd/gofix/testdata/reflect.read.go.out
index a3ddb9d..554b2a6 100644
--- a/src/cmd/gofix/testdata/reflect.read.go.out
+++ b/src/cmd/gofix/testdata/reflect.read.go.out
@@ -139,7 +139,7 @@ import (
 // to a freshly allocated value and then mapping the element to that value.
 //
 func Unmarshal(r io.Reader, val interface{}) os.Error {
-	v := reflect.NewValue(val)
+	v := reflect.ValueOf(val)
 	if v.Kind() != reflect.Ptr {
 		return os.NewError("non-pointer passed to Unmarshal")
 	}
@@ -176,7 +176,7 @@ func (e *TagPathError) String() string {
 // Passing a nil start element indicates that Unmarshal should
 // read the token stream to find the start element.
 func (p *Parser) Unmarshal(val interface{}, start *StartElement) os.Error {
-	v := reflect.NewValue(val)
+	v := reflect.ValueOf(val)
 	if v.Kind() != reflect.Ptr {
 		return os.NewError("non-pointer passed to Unmarshal")
 	}
@@ -280,7 +280,7 @@ func (p *Parser) unmarshal(val reflect.Value, start *StartElement) os.Error {
 
 	case reflect.Struct:
 		if _, ok := v.Interface().(Name); ok {
-			v.Set(reflect.NewValue(start.Name))
+			v.Set(reflect.ValueOf(start.Name))
 			break
 		}
 
@@ -316,7 +316,7 @@ func (p *Parser) unmarshal(val reflect.Value, start *StartElement) os.Error {
 			if _, ok := v.Interface().(Name); !ok {
 				return UnmarshalError(sv.Type().String() + " field XMLName does not have type xml.Name")
 			}
-			v.Set(reflect.NewValue(start.Name))
+			v.Set(reflect.ValueOf(start.Name))
 		}
 
 		// Assign attributes.
@@ -508,21 +508,21 @@ Loop:
 	case reflect.String:
 		t.SetString(string(data))
 	case reflect.Slice:
-		t.Set(reflect.NewValue(data))
+		t.Set(reflect.ValueOf(data))
 	}
 
 	switch t := saveComment; t.Kind() {
 	case reflect.String:
 		t.SetString(string(comment))
 	case reflect.Slice:
-		t.Set(reflect.NewValue(comment))
+		t.Set(reflect.ValueOf(comment))
 	}
 
 	switch t := saveXML; t.Kind() {
 	case reflect.String:
 		t.SetString(string(saveXMLData))
 	case reflect.Slice:
-		t.Set(reflect.NewValue(saveXMLData))
+		t.Set(reflect.ValueOf(saveXMLData))
 	}
 
 	return nil
diff --git a/src/cmd/gofix/testdata/reflect.scan.go.out b/src/cmd/gofix/testdata/reflect.scan.go.out
index b1b3975..42bc52c 100644
--- a/src/cmd/gofix/testdata/reflect.scan.go.out
+++ b/src/cmd/gofix/testdata/reflect.scan.go.out
@@ -423,7 +423,7 @@ func (s *ss) token(skipSpace bool, f func(int) bool) []byte {
 
 // typeError indicates that the type of the operand did not match the format
 func (s *ss) typeError(field interface{}, expected string) {
-	s.errorString("expected field of type pointer to " + expected + "; found " + reflect.Typeof(field).String())
+	s.errorString("expected field of type pointer to " + expected + "; found " + reflect.TypeOf(field).String())
 }
 
 var complexError = os.ErrorString("syntax error scanning complex number")
@@ -908,7 +908,7 @@ func (s *ss) scanOne(verb int, field interface{}) {
 		// If we scanned to bytes, the slice would point at the buffer.
 		*v = []byte(s.convertString(verb))
 	default:
-		val := reflect.NewValue(v)
+		val := reflect.ValueOf(v)
 		ptr := val
 		if ptr.Kind() != reflect.Ptr {
 			s.errorString("Scan: type not a pointer: " + val.Type().String())
diff --git a/src/cmd/gofix/testdata/reflect.script.go.out b/src/cmd/gofix/testdata/reflect.script.go.out
index b180184..bc5a6a4 100644
--- a/src/cmd/gofix/testdata/reflect.script.go.out
+++ b/src/cmd/gofix/testdata/reflect.script.go.out
@@ -134,19 +134,19 @@ type empty struct {
 }
 
 func newEmptyInterface(e empty) reflect.Value {
-	return reflect.NewValue(e).Field(0)
+	return reflect.ValueOf(e).Field(0)
 }
 
 func (s Send) send() {
 	// With reflect.ChanValue.Send, we must match the types exactly. So, if
 	// s.Channel is a chan interface{} we convert s.Value to an interface{}
 	// first.
-	c := reflect.NewValue(s.Channel)
+	c := reflect.ValueOf(s.Channel)
 	var v reflect.Value
 	if iface := c.Type().Elem(); iface.Kind() == reflect.Interface && iface.NumMethod() == 0 {
 		v = newEmptyInterface(empty{s.Value})
 	} else {
-		v = reflect.NewValue(s.Value)
+		v = reflect.ValueOf(s.Value)
 	}
 	c.Send(v)
 }
@@ -162,7 +162,7 @@ func (s Close) getSend() sendAction { return s }
 
 func (s Close) getChannel() interface{} { return s.Channel }
 
-func (s Close) send() { reflect.NewValue(s.Channel).Close() }
+func (s Close) send() { reflect.ValueOf(s.Channel).Close() }
 
 // A ReceivedUnexpected error results if no active Events match a value
 // received from a channel.
@@ -278,7 +278,7 @@ func getChannels(events []*Event) ([]interface{}, os.Error) {
 			continue
 		}
 		c := event.action.getChannel()
-		if reflect.NewValue(c).Kind() != reflect.Chan {
+		if reflect.ValueOf(c).Kind() != reflect.Chan {
 			return nil, SetupError("one of the channel values is not a channel")
 		}
 
@@ -303,7 +303,7 @@ func getChannels(events []*Event) ([]interface{}, os.Error) {
 // channel repeatedly, wrapping them up as either a channelRecv or
 // channelClosed structure, and forwards them to the multiplex channel.
 func recvValues(multiplex chan<- interface{}, channel interface{}) {
-	c := reflect.NewValue(channel)
+	c := reflect.ValueOf(channel)
 
 	for {
 		v, ok := c.Recv()
diff --git a/src/cmd/gofix/testdata/reflect.template.go.out b/src/cmd/gofix/testdata/reflect.template.go.out
index 28872db..c362884 100644
--- a/src/cmd/gofix/testdata/reflect.template.go.out
+++ b/src/cmd/gofix/testdata/reflect.template.go.out
@@ -646,7 +646,7 @@ func (t *Template) lookup(st *state, v reflect.Value, name string) reflect.Value
 			}
 			return av.FieldByName(name)
 		case reflect.Map:
-			if v := av.MapIndex(reflect.NewValue(name)); v.IsValid() {
+			if v := av.MapIndex(reflect.ValueOf(name)); v.IsValid() {
 				return v
 			}
 			return reflect.Zero(typ.Elem())
@@ -797,7 +797,7 @@ func (t *Template) executeElement(i int, st *state) int {
 		return elem.end
 	}
 	e := t.elems.At(i)
-	t.execError(st, 0, "internal error: bad directive in execute: %v %T\n", reflect.NewValue(e).Interface(), e)
+	t.execError(st, 0, "internal error: bad directive in execute: %v %T\n", reflect.ValueOf(e).Interface(), e)
 	return 0
 }
 
@@ -980,7 +980,7 @@ func (t *Template) ParseFile(filename string) (err os.Error) {
 // generating output to wr.
 func (t *Template) Execute(wr io.Writer, data interface{}) (err os.Error) {
 	// Extract the driver data.
-	val := reflect.NewValue(data)
+	val := reflect.ValueOf(data)
 	defer checkError(&err)
 	t.p = 0
 	t.execute(0, t.elems.Len(), &state{parent: nil, data: val, wr: wr})
diff --git a/src/cmd/gofix/testdata/reflect.type.go.out b/src/cmd/gofix/testdata/reflect.type.go.out
index 8fd1748..a39b074 100644
--- a/src/cmd/gofix/testdata/reflect.type.go.out
+++ b/src/cmd/gofix/testdata/reflect.type.go.out
@@ -243,18 +243,18 @@ var (
 )
 
 // Predefined because it's needed by the Decoder
-var tWireType = mustGetTypeInfo(reflect.Typeof(wireType{})).id
+var tWireType = mustGetTypeInfo(reflect.TypeOf(wireType{})).id
 var wireTypeUserInfo *userTypeInfo // userTypeInfo of (*wireType)
 
 func init() {
 	// Some magic numbers to make sure there are no surprises.
 	checkId(16, tWireType)
-	checkId(17, mustGetTypeInfo(reflect.Typeof(arrayType{})).id)
-	checkId(18, mustGetTypeInfo(reflect.Typeof(CommonType{})).id)
-	checkId(19, mustGetTypeInfo(reflect.Typeof(sliceType{})).id)
-	checkId(20, mustGetTypeInfo(reflect.Typeof(structType{})).id)
-	checkId(21, mustGetTypeInfo(reflect.Typeof(fieldType{})).id)
-	checkId(23, mustGetTypeInfo(reflect.Typeof(mapType{})).id)
+	checkId(17, mustGetTypeInfo(reflect.TypeOf(arrayType{})).id)
+	checkId(18, mustGetTypeInfo(reflect.TypeOf(CommonType{})).id)
+	checkId(19, mustGetTypeInfo(reflect.TypeOf(sliceType{})).id)
+	checkId(20, mustGetTypeInfo(reflect.TypeOf(structType{})).id)
+	checkId(21, mustGetTypeInfo(reflect.TypeOf(fieldType{})).id)
+	checkId(23, mustGetTypeInfo(reflect.TypeOf(mapType{})).id)
 
 	builtinIdToType = make(map[typeId]gobType)
 	for k, v := range idToType {
@@ -268,7 +268,7 @@ func init() {
 	}
 	nextId = firstUserId
 	registerBasics()
-	wireTypeUserInfo = userType(reflect.Typeof((*wireType)(nil)))
+	wireTypeUserInfo = userType(reflect.TypeOf((*wireType)(nil)))
 }
 
 // Array type
@@ -569,7 +569,7 @@ func checkId(want, got typeId) {
 // used for building the basic types; called only from init().  the incoming
 // interface always refers to a pointer.
 func bootstrapType(name string, e interface{}, expect typeId) typeId {
-	rt := reflect.Typeof(e).Elem()
+	rt := reflect.TypeOf(e).Elem()
 	_, present := types[rt]
 	if present {
 		panic("bootstrap type already present: " + name + ", " + rt.String())
@@ -723,7 +723,7 @@ func RegisterName(name string, value interface{}) {
 		// reserved for nil
 		panic("attempt to register empty name")
 	}
-	base := userType(reflect.Typeof(value)).base
+	base := userType(reflect.TypeOf(value)).base
 	// Check for incompatible duplicates.
 	if t, ok := nameToConcreteType[name]; ok && t != base {
 		panic("gob: registering duplicate types for " + name)
@@ -732,7 +732,7 @@ func RegisterName(name string, value interface{}) {
 		panic("gob: registering duplicate names for " + base.String())
 	}
 	// Store the name and type provided by the user....
-	nameToConcreteType[name] = reflect.Typeof(value)
+	nameToConcreteType[name] = reflect.TypeOf(value)
 	// but the flattened type in the type table, since that's what decode needs.
 	concreteTypeToName[base] = name
 }
@@ -745,7 +745,7 @@ func RegisterName(name string, value interface{}) {
 // between types and names is not a bijection.
 func Register(value interface{}) {
 	// Default to printed representation for unnamed types
-	rt := reflect.Typeof(value)
+	rt := reflect.TypeOf(value)
 	name := rt.String()
 
 	// But for named types (or pointers to them), qualify with import path.
diff --git a/src/cmd/gofix/typecheck.go b/src/cmd/gofix/typecheck.go
index d565e7b..2d81b97 100644
--- a/src/cmd/gofix/typecheck.go
+++ b/src/cmd/gofix/typecheck.go
@@ -259,7 +259,7 @@ func typecheck1(cfg *TypeConfig, f interface{}, typeof map[interface{}]string) {
 		if n == nil {
 			return
 		}
-		if false && reflect.Typeof(n).Kind() == reflect.Ptr { // debugging trace
+		if false && reflect.TypeOf(n).Kind() == reflect.Ptr { // debugging trace
 			defer func() {
 				if t := typeof[n]; t != "" {
 					pos := fset.Position(n.(ast.Node).Pos())
@@ -375,6 +375,11 @@ func typecheck1(cfg *TypeConfig, f interface{}, typeof map[interface{}]string) {
 				typeof[n] = gofmt(n.Args[0])
 				return
 			}
+			// new(T) has type *T
+			if isTopName(n.Fun, "new") && len(n.Args) == 1 {
+				typeof[n] = "*" + gofmt(n.Args[0])
+				return
+			}
 			// Otherwise, use type of function to determine arguments.
 			t := typeof[n.Fun]
 			in, out := splitFunc(t)
diff --git a/src/cmd/gofmt/doc.go b/src/cmd/gofmt/doc.go
index e44030e..1373b26 100644
--- a/src/cmd/gofmt/doc.go
+++ b/src/cmd/gofmt/doc.go
@@ -8,29 +8,37 @@ Gofmt formats Go programs.
 Without an explicit path, it processes the standard input.  Given a file,
 it operates on that file; given a directory, it operates on all .go files in
 that directory, recursively.  (Files starting with a period are ignored.)
+By default, gofmt prints the reformatted sources to standard output.
 
 Usage:
 	gofmt [flags] [path ...]
 
 The flags are:
 
+	-d
+		Do not print reformatted sources to standard output.
+		If a file's formatting is different than gofmt's, print diffs
+		to standard output.
 	-l
-		just list files whose formatting differs from gofmt's;
-		generate no other output unless -w is also set.
+		Do not print reformatted sources to standard output.
+		If a file's formatting is different from gofmt's, print its name
+		to standard output.
 	-r rule
-		apply the rewrite rule to the source before reformatting.
+		Apply the rewrite rule to the source before reformatting.
 	-s
-		try to simplify code (after applying the rewrite rule, if any).
+		Try to simplify code (after applying the rewrite rule, if any).
 	-w
-		if set, overwrite each input file with its output.
+		Do not print reformatted sources to standard output.
+		If a file's formatting is different from gofmt's, overwrite it
+		with gofmt's version.
 	-comments=true
-		print comments; if false, all comments are elided from the output.
+		Print comments; if false, all comments are elided from the output.
 	-spaces
-		align with spaces instead of tabs.
+		Align with spaces instead of tabs.
 	-tabindent
-		indent with tabs independent of -spaces.
+		Indent with tabs independent of -spaces.
 	-tabwidth=8
-		tab width in spaces.
+		Tab width in spaces.
 
 The rewrite rule specified with the -r flag must be a string of the form:
 
diff --git a/src/cmd/gofmt/gofmt.go b/src/cmd/gofmt/gofmt.go
index ce274aa..5dd801d 100644
--- a/src/cmd/gofmt/gofmt.go
+++ b/src/cmd/gofmt/gofmt.go
@@ -6,6 +6,7 @@ package main
 
 import (
 	"bytes"
+	"exec"
 	"flag"
 	"fmt"
 	"go/ast"
@@ -28,6 +29,7 @@ var (
 	write       = flag.Bool("w", false, "write result to (source) file instead of stdout")
 	rewriteRule = flag.String("r", "", "rewrite rule (e.g., 'α[β:len(α)] -> α[β:]')")
 	simplifyAST = flag.Bool("s", false, "simplify code")
+	doDiff      = flag.Bool("d", false, "display diffs instead of rewriting files")
 
 	// layout control
 	comments  = flag.Bool("comments", true, "print comments")
@@ -134,9 +136,17 @@ func processFile(filename string, in io.Reader, out io.Writer) os.Error {
 				return err
 			}
 		}
+		if *doDiff {
+			data, err := diff(src, res)
+			if err != nil {
+				return fmt.Errorf("computing diff: %s", err)
+			}
+			fmt.Printf("diff %s gofmt/%s\n", filename, filename)
+			out.Write(data)
+		}
 	}
 
-	if !*list && !*write {
+	if !*list && !*write && !*doDiff {
 		_, err = out.Write(res)
 	}
 
@@ -230,3 +240,37 @@ func gofmtMain() {
 		}
 	}
 }
+
+
+func diff(b1, b2 []byte) (data []byte, err os.Error) {
+	f1, err := ioutil.TempFile("", "gofmt")
+	if err != nil {
+		return nil, err
+	}
+	defer os.Remove(f1.Name())
+	defer f1.Close()
+
+	f2, err := ioutil.TempFile("", "gofmt")
+	if err != nil {
+		return nil, err
+	}
+	defer os.Remove(f2.Name())
+	defer f2.Close()
+
+	f1.Write(b1)
+	f2.Write(b2)
+
+	diffcmd, err := exec.LookPath("diff")
+	if err != nil {
+		return nil, err
+	}
+
+	c, err := exec.Run(diffcmd, []string{"diff", "-u", f1.Name(), f2.Name()},
+		nil, "", exec.DevNull, exec.Pipe, exec.MergeWithStdout)
+	if err != nil {
+		return nil, err
+	}
+	defer c.Close()
+
+	return ioutil.ReadAll(c.Stdout)
+}
diff --git a/src/cmd/gofmt/gofmt_test.go b/src/cmd/gofmt/gofmt_test.go
index 4ec94e2..a725303 100644
--- a/src/cmd/gofmt/gofmt_test.go
+++ b/src/cmd/gofmt/gofmt_test.go
@@ -71,6 +71,7 @@ var tests = []struct {
 	{".", "gofmt_test.go", "gofmt_test.go", ""},
 	{"testdata", "composites.input", "composites.golden", "-s"},
 	{"testdata", "rewrite1.input", "rewrite1.golden", "-r=Foo->Bar"},
+	{"testdata", "rewrite2.input", "rewrite2.golden", "-r=int->bool"},
 }
 
 
diff --git a/src/cmd/gofmt/rewrite.go b/src/cmd/gofmt/rewrite.go
index 93643dc..4c24282 100644
--- a/src/cmd/gofmt/rewrite.go
+++ b/src/cmd/gofmt/rewrite.go
@@ -19,6 +19,7 @@ import (
 
 func initRewrite() {
 	if *rewriteRule == "" {
+		rewrite = nil // disable any previous rewrite
 		return
 	}
 	f := strings.Split(*rewriteRule, "->", -1)
@@ -59,26 +60,34 @@ func dump(msg string, val reflect.Value) {
 // rewriteFile applies the rewrite rule 'pattern -> replace' to an entire file.
 func rewriteFile(pattern, replace ast.Expr, p *ast.File) *ast.File {
 	m := make(map[string]reflect.Value)
-	pat := reflect.NewValue(pattern)
-	repl := reflect.NewValue(replace)
+	pat := reflect.ValueOf(pattern)
+	repl := reflect.ValueOf(replace)
 	var f func(val reflect.Value) reflect.Value // f is recursive
 	f = func(val reflect.Value) reflect.Value {
+		// don't bother if val is invalid to start with
+		if !val.IsValid() {
+			return reflect.Value{}
+		}
 		for k := range m {
 			m[k] = reflect.Value{}, false
 		}
 		val = apply(f, val)
 		if match(m, pat, val) {
-			val = subst(m, repl, reflect.NewValue(val.Interface().(ast.Node).Pos()))
+			val = subst(m, repl, reflect.ValueOf(val.Interface().(ast.Node).Pos()))
 		}
 		return val
 	}
-	return apply(f, reflect.NewValue(p)).Interface().(*ast.File)
+	return apply(f, reflect.ValueOf(p)).Interface().(*ast.File)
 }
 
 
 // setValue is a wrapper for x.SetValue(y); it protects
 // the caller from panics if x cannot be changed to y.
 func setValue(x, y reflect.Value) {
+	// don't bother if y is invalid to start with
+	if !y.IsValid() {
+		return
+	}
 	defer func() {
 		if x := recover(); x != nil {
 			if s, ok := x.(string); ok && strings.HasPrefix(s, "type mismatch") {
@@ -94,11 +103,13 @@ func setValue(x, y reflect.Value) {
 
 // Values/types for special cases.
 var (
-	objectPtrNil = reflect.NewValue((*ast.Object)(nil))
+	objectPtrNil = reflect.ValueOf((*ast.Object)(nil))
+	scopePtrNil  = reflect.ValueOf((*ast.Scope)(nil))
 
-	identType     = reflect.Typeof((*ast.Ident)(nil))
-	objectPtrType = reflect.Typeof((*ast.Object)(nil))
-	positionType  = reflect.Typeof(token.NoPos)
+	identType     = reflect.TypeOf((*ast.Ident)(nil))
+	objectPtrType = reflect.TypeOf((*ast.Object)(nil))
+	positionType  = reflect.TypeOf(token.NoPos)
+	scopePtrType  = reflect.TypeOf((*ast.Scope)(nil))
 )
 
 
@@ -115,6 +126,12 @@ func apply(f func(reflect.Value) reflect.Value, val reflect.Value) reflect.Value
 		return objectPtrNil
 	}
 
+	// similarly for scopes: they are likely incorrect after a rewrite;
+	// replace them with nil
+	if val.Type() == scopePtrType {
+		return scopePtrNil
+	}
+
 	switch v := reflect.Indirect(val); v.Kind() {
 	case reflect.Slice:
 		for i := 0; i < v.Len(); i++ {
@@ -259,21 +276,21 @@ func subst(m map[string]reflect.Value, pattern reflect.Value, pos reflect.Value)
 		return v
 
 	case reflect.Struct:
-		v := reflect.Zero(p.Type())
+		v := reflect.New(p.Type()).Elem()
 		for i := 0; i < p.NumField(); i++ {
 			v.Field(i).Set(subst(m, p.Field(i), pos))
 		}
 		return v
 
 	case reflect.Ptr:
-		v := reflect.Zero(p.Type())
+		v := reflect.New(p.Type()).Elem()
 		if elem := p.Elem(); elem.IsValid() {
 			v.Set(subst(m, elem, pos).Addr())
 		}
 		return v
 
 	case reflect.Interface:
-		v := reflect.Zero(p.Type())
+		v := reflect.New(p.Type()).Elem()
 		if elem := p.Elem(); elem.IsValid() {
 			v.Set(subst(m, elem, pos))
 		}
diff --git a/src/cmd/gofmt/simplify.go b/src/cmd/gofmt/simplify.go
index bcc67c4..40a9f8f 100644
--- a/src/cmd/gofmt/simplify.go
+++ b/src/cmd/gofmt/simplify.go
@@ -26,7 +26,7 @@ func (s *simplifier) Visit(node ast.Node) ast.Visitor {
 		}
 
 		if eltType != nil {
-			typ := reflect.NewValue(eltType)
+			typ := reflect.ValueOf(eltType)
 			for _, x := range outer.Elts {
 				// look at value of indexed/named elements
 				if t, ok := x.(*ast.KeyValueExpr); ok {
@@ -37,7 +37,7 @@ func (s *simplifier) Visit(node ast.Node) ast.Visitor {
 				// matches the outer literal's element type exactly, the inner
 				// literal type may be omitted
 				if inner, ok := x.(*ast.CompositeLit); ok {
-					if match(nil, typ, reflect.NewValue(inner.Type)) {
+					if match(nil, typ, reflect.ValueOf(inner.Type)) {
 						inner.Type = nil
 					}
 				}
diff --git a/src/cmd/gofmt/test.sh b/src/cmd/gofmt/test.sh
index 3340c48..99ec769 100755
--- a/src/cmd/gofmt/test.sh
+++ b/src/cmd/gofmt/test.sh
@@ -36,7 +36,7 @@ apply1() {
 	# the following files are skipped because they are test cases
 	# for syntax errors and thus won't parse in the first place:
 	case `basename "$F"` in
-	func3.go | const2.go | char_lit1.go | \
+	func3.go | const2.go | char_lit1.go | blank1.go | \
 	bug014.go | bug050.go |  bug068.go |  bug083.go | bug088.go | \
 	bug106.go | bug121.go | bug125.go | bug133.go | bug160.go | \
 	bug163.go | bug166.go | bug169.go | bug217.go | bug222.go | \
diff --git a/src/cmd/gofmt/testdata/rewrite1.golden b/src/cmd/gofmt/testdata/rewrite1.golden
index 3f909ff..d9beb37 100644
--- a/src/cmd/gofmt/testdata/rewrite1.golden
+++ b/src/cmd/gofmt/testdata/rewrite1.golden
@@ -1,3 +1,7 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
 package main
 
 type Bar int
diff --git a/src/cmd/gofmt/testdata/rewrite1.input b/src/cmd/gofmt/testdata/rewrite1.input
index 1f10e36..bdb8943 100644
--- a/src/cmd/gofmt/testdata/rewrite1.input
+++ b/src/cmd/gofmt/testdata/rewrite1.input
@@ -1,3 +1,7 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
 package main
 
 type Foo int
diff --git a/src/cmd/gofmt/testdata/rewrite2.golden b/src/cmd/gofmt/testdata/rewrite2.golden
new file mode 100644
index 0000000..64c67ff
--- /dev/null
+++ b/src/cmd/gofmt/testdata/rewrite2.golden
@@ -0,0 +1,10 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+// Slices have nil Len values in the corresponding ast.ArrayType
+// node and reflect.NewValue(slice.Len) is an invalid reflect.Value.
+// The rewriter must not crash in that case. Was issue 1696.
+func f() []bool {}
diff --git a/src/cmd/gofmt/testdata/rewrite2.input b/src/cmd/gofmt/testdata/rewrite2.input
new file mode 100644
index 0000000..2117144
--- /dev/null
+++ b/src/cmd/gofmt/testdata/rewrite2.input
@@ -0,0 +1,10 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+// Slices have nil Len values in the corresponding ast.ArrayType
+// node and reflect.NewValue(slice.Len) is an invalid reflect.Value.
+// The rewriter must not crash in that case. Was issue 1696.
+func f() []int {}
diff --git a/src/cmd/goinstall/Makefile b/src/cmd/goinstall/Makefile
index aaf202e..202797c 100644
--- a/src/cmd/goinstall/Makefile
+++ b/src/cmd/goinstall/Makefile
@@ -10,6 +10,7 @@ GOFILES=\
 	main.go\
 	make.go\
 	parse.go\
+	path.go\
 	syslist.go\
 
 CLEANFILES+=syslist.go
diff --git a/src/cmd/goinstall/download.go b/src/cmd/goinstall/download.go
index 88befc0..7dad596 100644
--- a/src/cmd/goinstall/download.go
+++ b/src/cmd/goinstall/download.go
@@ -37,15 +37,15 @@ var bitbucket = regexp.MustCompile(`^(bitbucket\.org/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z
 var launchpad = regexp.MustCompile(`^(launchpad\.net/([a-z0-9A-Z_.\-]+(/[a-z0-9A-Z_.\-]+)?|~[a-z0-9A-Z_.\-]+/(\+junk|[a-z0-9A-Z_.\-]+)/[a-z0-9A-Z_.\-]+))(/[a-z0-9A-Z_.\-/]+)?$`)
 
 // download checks out or updates pkg from the remote server.
-func download(pkg string) (string, os.Error) {
+func download(pkg, srcDir string) os.Error {
 	if strings.Contains(pkg, "..") {
-		return "", os.ErrorString("invalid path (contains ..)")
+		return os.ErrorString("invalid path (contains ..)")
 	}
 	if m := bitbucket.FindStringSubmatch(pkg); m != nil {
-		if err := vcsCheckout(&hg, m[1], "http://"+m[1], m[1]); err != nil {
-			return "", err
+		if err := vcsCheckout(&hg, srcDir, m[1], "http://"+m[1], m[1]); err != nil {
+			return err
 		}
-		return root + pkg, nil
+		return nil
 	}
 	if m := googlecode.FindStringSubmatch(pkg); m != nil {
 		var v *vcs
@@ -58,29 +58,29 @@ func download(pkg string) (string, os.Error) {
 			// regexp only allows hg, svn to get through
 			panic("missing case in download: " + pkg)
 		}
-		if err := vcsCheckout(v, m[1], "https://"+m[1], m[1]); err != nil {
-			return "", err
+		if err := vcsCheckout(v, srcDir, m[1], "https://"+m[1], m[1]); err != nil {
+			return err
 		}
-		return root + pkg, nil
+		return nil
 	}
 	if m := github.FindStringSubmatch(pkg); m != nil {
 		if strings.HasSuffix(m[1], ".git") {
-			return "", os.ErrorString("repository " + pkg + " should not have .git suffix")
+			return os.ErrorString("repository " + pkg + " should not have .git suffix")
 		}
-		if err := vcsCheckout(&git, m[1], "http://"+m[1]+".git", m[1]); err != nil {
-			return "", err
+		if err := vcsCheckout(&git, srcDir, m[1], "http://"+m[1]+".git", m[1]); err != nil {
+			return err
 		}
-		return root + pkg, nil
+		return nil
 	}
 	if m := launchpad.FindStringSubmatch(pkg); m != nil {
 		// Either lp.net/<project>[/<series>[/<path>]]
 		//	 or lp.net/~<user or team>/<project>/<branch>[/<path>]
-		if err := vcsCheckout(&bzr, m[1], "https://"+m[1], m[1]); err != nil {
-			return "", err
+		if err := vcsCheckout(&bzr, srcDir, m[1], "https://"+m[1], m[1]); err != nil {
+			return err
 		}
-		return root + pkg, nil
+		return nil
 	}
-	return "", os.ErrorString("unknown repository: " + pkg)
+	return os.ErrorString("unknown repository: " + pkg)
 }
 
 // a vcs represents a version control system
@@ -172,8 +172,8 @@ func (v *vcs) updateRepo(dst string) os.Error {
 // exists and -u was specified on the command line)
 // the repository at tag/branch "release".  If there is no
 // such tag or branch, it falls back to the repository tip.
-func vcsCheckout(vcs *vcs, pkgprefix, repo, dashpath string) os.Error {
-	dst := filepath.Join(root, filepath.FromSlash(pkgprefix))
+func vcsCheckout(vcs *vcs, srcDir, pkgprefix, repo, dashpath string) os.Error {
+	dst := filepath.Join(srcDir, filepath.FromSlash(pkgprefix))
 	dir, err := os.Stat(filepath.Join(dst, vcs.metadir))
 	if err == nil && !dir.IsDirectory() {
 		return os.ErrorString("not a directory: " + dst)
diff --git a/src/cmd/goinstall/main.go b/src/cmd/goinstall/main.go
index 8fec8e3..6cd9290 100644
--- a/src/cmd/goinstall/main.go
+++ b/src/cmd/goinstall/main.go
@@ -150,6 +150,7 @@ func install(pkg, parent string) {
 	// Check whether package is local or remote.
 	// If remote, download or update it.
 	var dir string
+	proot := gopath[0] // default to GOROOT
 	local := false
 	if strings.HasPrefix(pkg, "http://") {
 		fmt.Fprintf(os.Stderr, "%s: %s: 'http://' used in remote path, try '%s'\n", argv0, pkg, pkg[7:])
@@ -163,8 +164,9 @@ func install(pkg, parent string) {
 		dir = filepath.Join(root, filepath.FromSlash(pkg))
 		local = true
 	} else {
-		var err os.Error
-		dir, err = download(pkg)
+		proot = findPkgroot(pkg)
+		err := download(pkg, proot.srcDir())
+		dir = filepath.Join(proot.srcDir(), pkg)
 		if err != nil {
 			fmt.Fprintf(os.Stderr, "%s: %s: %s\n", argv0, pkg, err)
 			errors = true
@@ -192,18 +194,11 @@ func install(pkg, parent string) {
 			install(p, pkg)
 		}
 	}
-	if dirInfo.pkgName == "main" {
-		if !errors {
-			fmt.Fprintf(os.Stderr, "%s: %s's dependencies are installed.\n", argv0, pkg)
-		}
-		errors = true
-		visit[pkg] = done
-		return
-	}
 
 	// Install this package.
 	if !errors {
-		if err := domake(dir, pkg, local); err != nil {
+		isCmd := dirInfo.pkgName == "main"
+		if err := domake(dir, pkg, proot, local, isCmd); err != nil {
 			fmt.Fprintf(os.Stderr, "%s: installing %s: %s\n", argv0, pkg, err)
 			errors = true
 		} else if !local && *logPkgs {
diff --git a/src/cmd/goinstall/make.go b/src/cmd/goinstall/make.go
index ceb119e..b2ca82b 100644
--- a/src/cmd/goinstall/make.go
+++ b/src/cmd/goinstall/make.go
@@ -9,6 +9,7 @@ package main
 import (
 	"bytes"
 	"os"
+	"path/filepath"
 	"template"
 )
 
@@ -17,7 +18,7 @@ import (
 // For non-local packages or packages without Makefiles,
 // domake generates a standard Makefile and passes it
 // to make on standard input.
-func domake(dir, pkg string, local bool) (err os.Error) {
+func domake(dir, pkg string, root *pkgroot, local, isCmd bool) (err os.Error) {
 	needMakefile := true
 	if local {
 		_, err := os.Stat(dir + "/Makefile")
@@ -28,7 +29,7 @@ func domake(dir, pkg string, local bool) (err os.Error) {
 	cmd := []string{"gomake"}
 	var makefile []byte
 	if needMakefile {
-		if makefile, err = makeMakefile(dir, pkg); err != nil {
+		if makefile, err = makeMakefile(dir, pkg, root, isCmd); err != nil {
 			return err
 		}
 		cmd = append(cmd, "-f-")
@@ -43,11 +44,26 @@ func domake(dir, pkg string, local bool) (err os.Error) {
 // makeMakefile computes the standard Makefile for the directory dir
 // installing as package pkg.  It includes all *.go files in the directory
 // except those in package main and those ending in _test.go.
-func makeMakefile(dir, pkg string) ([]byte, os.Error) {
+func makeMakefile(dir, pkg string, root *pkgroot, isCmd bool) ([]byte, os.Error) {
 	if !safeName(pkg) {
 		return nil, os.ErrorString("unsafe name: " + pkg)
 	}
-	dirInfo, err := scanDir(dir, false)
+	targ := pkg
+	targDir := root.pkgDir()
+	if isCmd {
+		// use the last part of the package name only
+		_, targ = filepath.Split(pkg)
+		// if building the working dir use the directory name
+		if targ == "." {
+			d, err := filepath.Abs(dir)
+			if err != nil {
+				return nil, os.NewError("finding path: " + err.String())
+			}
+			_, targ = filepath.Split(d)
+		}
+		targDir = root.binDir()
+	}
+	dirInfo, err := scanDir(dir, isCmd)
 	if err != nil {
 		return nil, err
 	}
@@ -94,7 +110,10 @@ func makeMakefile(dir, pkg string) ([]byte, os.Error) {
 	}
 
 	var buf bytes.Buffer
-	md := makedata{pkg, goFiles, oFiles, cgoFiles, cgoOFiles}
+	md := makedata{targ, targDir, "pkg", goFiles, oFiles, cgoFiles, cgoOFiles, imports}
+	if isCmd {
+		md.Type = "cmd"
+	}
 	if err := makefileTemplate.Execute(&buf, &md); err != nil {
 		return nil, err
 	}
@@ -104,6 +123,9 @@ func makeMakefile(dir, pkg string) ([]byte, os.Error) {
 var safeBytes = []byte("+-./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz")
 
 func safeName(s string) bool {
+	if s == "" {
+		return false
+	}
 	for i := 0; i < len(s); i++ {
 		if c := s[i]; c < 0x80 && bytes.IndexByte(safeBytes, c) < 0 {
 			return false
@@ -114,17 +136,21 @@ func safeName(s string) bool {
 
 // makedata is the data type for the makefileTemplate.
 type makedata struct {
-	Pkg       string   // package import path
+	Targ      string   // build target
+	TargDir   string   // build target directory
+	Type      string   // build type: "pkg" or "cmd"
 	GoFiles   []string // list of non-cgo .go files
 	OFiles    []string // list of .$O files
 	CgoFiles  []string // list of cgo .go files
 	CgoOFiles []string // list of cgo .o files, without extension
+	Imports   []string // gc/ld import paths
 }
 
 var makefileTemplate = template.MustParse(`
 include $(GOROOT)/src/Make.inc
 
-TARG={Pkg}
+TARG={Targ}
+TARGDIR={TargDir}
 
 {.section GoFiles}
 GOFILES=\
@@ -154,6 +180,9 @@ CGO_OFILES=\
 {.end}
 
 {.end}
-include $(GOROOT)/src/Make.pkg
+GCIMPORTS={.repeated section Imports}-I "{@}" {.end}
+LDIMPORTS={.repeated section Imports}-L "{@}" {.end}
+
+include $(GOROOT)/src/Make.{Type}
 `,
 	nil)
diff --git a/src/cmd/goinstall/parse.go b/src/cmd/goinstall/parse.go
index 0e61790..a4bb761 100644
--- a/src/cmd/goinstall/parse.go
+++ b/src/cmd/goinstall/parse.go
@@ -88,6 +88,9 @@ func scanDir(dir string, allowMain bool) (info *dirInfo, err os.Error) {
 		if s == "main" && !allowMain {
 			continue
 		}
+		if s == "documentation" {
+			continue
+		}
 		if pkgName == "" {
 			pkgName = s
 		} else if pkgName != s {
diff --git a/src/cmd/goinstall/path.go b/src/cmd/goinstall/path.go
new file mode 100644
index 0000000..1153e04
--- /dev/null
+++ b/src/cmd/goinstall/path.go
@@ -0,0 +1,117 @@
+// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"log"
+	"os"
+	"path/filepath"
+	"runtime"
+)
+
+var (
+	gopath      []*pkgroot
+	imports     []string
+	defaultRoot *pkgroot // default root for remote packages
+)
+
+// set up gopath: parse and validate GOROOT and GOPATH variables
+func init() {
+	p, err := newPkgroot(root)
+	if err != nil {
+		log.Fatalf("Invalid GOROOT %q: %v", root, err)
+	}
+	p.goroot = true
+	gopath = []*pkgroot{p}
+
+	for _, p := range filepath.SplitList(os.Getenv("GOPATH")) {
+		if p == "" {
+			continue
+		}
+		r, err := newPkgroot(p)
+		if err != nil {
+			log.Printf("Invalid GOPATH %q: %v", p, err)
+			continue
+		}
+		gopath = append(gopath, r)
+		imports = append(imports, r.pkgDir())
+
+		// select first GOPATH entry as default
+		if defaultRoot == nil {
+			defaultRoot = r
+		}
+	}
+
+	// use GOROOT if no valid GOPATH specified
+	if defaultRoot == nil {
+		defaultRoot = gopath[0]
+	}
+}
+
+type pkgroot struct {
+	path   string
+	goroot bool // TODO(adg): remove this once Go tree re-organized
+}
+
+func newPkgroot(p string) (*pkgroot, os.Error) {
+	if !filepath.IsAbs(p) {
+		return nil, os.NewError("must be absolute")
+	}
+	ep, err := filepath.EvalSymlinks(p)
+	if err != nil {
+		return nil, err
+	}
+	return &pkgroot{path: ep}, nil
+}
+
+func (r *pkgroot) srcDir() string {
+	if r.goroot {
+		return filepath.Join(r.path, "src", "pkg")
+	}
+	return filepath.Join(r.path, "src")
+}
+
+func (r *pkgroot) pkgDir() string {
+	goos, goarch := runtime.GOOS, runtime.GOARCH
+	if e := os.Getenv("GOOS"); e != "" {
+		goos = e
+	}
+	if e := os.Getenv("GOARCH"); e != "" {
+		goarch = e
+	}
+	return filepath.Join(r.path, "pkg", goos+"_"+goarch)
+}
+
+func (r *pkgroot) binDir() string {
+	return filepath.Join(r.path, "bin")
+}
+
+func (r *pkgroot) hasSrcDir(name string) bool {
+	fi, err := os.Stat(filepath.Join(r.srcDir(), name))
+	if err != nil {
+		return false
+	}
+	return fi.IsDirectory()
+}
+
+func (r *pkgroot) hasPkg(name string) bool {
+	fi, err := os.Stat(filepath.Join(r.pkgDir(), name+".a"))
+	if err != nil {
+		return false
+	}
+	return fi.IsRegular()
+	// TODO(adg): check object version is consistent
+}
+
+// findPkgroot searches each of the gopath roots
+// for the source code for the given import path.
+func findPkgroot(importPath string) *pkgroot {
+	for _, r := range gopath {
+		if r.hasSrcDir(importPath) {
+			return r
+		}
+	}
+	return defaultRoot
+}
diff --git a/src/cmd/gopack/ar.c b/src/cmd/gopack/ar.c
index dc3899f..017978c 100644
--- a/src/cmd/gopack/ar.c
+++ b/src/cmd/gopack/ar.c
@@ -144,6 +144,7 @@ char	*file;				/* current file or member being worked on */
 Biobuf	bout;
 Biobuf bar;
 char	*prefix;
+int	pkgdefsafe;		/* was __.PKGDEF marked safe? */
 
 void	arcopy(Biobuf*, Arfile*, Armember*);
 int	arcreate(char*);
@@ -177,6 +178,7 @@ void	scanpkg(Biobuf*, long);
 void	select(int*, long);
 void	setcom(void(*)(char*, int, char**));
 void	skip(Biobuf*, vlong);
+void	checksafe(Biobuf*, vlong);
 int	symcomp(void*, void*);
 void	trim(char*, char*, int);
 void	usage(void);
@@ -322,9 +324,9 @@ rcmd(char *arname, int count, char **files)
 			skip(&bar, bp->size);
 			continue;
 		}
-			/* pitch pkgdef file */
+			/* pitch pkgdef file but remember whether it was marked safe */
 		if (gflag && strcmp(file, pkgdef) == 0) {
-			skip(&bar, bp->size);
+			checksafe(&bar, bp->size);
 			continue;
 		}
 		/*
@@ -773,7 +775,8 @@ scanpkg(Biobuf *b, long size)
 		goto foundstart;
 	}
 	// fprint(2, "gopack: warning: no package import section in %s\n", file);
-	safe = 0;	// non-Go file (C or assembly)
+	if(b != &bar || !pkgdefsafe)
+		safe = 0;	// non-Go file (C or assembly)
 	return;
 
 foundstart:
@@ -807,7 +810,7 @@ foundstart:
 			pkgname = armalloc(pkg - data + 1);
 			memmove(pkgname, data, pkg - data);
 			pkgname[pkg-data] = '\0';
-			if(strcmp(pkg, " safe\n") != 0)
+			if(strcmp(pkg, " safe\n") != 0 && (b != &bar || !pkgdefsafe))
 				safe = 0;
 			start = Boffset(b);  // after package statement
 			first = 0;
@@ -1094,6 +1097,36 @@ skip(Biobuf *bp, vlong len)
 	Bseek(bp, len, 1);
 }
 
+void
+checksafe(Biobuf *bp, vlong len)
+{
+	char *p;
+	vlong end;
+
+	if (len & 01)
+		len++;
+	end = Boffset(bp) + len;
+
+	p = Brdline(bp, '\n');
+	if(p == nil || strncmp(p, "go object ", 10) != 0)
+		goto done;
+	for(;;) {
+		p = Brdline(bp, '\n');
+		if(p == nil || Boffset(bp) >= end)
+			goto done;
+		if(strncmp(p, "$$\n", 3) == 0)
+			break;
+	}
+	p = Brdline(bp, '\n');
+	if(p == nil || Boffset(bp) > end)
+		goto done;
+	if(Blinelen(bp) > 8+6 && strncmp(p, "package ", 8) == 0 && strncmp(p+Blinelen(bp)-6, " safe\n", 6) == 0)
+		pkgdefsafe = 1;
+
+done:
+	Bseek(bp, end, 0);
+}
+
 /*
  *	Stream the three temp files to an archive
  */
@@ -1676,6 +1709,10 @@ arread_cutprefix(Biobuf *b, Armember *bp)
 					offset = o;
 				}
 			}
+		} else {
+			// didn't find the whole prefix.
+			// give up and let it emit the entire name.
+			inprefix = nil;
 		}
 
 		// copy instructions
diff --git a/src/cmd/gotest/gotest.go b/src/cmd/gotest/gotest.go
index 138216e..a7ba8dd 100644
--- a/src/cmd/gotest/gotest.go
+++ b/src/cmd/gotest/gotest.go
@@ -16,6 +16,7 @@ import (
 	"path/filepath"
 	"runtime"
 	"strings"
+	"time"
 	"unicode"
 	"utf8"
 )
@@ -51,6 +52,13 @@ var (
 	xFlag bool
 )
 
+// elapsed returns  time elapsed since gotest started.
+func elapsed() float64 {
+	return float64(time.Nanoseconds()-start) / 1e9
+}
+
+var start = time.Nanoseconds()
+
 // File represents a file that contains tests.
 type File struct {
 	name       string
@@ -80,6 +88,9 @@ func main() {
 	if !cFlag {
 		runTestWithArgs("./" + O + ".out")
 	}
+	if xFlag {
+		fmt.Printf("gotest %.2fs: done\n", elapsed())
+	}
 }
 
 // needMakefile tests that we have a Makefile in this directory.
@@ -119,7 +130,10 @@ func setEnvironment() {
 	// Basic environment.
 	GOROOT = runtime.GOROOT()
 	addEnv("GOROOT", GOROOT)
-	GOARCH = runtime.GOARCH
+	GOARCH = os.Getenv("GOARCH")
+	if GOARCH == "" {
+		GOARCH = runtime.GOARCH
+	}
 	addEnv("GOARCH", GOARCH)
 	O = theChar[GOARCH]
 	if O == "" {
@@ -254,7 +268,12 @@ func runTestWithArgs(binary string) {
 // retrieve standard output.
 func doRun(argv []string, returnStdout bool) string {
 	if xFlag {
-		fmt.Printf("gotest: %s\n", strings.Join(argv, " "))
+		fmt.Printf("gotest %.2fs: %s\n", elapsed(), strings.Join(argv, " "))
+		t := -time.Nanoseconds()
+		defer func() {
+			t += time.Nanoseconds()
+			fmt.Printf(" [+%.2fs]\n", float64(t)/1e9)
+		}()
 	}
 	command := argv[0]
 	if runtime.GOOS == "windows" && command == "gomake" {
@@ -266,7 +285,7 @@ func doRun(argv []string, returnStdout bool) string {
 			}
 			cmd += `"` + v + `"`
 		}
-		argv = []string{"cmd", "/c", "sh", "-c", cmd}
+		argv = []string{"sh", "-c", cmd}
 	}
 	var err os.Error
 	argv[0], err = exec.LookPath(argv[0])
@@ -359,7 +378,7 @@ func writeTestmainGo() {
 		fmt.Fprintf(b, "import %q\n", "./_xtest_")
 	}
 	fmt.Fprintf(b, "import %q\n", "testing")
-	fmt.Fprintf(b, "import __os__     %q\n", "os")     // rename in case tested package is called os
+	fmt.Fprintf(b, "import __os__ %q\n", "os")         // rename in case tested package is called os
 	fmt.Fprintf(b, "import __regexp__ %q\n", "regexp") // rename in case tested package is called regexp
 	fmt.Fprintln(b)                                    // for gofmt
 
@@ -374,7 +393,7 @@ func writeTestmainGo() {
 	fmt.Fprintln(b)
 
 	// Benchmarks.
-	fmt.Fprintln(b, "var benchmarks = []testing.InternalBenchmark{")
+	fmt.Fprintf(b, "var benchmarks = []testing.InternalBenchmark{")
 	for _, f := range files {
 		for _, bm := range f.benchmarks {
 			fmt.Fprintf(b, "\t{\"%s.%s\", %s.%s},\n", f.pkg, bm, notMain(f.pkg), bm)
diff --git a/src/cmd/ld/data.c b/src/cmd/ld/data.c
index d27416d..0cb2b21 100644
--- a/src/cmd/ld/data.c
+++ b/src/cmd/ld/data.c
@@ -312,7 +312,7 @@ symgrow(Sym *s, int32 siz)
 }
 
 void
-savedata(Sym *s, Prog *p)
+savedata(Sym *s, Prog *p, char *pn)
 {
 	int32 off, siz, i, fl;
 	uchar *cast;
@@ -321,8 +321,10 @@ savedata(Sym *s, Prog *p)
 
 	off = p->from.offset;
 	siz = p->datasize;
+	if(off < 0 || siz < 0 || off >= 1<<30 || siz >= 100)
+		mangle(pn);
 	symgrow(s, off+siz);
-	
+
 	switch(p->to.type) {
 	default:
 		diag("bad data: %P", p);
@@ -876,7 +878,7 @@ textaddress(void)
 void
 address(void)
 {
-	Section *s, *text, *data, *rodata, *bss;
+	Section *s, *text, *data, *rodata;
 	Sym *sym, *sub;
 	uvlong va;
 
@@ -911,7 +913,6 @@ address(void)
 	text = segtext.sect;
 	rodata = segtext.sect->next;
 	data = segdata.sect;
-	bss = segdata.sect->next;
 
 	for(sym = datap; sym != nil; sym = sym->next) {
 		cursym = sym;
diff --git a/src/cmd/ld/dwarf.c b/src/cmd/ld/dwarf.c
index fa55fcb..98b0680 100644
--- a/src/cmd/ld/dwarf.c
+++ b/src/cmd/ld/dwarf.c
@@ -1376,20 +1376,18 @@ synthesizemaptypes(DWDie *die)
 static void
 synthesizechantypes(DWDie *die)
 {
-	DWDie *sudog, *waitq, *link, *hchan,
+	DWDie *sudog, *waitq, *hchan,
 		*dws, *dww, *dwh, *elemtype;
 	DWAttr *a;
-	int elemsize, linksize, sudogsize;
+	int elemsize, sudogsize;
 
 	sudog = defgotype(lookup_or_diag("type.runtime.sudog"));
 	waitq = defgotype(lookup_or_diag("type.runtime.waitq"));
-	link  = defgotype(lookup_or_diag("type.runtime.link"));
 	hchan = defgotype(lookup_or_diag("type.runtime.hchan"));
-	if (sudog == nil || waitq == nil || link == nil || hchan == nil)
+	if (sudog == nil || waitq == nil || hchan == nil)
 		return;
 
 	sudogsize = getattr(sudog, DW_AT_byte_size)->value;
-	linksize = getattr(link, DW_AT_byte_size)->value;
 
 	for (; die != nil; die = die->link) {
 		if (die->abbrev != DW_ABRV_CHANTYPE)
@@ -1422,7 +1420,7 @@ synthesizechantypes(DWDie *die)
 		copychildren(dwh, hchan);
 		substitutetype(dwh, "recvq", dww);
 		substitutetype(dwh, "sendq", dww);
-		substitutetype(dwh, "free", dws);
+		substitutetype(dwh, "free", defptrto(dws));
 		newattr(dwh, DW_AT_byte_size, DW_CLS_CONSTANT,
 			getattr(hchan, DW_AT_byte_size)->value, NULL);
 
@@ -2569,12 +2567,8 @@ dwarfaddpeheaders(void)
 	newPEDWARFSection(".debug_line", linesize);
 	newPEDWARFSection(".debug_frame", framesize);
 	newPEDWARFSection(".debug_info", infosize);
-	if (pubnamessize > 0)
-		newPEDWARFSection(".debug_pubnames", pubnamessize);
-	if (pubtypessize > 0)
-		newPEDWARFSection(".debug_pubtypes", pubtypessize);
-	if (arangessize > 0)
-		newPEDWARFSection(".debug_aranges", arangessize);
-	if (gdbscriptsize > 0)
-		newPEDWARFSection(".debug_gdb_scripts", gdbscriptsize);
+	newPEDWARFSection(".debug_pubnames", pubnamessize);
+	newPEDWARFSection(".debug_pubtypes", pubtypessize);
+	newPEDWARFSection(".debug_aranges", arangessize);
+	newPEDWARFSection(".debug_gdb_scripts", gdbscriptsize);
 }
diff --git a/src/cmd/ld/elf.c b/src/cmd/ld/elf.c
index b0cce49..fc917b2 100644
--- a/src/cmd/ld/elf.c
+++ b/src/cmd/ld/elf.c
@@ -331,17 +331,62 @@ elfinterp(ElfShdr *sh, uint64 startva, char *p)
 }
 
 extern int nelfsym;
+int elfverneed;
+
+typedef struct Elfaux Elfaux;
+typedef struct Elflib Elflib;
+
+struct Elflib
+{
+	Elflib *next;
+	Elfaux *aux;
+	char *file;
+};
+
+struct Elfaux
+{
+	Elfaux *next;
+	int num;
+	char *vers;
+};
+
+Elfaux*
+addelflib(Elflib **list, char *file, char *vers)
+{
+	Elflib *lib;
+	Elfaux *aux;
+	
+	for(lib=*list; lib; lib=lib->next)
+		if(strcmp(lib->file, file) == 0)
+			goto havelib;
+	lib = mal(sizeof *lib);
+	lib->next = *list;
+	lib->file = file;
+	*list = lib;
+havelib:
+	for(aux=lib->aux; aux; aux=aux->next)
+		if(strcmp(aux->vers, vers) == 0)
+			goto haveaux;
+	aux = mal(sizeof *aux);
+	aux->next = lib->aux;
+	aux->vers = vers;
+	lib->aux = aux;
+haveaux:
+	return aux;
+}
 
 void
 elfdynhash(void)
 {
-	Sym *s, *sy;
-	int i, nbucket, b;
-	uchar *pc;
-	uint32 hc, g;
-	uint32 *chain, *buckets;
+	Sym *s, *sy, *dynstr;
+	int i, j, nbucket, b, nfile;
+	uint32 hc, *chain, *buckets;
 	int nsym;
 	char *name;
+	Elfaux **need;
+	Elflib *needlib;
+	Elflib *l;
+	Elfaux *x;
 	
 	if(!iself)
 		return;
@@ -358,29 +403,29 @@ elfdynhash(void)
 		i >>= 1;
 	}
 
-	chain = malloc(nsym * sizeof(uint32));
-	buckets = malloc(nbucket * sizeof(uint32));
-	if(chain == nil || buckets == nil) {
+	needlib = nil;
+	need = malloc(nsym * sizeof need[0]);
+	chain = malloc(nsym * sizeof chain[0]);
+	buckets = malloc(nbucket * sizeof buckets[0]);
+	if(need == nil || chain == nil || buckets == nil) {
 		cursym = nil;
 		diag("out of memory");
 		errorexit();
 	}
-	memset(chain, 0, nsym * sizeof(uint32));
-	memset(buckets, 0, nbucket * sizeof(uint32));
+	memset(need, 0, nsym * sizeof need[0]);
+	memset(chain, 0, nsym * sizeof chain[0]);
+	memset(buckets, 0, nbucket * sizeof buckets[0]);
 	for(sy=allsym; sy!=S; sy=sy->allsym) {
 		if (sy->dynid <= 0)
 			continue;
 
-		hc = 0;
+		if(sy->dynimpvers)
+			need[sy->dynid] = addelflib(&needlib, sy->dynimplib, sy->dynimpvers);
+
 		name = sy->dynimpname;
 		if(name == nil)
 			name = sy->name;
-		for(pc = (uchar*)name; *pc; pc++) {
-			hc = (hc<<4) + *pc;
-			g = hc & 0xf0000000;
-			hc ^= g >> 24;
-			hc &= ~g;
-		}
+		hc = elfhash((uchar*)name);
 
 		b = hc % nbucket;
 		chain[sy->dynid] = buckets[b];
@@ -396,8 +441,62 @@ elfdynhash(void)
 
 	free(chain);
 	free(buckets);
+	
+	// version symbols
+	dynstr = lookup(".dynstr", 0);
+	s = lookup(".gnu.version_r", 0);
+	i = 2;
+	nfile = 0;
+	for(l=needlib; l; l=l->next) {
+		nfile++;
+		// header
+		adduint16(s, 1);  // table version
+		j = 0;
+		for(x=l->aux; x; x=x->next)
+			j++;
+		adduint16(s, j);	// aux count
+		adduint32(s, addstring(dynstr, l->file));  // file string offset
+		adduint32(s, 16);  // offset from header to first aux
+		if(l->next)
+			adduint32(s, 16+j*16);  // offset from this header to next
+		else
+			adduint32(s, 0);
+		
+		for(x=l->aux; x; x=x->next) {
+			x->num = i++;
+			// aux struct
+			adduint32(s, elfhash((uchar*)x->vers));  // hash
+			adduint16(s, 0);  // flags
+			adduint16(s, x->num);  // other - index we refer to this by
+			adduint32(s, addstring(dynstr, x->vers));  // version string offset
+			if(x->next)
+				adduint32(s, 16);  // offset from this aux to next
+			else
+				adduint32(s, 0);
+		}
+	}
+
+	// version references
+	s = lookup(".gnu.version", 0);
+	for(i=0; i<nsym; i++) {
+		if(i == 0)
+			adduint16(s, 0); // first entry - no symbol
+		else if(need[i] == nil)
+			adduint16(s, 1); // global
+		else
+			adduint16(s, need[i]->num);
+	}
 
-	elfwritedynent(lookup(".dynamic", 0), DT_NULL, 0);
+	free(need);
+
+	s = lookup(".dynamic", 0);
+	elfverneed = nfile;
+	if(elfverneed) {
+		elfwritedynentsym(s, DT_VERNEED, lookup(".gnu.version_r", 0));
+		elfwritedynent(s, DT_VERNEEDNUM, nfile);
+		elfwritedynentsym(s, DT_VERSYM, lookup(".gnu.version", 0));
+	}
+	elfwritedynent(s, DT_NULL, 0);
 }
 
 ElfPhdr*
diff --git a/src/cmd/ld/elf.h b/src/cmd/ld/elf.h
index b27ae67..08583cc 100644
--- a/src/cmd/ld/elf.h
+++ b/src/cmd/ld/elf.h
@@ -216,6 +216,9 @@ typedef struct {
 #define SHT_SYMTAB_SHNDX	18	/* Section indexes (see SHN_XINDEX). */
 #define SHT_LOOS	0x60000000	/* First of OS specific semantics */
 #define SHT_HIOS	0x6fffffff	/* Last of OS specific semantics */
+#define SHT_GNU_VERDEF	0x6ffffffd
+#define SHT_GNU_VERNEED	0x6ffffffe
+#define SHT_GNU_VERSYM	0x6fffffff
 #define SHT_LOPROC	0x70000000	/* reserved range for processor */
 #define SHT_HIPROC	0x7fffffff	/* specific section header types */
 #define SHT_LOUSER	0x80000000	/* reserved range for application */
@@ -311,6 +314,10 @@ typedef struct {
 #define	DT_LOPROC	0x70000000	/* First processor-specific type. */
 #define	DT_HIPROC	0x7fffffff	/* Last processor-specific type. */
 
+#define	DT_VERNEED	0x6ffffffe
+#define	DT_VERNEEDNUM	0x6fffffff
+#define	DT_VERSYM	0x6ffffff0
+
 /* Values for DT_FLAGS */
 #define	DF_ORIGIN	0x0001	/* Indicates that the object being loaded may
 				   make reference to the $ORIGIN substitution
@@ -962,12 +969,14 @@ uint64	endelf(void);
 extern	int	numelfphdr;
 extern	int	numelfshdr;
 extern	int	iself;
+extern	int	elfverneed;
 int	elfwriteinterp(void);
 void	elfinterp(ElfShdr*, uint64, char*);
 void	elfdynhash(void);
 ElfPhdr* elfphload(Segment*);
 ElfShdr* elfshbits(Section*);
 void	elfsetstring(char*, int);
+void	elfaddverneed(Sym*);
 
 /*
  * Total amount of space to reserve at the start of the file
diff --git a/src/cmd/ld/go.c b/src/cmd/ld/go.c
index 055163d..e52c5cb 100644
--- a/src/cmd/ld/go.c
+++ b/src/cmd/ld/go.c
@@ -412,7 +412,7 @@ parsemethod(char **pp, char *ep, char **methp)
 static void
 loaddynimport(char *file, char *pkg, char *p, int n)
 {
-	char *pend, *next, *name, *def, *p0, *lib;
+	char *pend, *next, *name, *def, *p0, *lib, *q;
 	Sym *s;
 
 	pend = p + n;
@@ -445,6 +445,12 @@ loaddynimport(char *file, char *pkg, char *p, int n)
 		*strchr(name, ' ') = 0;
 		*strchr(def, ' ') = 0;
 		
+		if(debug['d']) {
+			fprint(2, "%s: %s: cannot use dynamic imports with -d flag\n", argv0, file);
+			nerrors++;
+			return;
+		}
+		
 		if(strcmp(name, "_") == 0 && strcmp(def, "_") == 0) {
 			// allow #pragma dynimport _ _ "foo.so"
 			// to force a link of foo.so.
@@ -453,17 +459,21 @@ loaddynimport(char *file, char *pkg, char *p, int n)
 		}
 
 		name = expandpkg(name, pkg);
+		q = strchr(def, '@');
+		if(q)
+			*q++ = '\0';
 		s = lookup(name, 0);
 		if(s->type == 0 || s->type == SXREF) {
 			s->dynimplib = lib;
 			s->dynimpname = def;
+			s->dynimpvers = q;
 			s->type = SDYNIMPORT;
 		}
 	}
 	return;
 
 err:
-	fprint(2, "%s: invalid dynimport line: %s\n", argv0, p0);
+	fprint(2, "%s: %s: invalid dynimport line: %s\n", argv0, file, p0);
 	nerrors++;
 }
 
diff --git a/src/cmd/ld/ldelf.c b/src/cmd/ld/ldelf.c
index 44bbe68..d61020e 100644
--- a/src/cmd/ld/ldelf.c
+++ b/src/cmd/ld/ldelf.c
@@ -319,7 +319,7 @@ ldelf(Biobuf *f, char *pkg, int64 len, char *pn)
 	char *name;
 	int i, j, rela, is64, n;
 	uchar hdrbuf[64];
-	uchar *p, *dp;
+	uchar *p;
 	ElfHdrBytes *hdr;
 	ElfObj *obj;
 	ElfSect *sect, *rsect;
@@ -561,7 +561,6 @@ ldelf(Biobuf *f, char *pkg, int64 len, char *pn)
 		n = rsect->size/(4+4*is64)/(2+rela);
 		r = mal(n*sizeof r[0]);
 		p = rsect->base;
-		dp = sect->base;
 		for(j=0; j<n; j++) {
 			add = 0;
 			rp = &r[j];
diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c
index 8cd5704..15219ba 100644
--- a/src/cmd/ld/lib.c
+++ b/src/cmd/ld/lib.c
@@ -438,7 +438,7 @@ ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence)
 		return;
 	}
 	t = smprint("%s %s %s", getgoos(), thestring, getgoversion());
-	if(strcmp(line+10, t) != 0) {
+	if(strcmp(line+10, t) != 0 && !debug['f']) {
 		diag("%s: object is [%s] expected [%s]", pn, line+10, t);
 		free(t);
 		return;
@@ -1033,7 +1033,7 @@ mkfwd(void)
 	Prog *p;
 	int i;
 	int32 dwn[LOG], cnt[LOG];
-	Prog *lst[LOG], *last;
+	Prog *lst[LOG];
 
 	for(i=0; i<LOG; i++) {
 		if(i == 0)
@@ -1044,7 +1044,6 @@ mkfwd(void)
 		lst[i] = P;
 	}
 	i = 0;
-	last = nil;
 	for(cursym = textp; cursym != nil; cursym = cursym->next) {
 		for(p = cursym->text; p != P; p = p->link) {
 			if(p->link == P) {
diff --git a/src/cmd/ld/lib.h b/src/cmd/ld/lib.h
index 646aeb5..8b603a0 100644
--- a/src/cmd/ld/lib.h
+++ b/src/cmd/ld/lib.h
@@ -173,7 +173,7 @@ void	datblk(int32, int32);
 Sym*	datsort(Sym*);
 void	reloc(void);
 void	relocsym(Sym*);
-void	savedata(Sym*, Prog*);
+void	savedata(Sym*, Prog*, char*);
 void	symgrow(Sym*, int32);
 vlong	addstring(Sym*, char*);
 vlong	adduint32(Sym*, uint32);
diff --git a/src/cmd/ld/macho.c b/src/cmd/ld/macho.c
index c8d7c4a..01349bb 100644
--- a/src/cmd/ld/macho.c
+++ b/src/cmd/ld/macho.c
@@ -12,10 +12,10 @@
 
 static	int	macho64;
 static	MachoHdr	hdr;
-static	MachoLoad	load[16];
+static	MachoLoad	*load;
 static	MachoSeg	seg[16];
 static	MachoDebug	xdebug[16];
-static	int	nload, nseg, ndebug, nsect;
+static	int	nload, mload, nseg, ndebug, nsect;
 
 void
 machoinit(void)
@@ -43,11 +43,18 @@ newMachoLoad(uint32 type, uint32 ndata)
 {
 	MachoLoad *l;
 
-	if(nload >= nelem(load)) {
-		diag("too many loads");
-		errorexit();
+	if(nload >= mload) {
+		if(mload == 0)
+			mload = 1;
+		else
+			mload *= 2;
+		load = realloc(load, mload*sizeof load[0]);
+		if(load == nil) {
+			diag("out of memory");
+			errorexit();
+		}
 	}
-	
+
 	if(macho64 && (ndata & 1))
 		ndata++;
 	
@@ -342,11 +349,13 @@ asmbmacho(void)
 
 	msect = newMachoSect(ms, "__data");
 	msect->addr = va+v;
-	msect->size = symaddr(lookup(".got", 0)) - msect->addr;
 	msect->off = v;
+	msect->size = segdata.filelen;
 
 	s = lookup(".got", 0);
 	if(s->size > 0) {
+		msect->size = symaddr(s) - msect->addr;
+
 		msect = newMachoSect(ms, "__nl_symbol_ptr");
 		msect->addr = symaddr(s);
 		msect->size = s->size;
diff --git a/src/cmd/ld/pe.c b/src/cmd/ld/pe.c
index 0d4240e..d523ca9 100644
--- a/src/cmd/ld/pe.c
+++ b/src/cmd/ld/pe.c
@@ -415,6 +415,9 @@ newPEDWARFSection(char *name, vlong size)
 	IMAGE_SECTION_HEADER *h;
 	char s[8];
 
+	if(size == 0)
+		return nil;
+
 	if(nextsymoff+strlen(name)+1 > sizeof(symnames)) {
 		diag("pe string table is full");
 		errorexit();
diff --git a/src/cmd/ld/symtab.c b/src/cmd/ld/symtab.c
index aefe0b1..da698fc 100644
--- a/src/cmd/ld/symtab.c
+++ b/src/cmd/ld/symtab.c
@@ -140,29 +140,25 @@ void
 putplan9sym(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go)
 {
 	int i;
-		
+
 	switch(t) {
 	case 'T':
-	case 't':
 	case 'L':
-	case 'l':
 	case 'D':
-	case 'd':
 	case 'B':
-	case 'b':
+		if(ver)
+			t += 'a' - 'A';
 	case 'a':
 	case 'p':
-	
 	case 'f':
 	case 'z':
 	case 'Z':
-		
 	case 'm':
 		lputb(addr);
 		cput(t+0x80); /* 0x80 is variable length */
-		
+
 		if(t == 'z' || t == 'Z') {
-			cput(0);
+			cput(s[0]);
 			for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
 				cput(s[i]);
 				cput(s[i+1]);
@@ -172,19 +168,17 @@ putplan9sym(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go)
 			i++;
 		} else {
 			/* skip the '<' in filenames */
-			if(t=='f')
+			if(t == 'f')
 				s++;
-			
 			for(i=0; s[i]; i++)
 				cput(s[i]);
 			cput(0);
 		}
-		
 		symsize += 4 + 1 + i + 1;
 		break;
 	default:
 		return;
-	};	
+	};
 }
 
 void
diff --git a/src/env.bash b/src/env.bash
index c1055d5..ca3eceb 100644
--- a/src/env.bash
+++ b/src/env.bash
@@ -3,6 +3,16 @@
 # Use of this source code is governed by a BSD-style
 # license that can be found in the LICENSE file.
 
+# If set to a Windows-style path convert to an MSYS-Unix 
+# one using the built-in shell commands.   
+if [[ "$GOROOT" == *:* ]]; then
+	GOROOT=$(cd "$GOROOT"; pwd)
+fi
+
+if [[ "$GOBIN" == *:* ]]; then
+	GOBIN=$(cd "$GOBIN"; pwd)
+fi
+
 export GOROOT=${GOROOT:-$(cd ..; pwd)}
 
 if ! test -f "$GOROOT"/include/u.h
diff --git a/src/lib9/create.c b/src/lib9/create.c
index 59845ba..d7023ae 100644
--- a/src/lib9/create.c
+++ b/src/lib9/create.c
@@ -37,9 +37,8 @@ THE SOFTWARE.
 int
 p9create(char *path, int mode, ulong perm)
 {
-	int fd, umode, rclose, rdwr;
+	int fd, umode, rclose;
 
-	rdwr = mode&3;
 	rclose = mode&ORCLOSE;
 	mode &= ~ORCLOSE;
 
diff --git a/src/libmach/executable.c b/src/libmach/executable.c
index 33000ed..e903344 100644
--- a/src/libmach/executable.c
+++ b/src/libmach/executable.c
@@ -991,7 +991,6 @@ machdotout(int fd, Fhdr *fp, ExecHdr *hp)
 {
 	uvlong (*swav)(uvlong);
 	uint32 (*swal)(uint32);
-	ushort (*swab)(ushort);
 	Machhdr *mp;
 	MachCmd **cmd;
 	MachSymSeg *symtab;
@@ -1012,7 +1011,6 @@ machdotout(int fd, Fhdr *fp, ExecHdr *hp)
 		return 0;
 	}
 
-	swab = leswab;
 	swal = leswal;
 	swav = leswav;
 
diff --git a/src/libmach/obj.c b/src/libmach/obj.c
index 1ffe7a0..7d66078 100644
--- a/src/libmach/obj.c
+++ b/src/libmach/obj.c
@@ -215,7 +215,7 @@ processprog(Prog *p, int doautos)
 {
 	if(p->kind == aNone)
 		return 1;
-	if(p->sym < 0 || p->sym >= NNAMES)
+	if((schar)p->sym < 0 || p->sym >= NNAMES)
 		return 0;
 	switch(p->kind)
 	{
diff --git a/src/pkg/Makefile b/src/pkg/Makefile
index e45b39e..b046064 100644
--- a/src/pkg/Makefile
+++ b/src/pkg/Makefile
@@ -100,6 +100,7 @@ DIRS=\
 	html\
 	http\
 	http/cgi\
+	http/fcgi\
 	http/pprof\
 	http/httptest\
 	image\
@@ -120,6 +121,7 @@ DIRS=\
 	netchan\
 	os\
 	os/signal\
+	os/user\
 	patch\
 	path\
 	path/filepath\
@@ -183,7 +185,6 @@ NOTEST+=\
 	hash\
 	http/pprof\
 	http/httptest\
-	image/jpeg\
 	net/dict\
 	rand\
 	runtime/cgo\
@@ -202,11 +203,6 @@ NOTEST+=\
 NOBENCH+=\
 	container/vector\
 
-# Disable tests that depend on an external network.
-ifeq ($(DISABLE_NET_TESTS),1)
-NOTEST+=net syslog
-endif
-
 # Disable tests that windows cannot run yet.
 ifeq ($(GOOS),windows)
 NOTEST+=os/signal    # no signals
diff --git a/src/pkg/archive/tar/common.go b/src/pkg/archive/tar/common.go
index 5b781ff..5288587 100644
--- a/src/pkg/archive/tar/common.go
+++ b/src/pkg/archive/tar/common.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The tar package implements access to tar archives.
+// Package tar implements access to tar archives.
 // It aims to cover most of the variations, including those produced
 // by GNU and BSD tars.
 //
diff --git a/src/pkg/archive/tar/reader.go b/src/pkg/archive/tar/reader.go
index 0cfdf35..ad06b6d 100644
--- a/src/pkg/archive/tar/reader.go
+++ b/src/pkg/archive/tar/reader.go
@@ -10,6 +10,7 @@ package tar
 import (
 	"bytes"
 	"io"
+	"io/ioutil"
 	"os"
 	"strconv"
 )
@@ -84,12 +85,6 @@ func (tr *Reader) octal(b []byte) int64 {
 	return int64(x)
 }
 
-type ignoreWriter struct{}
-
-func (ignoreWriter) Write(b []byte) (n int, err os.Error) {
-	return len(b), nil
-}
-
 // Skip any unread bytes in the existing file entry, as well as any alignment padding.
 func (tr *Reader) skipUnread() {
 	nr := tr.nb + tr.pad // number of bytes to skip
@@ -99,7 +94,7 @@ func (tr *Reader) skipUnread() {
 			return
 		}
 	}
-	_, tr.err = io.Copyn(ignoreWriter{}, tr.r, nr)
+	_, tr.err = io.Copyn(ioutil.Discard, tr.r, nr)
 }
 
 func (tr *Reader) verifyChecksum(header []byte) bool {
diff --git a/src/pkg/archive/zip/reader.go b/src/pkg/archive/zip/reader.go
index 0391d64..17464c5 100644
--- a/src/pkg/archive/zip/reader.go
+++ b/src/pkg/archive/zip/reader.go
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 /*
-The zip package provides support for reading ZIP archives.
+Package zip provides support for reading ZIP archives.
 
 See: http://www.pkware.com/documents/casestudies/APPNOTE.TXT
 
diff --git a/src/pkg/asn1/asn1.go b/src/pkg/asn1/asn1.go
index 8c99bd7..5f470ae 100644
--- a/src/pkg/asn1/asn1.go
+++ b/src/pkg/asn1/asn1.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The asn1 package implements parsing of DER-encoded ASN.1 data structures,
+// Package asn1 implements parsing of DER-encoded ASN.1 data structures,
 // as defined in ITU-T Rec X.690.
 //
 // See also ``A Layman's Guide to a Subset of ASN.1, BER, and DER,''
@@ -418,13 +418,13 @@ func parseSequenceOf(bytes []byte, sliceType reflect.Type, elemType reflect.Type
 }
 
 var (
-	bitStringType        = reflect.Typeof(BitString{})
-	objectIdentifierType = reflect.Typeof(ObjectIdentifier{})
-	enumeratedType       = reflect.Typeof(Enumerated(0))
-	flagType             = reflect.Typeof(Flag(false))
-	timeType             = reflect.Typeof(&time.Time{})
-	rawValueType         = reflect.Typeof(RawValue{})
-	rawContentsType      = reflect.Typeof(RawContent(nil))
+	bitStringType        = reflect.TypeOf(BitString{})
+	objectIdentifierType = reflect.TypeOf(ObjectIdentifier{})
+	enumeratedType       = reflect.TypeOf(Enumerated(0))
+	flagType             = reflect.TypeOf(Flag(false))
+	timeType             = reflect.TypeOf(&time.Time{})
+	rawValueType         = reflect.TypeOf(RawValue{})
+	rawContentsType      = reflect.TypeOf(RawContent(nil))
 )
 
 // invalidLength returns true iff offset + length > sliceLength, or if the
@@ -461,7 +461,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
 		}
 		result := RawValue{t.class, t.tag, t.isCompound, bytes[offset : offset+t.length], bytes[initOffset : offset+t.length]}
 		offset += t.length
-		v.Set(reflect.NewValue(result))
+		v.Set(reflect.ValueOf(result))
 		return
 	}
 
@@ -505,7 +505,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
 			return
 		}
 		if result != nil {
-			v.Set(reflect.NewValue(result))
+			v.Set(reflect.ValueOf(result))
 		}
 		return
 	}
@@ -605,14 +605,14 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
 		newSlice, err1 := parseObjectIdentifier(innerBytes)
 		v.Set(reflect.MakeSlice(v.Type(), len(newSlice), len(newSlice)))
 		if err1 == nil {
-			reflect.Copy(v, reflect.NewValue(newSlice))
+			reflect.Copy(v, reflect.ValueOf(newSlice))
 		}
 		err = err1
 		return
 	case bitStringType:
 		bs, err1 := parseBitString(innerBytes)
 		if err1 == nil {
-			v.Set(reflect.NewValue(bs))
+			v.Set(reflect.ValueOf(bs))
 		}
 		err = err1
 		return
@@ -625,7 +625,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
 			time, err1 = parseGeneralizedTime(innerBytes)
 		}
 		if err1 == nil {
-			v.Set(reflect.NewValue(time))
+			v.Set(reflect.ValueOf(time))
 		}
 		err = err1
 		return
@@ -671,7 +671,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
 		if structType.NumField() > 0 &&
 			structType.Field(0).Type == rawContentsType {
 			bytes := bytes[initOffset:offset]
-			val.Field(0).Set(reflect.NewValue(RawContent(bytes)))
+			val.Field(0).Set(reflect.ValueOf(RawContent(bytes)))
 		}
 
 		innerOffset := 0
@@ -693,7 +693,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
 		sliceType := fieldType
 		if sliceType.Elem().Kind() == reflect.Uint8 {
 			val.Set(reflect.MakeSlice(sliceType, len(innerBytes), len(innerBytes)))
-			reflect.Copy(val, reflect.NewValue(innerBytes))
+			reflect.Copy(val, reflect.ValueOf(innerBytes))
 			return
 		}
 		newSlice, err1 := parseSequenceOf(innerBytes, sliceType, sliceType.Elem())
@@ -798,7 +798,7 @@ func Unmarshal(b []byte, val interface{}) (rest []byte, err os.Error) {
 // UnmarshalWithParams allows field parameters to be specified for the
 // top-level element. The form of the params is the same as the field tags.
 func UnmarshalWithParams(b []byte, val interface{}, params string) (rest []byte, err os.Error) {
-	v := reflect.NewValue(val).Elem()
+	v := reflect.ValueOf(val).Elem()
 	offset, err := parseField(v, b, 0, parseFieldParameters(params))
 	if err != nil {
 		return nil, err
diff --git a/src/pkg/asn1/asn1_test.go b/src/pkg/asn1/asn1_test.go
index 018c534..78f5628 100644
--- a/src/pkg/asn1/asn1_test.go
+++ b/src/pkg/asn1/asn1_test.go
@@ -267,11 +267,6 @@ func TestParseFieldParameters(t *testing.T) {
 	}
 }
 
-type unmarshalTest struct {
-	in  []byte
-	out interface{}
-}
-
 type TestObjectIdentifierStruct struct {
 	OID ObjectIdentifier
 }
@@ -290,7 +285,10 @@ type TestElementsAfterString struct {
 	A, B int
 }
 
-var unmarshalTestData []unmarshalTest = []unmarshalTest{
+var unmarshalTestData = []struct {
+	in  []byte
+	out interface{}
+}{
 	{[]byte{0x02, 0x01, 0x42}, newInt(0x42)},
 	{[]byte{0x30, 0x08, 0x06, 0x06, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d}, &TestObjectIdentifierStruct{[]int{1, 2, 840, 113549}}},
 	{[]byte{0x03, 0x04, 0x06, 0x6e, 0x5d, 0xc0}, &BitString{[]byte{110, 93, 192}, 18}},
@@ -309,9 +307,7 @@ var unmarshalTestData []unmarshalTest = []unmarshalTest{
 
 func TestUnmarshal(t *testing.T) {
 	for i, test := range unmarshalTestData {
-		pv := reflect.Zero(reflect.NewValue(test.out).Type())
-		zv := reflect.Zero(pv.Type().Elem())
-		pv.Set(zv.Addr())
+		pv := reflect.New(reflect.TypeOf(test.out).Elem())
 		val := pv.Interface()
 		_, err := Unmarshal(test.in, val)
 		if err != nil {
diff --git a/src/pkg/asn1/marshal.go b/src/pkg/asn1/marshal.go
index 64cb0f2..a3e1145 100644
--- a/src/pkg/asn1/marshal.go
+++ b/src/pkg/asn1/marshal.go
@@ -493,7 +493,7 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
 // Marshal returns the ASN.1 encoding of val.
 func Marshal(val interface{}) ([]byte, os.Error) {
 	var out bytes.Buffer
-	v := reflect.NewValue(val)
+	v := reflect.ValueOf(val)
 	f := newForkableWriter()
 	err := marshalField(f, v, fieldParameters{})
 	if err != nil {
diff --git a/src/pkg/big/nat.go b/src/pkg/big/nat.go
index a04d3b1..4848d42 100755
--- a/src/pkg/big/nat.go
+++ b/src/pkg/big/nat.go
@@ -2,11 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This file contains operations on unsigned multi-precision integers.
-// These are the building blocks for the operations on signed integers
-// and rationals.
-
-// This package implements multi-precision arithmetic (big numbers).
+// Package big implements multi-precision arithmetic (big numbers).
 // The following numeric types are supported:
 //
 //	- Int	signed integers
@@ -18,6 +14,10 @@
 //
 package big
 
+// This file contains operations on unsigned multi-precision integers.
+// These are the building blocks for the operations on signed integers
+// and rationals.
+
 import "rand"
 
 // An unsigned integer x of the form
diff --git a/src/pkg/bufio/bufio.go b/src/pkg/bufio/bufio.go
index 32a25af..eaae8bb 100644
--- a/src/pkg/bufio/bufio.go
+++ b/src/pkg/bufio/bufio.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package implements buffered I/O.  It wraps an io.Reader or io.Writer
+// Package bufio implements buffered I/O.  It wraps an io.Reader or io.Writer
 // object, creating another object (Reader or Writer) that also implements
 // the interface but provides buffering and some help for textual I/O.
 package bufio
diff --git a/src/pkg/bytes/bytes.go b/src/pkg/bytes/bytes.go
index c12a135..0f9ac98 100644
--- a/src/pkg/bytes/bytes.go
+++ b/src/pkg/bytes/bytes.go
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The bytes package implements functions for the manipulation of byte slices.
-// Analogous to the facilities of the strings package.
+// Package bytes implements functions for the manipulation of byte slices.
+// It is analogous to the facilities of the strings package.
 package bytes
 
 import (
diff --git a/src/pkg/cmath/abs.go b/src/pkg/cmath/abs.go
index 725dc4e..f3199ca 100644
--- a/src/pkg/cmath/abs.go
+++ b/src/pkg/cmath/abs.go
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The cmath package provides basic constants
-// and mathematical functions for complex numbers.
+// Package cmath provides basic constants and mathematical functions for
+// complex numbers.
 package cmath
 
 import "math"
diff --git a/src/pkg/compress/flate/deflate.go b/src/pkg/compress/flate/deflate.go
index 591b35c..e5b2bea 100644
--- a/src/pkg/compress/flate/deflate.go
+++ b/src/pkg/compress/flate/deflate.go
@@ -477,6 +477,33 @@ func NewWriter(w io.Writer, level int) *Writer {
 	return &Writer{pw, &d}
 }
 
+// NewWriterDict is like NewWriter but initializes the new
+// Writer with a preset dictionary.  The returned Writer behaves
+// as if the dictionary had been written to it without producing
+// any compressed output.  The compressed data written to w
+// can only be decompressed by a Reader initialized with the
+// same dictionary.
+func NewWriterDict(w io.Writer, level int, dict []byte) *Writer {
+	dw := &dictWriter{w, false}
+	zw := NewWriter(dw, level)
+	zw.Write(dict)
+	zw.Flush()
+	dw.enabled = true
+	return zw
+}
+
+type dictWriter struct {
+	w       io.Writer
+	enabled bool
+}
+
+func (w *dictWriter) Write(b []byte) (n int, err os.Error) {
+	if w.enabled {
+		return w.w.Write(b)
+	}
+	return len(b), nil
+}
+
 // A Writer takes data written to it and writes the compressed
 // form of that data to an underlying writer (see NewWriter).
 type Writer struct {
diff --git a/src/pkg/compress/flate/deflate_test.go b/src/pkg/compress/flate/deflate_test.go
index ed5884a..650a805 100644
--- a/src/pkg/compress/flate/deflate_test.go
+++ b/src/pkg/compress/flate/deflate_test.go
@@ -275,3 +275,49 @@ func TestDeflateInflateString(t *testing.T) {
 	}
 	testToFromWithLevel(t, 1, gold, "2.718281828...")
 }
+
+func TestReaderDict(t *testing.T) {
+	const (
+		dict = "hello world"
+		text = "hello again world"
+	)
+	var b bytes.Buffer
+	w := NewWriter(&b, 5)
+	w.Write([]byte(dict))
+	w.Flush()
+	b.Reset()
+	w.Write([]byte(text))
+	w.Close()
+
+	r := NewReaderDict(&b, []byte(dict))
+	data, err := ioutil.ReadAll(r)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if string(data) != "hello again world" {
+		t.Fatalf("read returned %q want %q", string(data), text)
+	}
+}
+
+func TestWriterDict(t *testing.T) {
+	const (
+		dict = "hello world"
+		text = "hello again world"
+	)
+	var b bytes.Buffer
+	w := NewWriter(&b, 5)
+	w.Write([]byte(dict))
+	w.Flush()
+	b.Reset()
+	w.Write([]byte(text))
+	w.Close()
+
+	var b1 bytes.Buffer
+	w = NewWriterDict(&b1, 5, []byte(dict))
+	w.Write([]byte(text))
+	w.Close()
+
+	if !bytes.Equal(b1.Bytes(), b.Bytes()) {
+		t.Fatalf("writer wrote %q want %q", b1.Bytes(), b.Bytes())
+	}
+}
diff --git a/src/pkg/compress/flate/inflate.go b/src/pkg/compress/flate/inflate.go
index 7dc8cf9..320b80d 100644
--- a/src/pkg/compress/flate/inflate.go
+++ b/src/pkg/compress/flate/inflate.go
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The flate package implements the DEFLATE compressed data
-// format, described in RFC 1951.  The gzip and zlib packages
-// implement access to DEFLATE-based file formats.
+// Package flate implements the DEFLATE compressed data format, described in
+// RFC 1951.  The gzip and zlib packages implement access to DEFLATE-based file
+// formats.
 package flate
 
 import (
@@ -526,6 +526,20 @@ func (f *decompressor) dataBlock() os.Error {
 	return nil
 }
 
+func (f *decompressor) setDict(dict []byte) {
+	if len(dict) > len(f.hist) {
+		// Will only remember the tail.
+		dict = dict[len(dict)-len(f.hist):]
+	}
+
+	f.hp = copy(f.hist[:], dict)
+	if f.hp == len(f.hist) {
+		f.hp = 0
+		f.hfull = true
+	}
+	f.hw = f.hp
+}
+
 func (f *decompressor) moreBits() os.Error {
 	c, err := f.r.ReadByte()
 	if err != nil {
@@ -618,3 +632,16 @@ func NewReader(r io.Reader) io.ReadCloser {
 	go func() { pw.CloseWithError(f.decompress(r, pw)) }()
 	return pr
 }
+
+// NewReaderDict is like NewReader but initializes the reader
+// with a preset dictionary.  The returned Reader behaves as if
+// the uncompressed data stream started with the given dictionary,
+// which has already been read.  NewReaderDict is typically used
+// to read data compressed by NewWriterDict.
+func NewReaderDict(r io.Reader, dict []byte) io.ReadCloser {
+	var f decompressor
+	f.setDict(dict)
+	pr, pw := io.Pipe()
+	go func() { pw.CloseWithError(f.decompress(r, pw)) }()
+	return pr
+}
diff --git a/src/pkg/compress/gzip/gunzip.go b/src/pkg/compress/gzip/gunzip.go
index 3c0b3c5..b0ddc81 100644
--- a/src/pkg/compress/gzip/gunzip.go
+++ b/src/pkg/compress/gzip/gunzip.go
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The gzip package implements reading and writing of
-// gzip format compressed files, as specified in RFC 1952.
+// Package gzip implements reading and writing of gzip format compressed files,
+// as specified in RFC 1952.
 package gzip
 
 import (
diff --git a/src/pkg/compress/lzw/reader.go b/src/pkg/compress/lzw/reader.go
index 8a540cb..d418bc8 100644
--- a/src/pkg/compress/lzw/reader.go
+++ b/src/pkg/compress/lzw/reader.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The lzw package implements the Lempel-Ziv-Welch compressed data format,
+// Package lzw implements the Lempel-Ziv-Welch compressed data format,
 // described in T. A. Welch, ``A Technique for High-Performance Data
 // Compression'', Computer, 17(6) (June 1984), pp 8-19.
 //
diff --git a/src/pkg/compress/lzw/reader_test.go b/src/pkg/compress/lzw/reader_test.go
index 4b5dfaa..72121a6 100644
--- a/src/pkg/compress/lzw/reader_test.go
+++ b/src/pkg/compress/lzw/reader_test.go
@@ -112,12 +112,6 @@ func TestReader(t *testing.T) {
 	}
 }
 
-type devNull struct{}
-
-func (devNull) Write(p []byte) (int, os.Error) {
-	return len(p), nil
-}
-
 func benchmarkDecoder(b *testing.B, n int) {
 	b.StopTimer()
 	b.SetBytes(int64(n))
@@ -134,7 +128,7 @@ func benchmarkDecoder(b *testing.B, n int) {
 	runtime.GC()
 	b.StartTimer()
 	for i := 0; i < b.N; i++ {
-		io.Copy(devNull{}, NewReader(bytes.NewBuffer(buf1), LSB, 8))
+		io.Copy(ioutil.Discard, NewReader(bytes.NewBuffer(buf1), LSB, 8))
 	}
 }
 
diff --git a/src/pkg/compress/lzw/writer_test.go b/src/pkg/compress/lzw/writer_test.go
index e5815a0..82464ec 100644
--- a/src/pkg/compress/lzw/writer_test.go
+++ b/src/pkg/compress/lzw/writer_test.go
@@ -113,7 +113,7 @@ func benchmarkEncoder(b *testing.B, n int) {
 	runtime.GC()
 	b.StartTimer()
 	for i := 0; i < b.N; i++ {
-		w := NewWriter(devNull{}, LSB, 8)
+		w := NewWriter(ioutil.Discard, LSB, 8)
 		w.Write(buf1)
 		w.Close()
 	}
diff --git a/src/pkg/compress/zlib/reader.go b/src/pkg/compress/zlib/reader.go
index 721f6ec..8a3ef15 100644
--- a/src/pkg/compress/zlib/reader.go
+++ b/src/pkg/compress/zlib/reader.go
@@ -3,8 +3,8 @@
 // license that can be found in the LICENSE file.
 
 /*
-The zlib package implements reading and writing of zlib
-format compressed data, as specified in RFC 1950.
+Package zlib implements reading and writing of zlib format compressed data,
+as specified in RFC 1950.
 
 The implementation provides filters that uncompress during reading
 and compress during writing.  For example, to write compressed data
@@ -36,7 +36,7 @@ const zlibDeflate = 8
 
 var ChecksumError os.Error = os.ErrorString("zlib checksum error")
 var HeaderError os.Error = os.ErrorString("invalid zlib header")
-var UnsupportedError os.Error = os.ErrorString("unsupported zlib format")
+var DictionaryError os.Error = os.ErrorString("invalid zlib dictionary")
 
 type reader struct {
 	r            flate.Reader
@@ -50,6 +50,12 @@ type reader struct {
 // The implementation buffers input and may read more data than necessary from r.
 // It is the caller's responsibility to call Close on the ReadCloser when done.
 func NewReader(r io.Reader) (io.ReadCloser, os.Error) {
+	return NewReaderDict(r, nil)
+}
+
+// NewReaderDict is like NewReader but uses a preset dictionary.
+// NewReaderDict ignores the dictionary if the compressed data does not refer to it.
+func NewReaderDict(r io.Reader, dict []byte) (io.ReadCloser, os.Error) {
 	z := new(reader)
 	if fr, ok := r.(flate.Reader); ok {
 		z.r = fr
@@ -65,11 +71,19 @@ func NewReader(r io.Reader) (io.ReadCloser, os.Error) {
 		return nil, HeaderError
 	}
 	if z.scratch[1]&0x20 != 0 {
-		// BUG(nigeltao): The zlib package does not implement the FDICT flag.
-		return nil, UnsupportedError
+		_, err = io.ReadFull(z.r, z.scratch[0:4])
+		if err != nil {
+			return nil, err
+		}
+		checksum := uint32(z.scratch[0])<<24 | uint32(z.scratch[1])<<16 | uint32(z.scratch[2])<<8 | uint32(z.scratch[3])
+		if checksum != adler32.Checksum(dict) {
+			return nil, DictionaryError
+		}
+		z.decompressor = flate.NewReaderDict(z.r, dict)
+	} else {
+		z.decompressor = flate.NewReader(z.r)
 	}
 	z.digest = adler32.New()
-	z.decompressor = flate.NewReader(z.r)
 	return z, nil
 }
 
diff --git a/src/pkg/compress/zlib/reader_test.go b/src/pkg/compress/zlib/reader_test.go
index eaefc3a..195db44 100644
--- a/src/pkg/compress/zlib/reader_test.go
+++ b/src/pkg/compress/zlib/reader_test.go
@@ -15,6 +15,7 @@ type zlibTest struct {
 	desc       string
 	raw        string
 	compressed []byte
+	dict       []byte
 	err        os.Error
 }
 
@@ -27,6 +28,7 @@ var zlibTests = []zlibTest{
 		"",
 		[]byte{0x78, 0x9c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01},
 		nil,
+		nil,
 	},
 	{
 		"goodbye",
@@ -37,23 +39,27 @@ var zlibTests = []zlibTest{
 			0x01, 0x00, 0x28, 0xa5, 0x05, 0x5e,
 		},
 		nil,
+		nil,
 	},
 	{
 		"bad header",
 		"",
 		[]byte{0x78, 0x9f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01},
+		nil,
 		HeaderError,
 	},
 	{
 		"bad checksum",
 		"",
 		[]byte{0x78, 0x9c, 0x03, 0x00, 0x00, 0x00, 0x00, 0xff},
+		nil,
 		ChecksumError,
 	},
 	{
 		"not enough data",
 		"",
 		[]byte{0x78, 0x9c, 0x03, 0x00, 0x00, 0x00},
+		nil,
 		io.ErrUnexpectedEOF,
 	},
 	{
@@ -64,6 +70,33 @@ var zlibTests = []zlibTest{
 			0x78, 0x9c, 0xff,
 		},
 		nil,
+		nil,
+	},
+	{
+		"dictionary",
+		"Hello, World!\n",
+		[]byte{
+			0x78, 0xbb, 0x1c, 0x32, 0x04, 0x27, 0xf3, 0x00,
+			0xb1, 0x75, 0x20, 0x1c, 0x45, 0x2e, 0x00, 0x24,
+			0x12, 0x04, 0x74,
+		},
+		[]byte{
+			0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x0a,
+		},
+		nil,
+	},
+	{
+		"wrong dictionary",
+		"",
+		[]byte{
+			0x78, 0xbb, 0x1c, 0x32, 0x04, 0x27, 0xf3, 0x00,
+			0xb1, 0x75, 0x20, 0x1c, 0x45, 0x2e, 0x00, 0x24,
+			0x12, 0x04, 0x74,
+		},
+		[]byte{
+			0x48, 0x65, 0x6c, 0x6c,
+		},
+		DictionaryError,
 	},
 }
 
@@ -71,7 +104,7 @@ func TestDecompressor(t *testing.T) {
 	b := new(bytes.Buffer)
 	for _, tt := range zlibTests {
 		in := bytes.NewBuffer(tt.compressed)
-		zlib, err := NewReader(in)
+		zlib, err := NewReaderDict(in, tt.dict)
 		if err != nil {
 			if err != tt.err {
 				t.Errorf("%s: NewReader: %s", tt.desc, err)
diff --git a/src/pkg/compress/zlib/writer.go b/src/pkg/compress/zlib/writer.go
index 031586c..f1f9b28 100644
--- a/src/pkg/compress/zlib/writer.go
+++ b/src/pkg/compress/zlib/writer.go
@@ -21,56 +21,80 @@ const (
 	DefaultCompression = flate.DefaultCompression
 )
 
-type writer struct {
+// A Writer takes data written to it and writes the compressed
+// form of that data to an underlying writer (see NewWriter).
+type Writer struct {
 	w          io.Writer
-	compressor io.WriteCloser
+	compressor *flate.Writer
 	digest     hash.Hash32
 	err        os.Error
 	scratch    [4]byte
 }
 
 // NewWriter calls NewWriterLevel with the default compression level.
-func NewWriter(w io.Writer) (io.WriteCloser, os.Error) {
+func NewWriter(w io.Writer) (*Writer, os.Error) {
 	return NewWriterLevel(w, DefaultCompression)
 }
 
-// NewWriterLevel creates a new io.WriteCloser that satisfies writes by compressing data written to w.
+// NewWriterLevel calls NewWriterDict with no dictionary.
+func NewWriterLevel(w io.Writer, level int) (*Writer, os.Error) {
+	return NewWriterDict(w, level, nil)
+}
+
+// NewWriterDict creates a new io.WriteCloser that satisfies writes by compressing data written to w.
 // It is the caller's responsibility to call Close on the WriteCloser when done.
 // level is the compression level, which can be DefaultCompression, NoCompression,
 // or any integer value between BestSpeed and BestCompression (inclusive).
-func NewWriterLevel(w io.Writer, level int) (io.WriteCloser, os.Error) {
-	z := new(writer)
+// dict is the preset dictionary to compress with, or nil to use no dictionary.
+func NewWriterDict(w io.Writer, level int, dict []byte) (*Writer, os.Error) {
+	z := new(Writer)
 	// ZLIB has a two-byte header (as documented in RFC 1950).
 	// The first four bits is the CINFO (compression info), which is 7 for the default deflate window size.
 	// The next four bits is the CM (compression method), which is 8 for deflate.
 	z.scratch[0] = 0x78
 	// The next two bits is the FLEVEL (compression level). The four values are:
 	// 0=fastest, 1=fast, 2=default, 3=best.
-	// The next bit, FDICT, is unused, in this implementation.
+	// The next bit, FDICT, is set if a dictionary is given.
 	// The final five FCHECK bits form a mod-31 checksum.
 	switch level {
 	case 0, 1:
-		z.scratch[1] = 0x01
+		z.scratch[1] = 0 << 6
 	case 2, 3, 4, 5:
-		z.scratch[1] = 0x5e
+		z.scratch[1] = 1 << 6
 	case 6, -1:
-		z.scratch[1] = 0x9c
+		z.scratch[1] = 2 << 6
 	case 7, 8, 9:
-		z.scratch[1] = 0xda
+		z.scratch[1] = 3 << 6
 	default:
 		return nil, os.NewError("level out of range")
 	}
+	if dict != nil {
+		z.scratch[1] |= 1 << 5
+	}
+	z.scratch[1] += uint8(31 - (uint16(z.scratch[0])<<8+uint16(z.scratch[1]))%31)
 	_, err := w.Write(z.scratch[0:2])
 	if err != nil {
 		return nil, err
 	}
+	if dict != nil {
+		// The next four bytes are the Adler-32 checksum of the dictionary.
+		checksum := adler32.Checksum(dict)
+		z.scratch[0] = uint8(checksum >> 24)
+		z.scratch[1] = uint8(checksum >> 16)
+		z.scratch[2] = uint8(checksum >> 8)
+		z.scratch[3] = uint8(checksum >> 0)
+		_, err = w.Write(z.scratch[0:4])
+		if err != nil {
+			return nil, err
+		}
+	}
 	z.w = w
 	z.compressor = flate.NewWriter(w, level)
 	z.digest = adler32.New()
 	return z, nil
 }
 
-func (z *writer) Write(p []byte) (n int, err os.Error) {
+func (z *Writer) Write(p []byte) (n int, err os.Error) {
 	if z.err != nil {
 		return 0, z.err
 	}
@@ -86,8 +110,17 @@ func (z *writer) Write(p []byte) (n int, err os.Error) {
 	return
 }
 
+// Flush flushes the underlying compressor.
+func (z *Writer) Flush() os.Error {
+	if z.err != nil {
+		return z.err
+	}
+	z.err = z.compressor.Flush()
+	return z.err
+}
+
 // Calling Close does not close the wrapped io.Writer originally passed to NewWriter.
-func (z *writer) Close() os.Error {
+func (z *Writer) Close() os.Error {
 	if z.err != nil {
 		return z.err
 	}
diff --git a/src/pkg/compress/zlib/writer_test.go b/src/pkg/compress/zlib/writer_test.go
index 7eb1cd4..f94f284 100644
--- a/src/pkg/compress/zlib/writer_test.go
+++ b/src/pkg/compress/zlib/writer_test.go
@@ -16,13 +16,19 @@ var filenames = []string{
 	"../testdata/pi.txt",
 }
 
-// Tests that compressing and then decompressing the given file at the given compression level
+// Tests that compressing and then decompressing the given file at the given compression level and dictionary
 // yields equivalent bytes to the original file.
-func testFileLevel(t *testing.T, fn string, level int) {
+func testFileLevelDict(t *testing.T, fn string, level int, d string) {
+	// Read dictionary, if given.
+	var dict []byte
+	if d != "" {
+		dict = []byte(d)
+	}
+
 	// Read the file, as golden output.
 	golden, err := os.Open(fn)
 	if err != nil {
-		t.Errorf("%s (level=%d): %v", fn, level, err)
+		t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err)
 		return
 	}
 	defer golden.Close()
@@ -30,7 +36,7 @@ func testFileLevel(t *testing.T, fn string, level int) {
 	// Read the file again, and push it through a pipe that compresses at the write end, and decompresses at the read end.
 	raw, err := os.Open(fn)
 	if err != nil {
-		t.Errorf("%s (level=%d): %v", fn, level, err)
+		t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err)
 		return
 	}
 	piper, pipew := io.Pipe()
@@ -38,9 +44,9 @@ func testFileLevel(t *testing.T, fn string, level int) {
 	go func() {
 		defer raw.Close()
 		defer pipew.Close()
-		zlibw, err := NewWriterLevel(pipew, level)
+		zlibw, err := NewWriterDict(pipew, level, dict)
 		if err != nil {
-			t.Errorf("%s (level=%d): %v", fn, level, err)
+			t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err)
 			return
 		}
 		defer zlibw.Close()
@@ -48,7 +54,7 @@ func testFileLevel(t *testing.T, fn string, level int) {
 		for {
 			n, err0 := raw.Read(b[0:])
 			if err0 != nil && err0 != os.EOF {
-				t.Errorf("%s (level=%d): %v", fn, level, err0)
+				t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err0)
 				return
 			}
 			_, err1 := zlibw.Write(b[0:n])
@@ -57,7 +63,7 @@ func testFileLevel(t *testing.T, fn string, level int) {
 				return
 			}
 			if err1 != nil {
-				t.Errorf("%s (level=%d): %v", fn, level, err1)
+				t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err1)
 				return
 			}
 			if err0 == os.EOF {
@@ -65,9 +71,9 @@ func testFileLevel(t *testing.T, fn string, level int) {
 			}
 		}
 	}()
-	zlibr, err := NewReader(piper)
+	zlibr, err := NewReaderDict(piper, dict)
 	if err != nil {
-		t.Errorf("%s (level=%d): %v", fn, level, err)
+		t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err)
 		return
 	}
 	defer zlibr.Close()
@@ -76,20 +82,20 @@ func testFileLevel(t *testing.T, fn string, level int) {
 	b0, err0 := ioutil.ReadAll(golden)
 	b1, err1 := ioutil.ReadAll(zlibr)
 	if err0 != nil {
-		t.Errorf("%s (level=%d): %v", fn, level, err0)
+		t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err0)
 		return
 	}
 	if err1 != nil {
-		t.Errorf("%s (level=%d): %v", fn, level, err1)
+		t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err1)
 		return
 	}
 	if len(b0) != len(b1) {
-		t.Errorf("%s (level=%d): length mismatch %d versus %d", fn, level, len(b0), len(b1))
+		t.Errorf("%s (level=%d, dict=%q): length mismatch %d versus %d", fn, level, d, len(b0), len(b1))
 		return
 	}
 	for i := 0; i < len(b0); i++ {
 		if b0[i] != b1[i] {
-			t.Errorf("%s (level=%d): mismatch at %d, 0x%02x versus 0x%02x\n", fn, level, i, b0[i], b1[i])
+			t.Errorf("%s (level=%d, dict=%q): mismatch at %d, 0x%02x versus 0x%02x\n", fn, level, d, i, b0[i], b1[i])
 			return
 		}
 	}
@@ -97,10 +103,21 @@ func testFileLevel(t *testing.T, fn string, level int) {
 
 func TestWriter(t *testing.T) {
 	for _, fn := range filenames {
-		testFileLevel(t, fn, DefaultCompression)
-		testFileLevel(t, fn, NoCompression)
+		testFileLevelDict(t, fn, DefaultCompression, "")
+		testFileLevelDict(t, fn, NoCompression, "")
+		for level := BestSpeed; level <= BestCompression; level++ {
+			testFileLevelDict(t, fn, level, "")
+		}
+	}
+}
+
+func TestWriterDict(t *testing.T) {
+	const dictionary = "0123456789."
+	for _, fn := range filenames {
+		testFileLevelDict(t, fn, DefaultCompression, dictionary)
+		testFileLevelDict(t, fn, NoCompression, dictionary)
 		for level := BestSpeed; level <= BestCompression; level++ {
-			testFileLevel(t, fn, level)
+			testFileLevelDict(t, fn, level, dictionary)
 		}
 	}
 }
diff --git a/src/pkg/container/heap/heap.go b/src/pkg/container/heap/heap.go
index 4435a57..f2b8a75 100644
--- a/src/pkg/container/heap/heap.go
+++ b/src/pkg/container/heap/heap.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package provides heap operations for any type that implements
+// Package heap provides heap operations for any type that implements
 // heap.Interface.
 //
 package heap
diff --git a/src/pkg/container/heap/heap_test.go b/src/pkg/container/heap/heap_test.go
index 89d444d..5eb5437 100644
--- a/src/pkg/container/heap/heap_test.go
+++ b/src/pkg/container/heap/heap_test.go
@@ -2,11 +2,12 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package heap
+package heap_test
 
 import (
 	"testing"
 	"container/vector"
+	. "container/heap"
 )
 
 
diff --git a/src/pkg/container/list/list.go b/src/pkg/container/list/list.go
index c1ebcdd..a3fd4b3 100644
--- a/src/pkg/container/list/list.go
+++ b/src/pkg/container/list/list.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The list package implements a doubly linked list.
+// Package list implements a doubly linked list.
 //
 // To iterate over a list (where l is a *List):
 //	for e := l.Front(); e != nil; e = e.Next() {
diff --git a/src/pkg/container/ring/ring.go b/src/pkg/container/ring/ring.go
index 5925164..cc870ce 100644
--- a/src/pkg/container/ring/ring.go
+++ b/src/pkg/container/ring/ring.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The ring package implements operations on circular lists.
+// Package ring implements operations on circular lists.
 package ring
 
 // A Ring is an element of a circular list, or ring.
diff --git a/src/pkg/container/vector/defs.go b/src/pkg/container/vector/defs.go
index a2febb6..bfb5481 100644
--- a/src/pkg/container/vector/defs.go
+++ b/src/pkg/container/vector/defs.go
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The vector package implements containers for managing sequences
-// of elements. Vectors grow and shrink dynamically as necessary.
+// Package vector implements containers for managing sequences of elements.
+// Vectors grow and shrink dynamically as necessary.
 package vector
 
 
diff --git a/src/pkg/crypto/aes/const.go b/src/pkg/crypto/aes/const.go
index 97a5b64..25acd0d 100644
--- a/src/pkg/crypto/aes/const.go
+++ b/src/pkg/crypto/aes/const.go
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// AES constants - 8720 bytes of initialized data.
-
-// This package implements AES encryption (formerly Rijndael),
-// as defined in U.S. Federal Information Processing Standards Publication 197.
+// Package aes implements AES encryption (formerly Rijndael), as defined in
+// U.S. Federal Information Processing Standards Publication 197.
 package aes
 
+// This file contains AES constants - 8720 bytes of initialized data.
+
 // http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf
 
 // AES is based on the mathematical behavior of binary polynomials
diff --git a/src/pkg/crypto/blowfish/cipher.go b/src/pkg/crypto/blowfish/cipher.go
index 947f762..f3c5175 100644
--- a/src/pkg/crypto/blowfish/cipher.go
+++ b/src/pkg/crypto/blowfish/cipher.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package implements Bruce Schneier's Blowfish encryption algorithm.
+// Package blowfish implements Bruce Schneier's Blowfish encryption algorithm.
 package blowfish
 
 // The code is a port of Bruce Schneier's C implementation.
diff --git a/src/pkg/crypto/cast5/cast5.go b/src/pkg/crypto/cast5/cast5.go
index 35f3e64..cb62e31 100644
--- a/src/pkg/crypto/cast5/cast5.go
+++ b/src/pkg/crypto/cast5/cast5.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package implements CAST5, as defined in RFC 2144. CAST5 is a common
+// Package cast5 implements CAST5, as defined in RFC 2144. CAST5 is a common
 // OpenPGP cipher.
 package cast5
 
diff --git a/src/pkg/crypto/cipher/cipher.go b/src/pkg/crypto/cipher/cipher.go
index 50516b2..1ffaa8c 100644
--- a/src/pkg/crypto/cipher/cipher.go
+++ b/src/pkg/crypto/cipher/cipher.go
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The cipher package implements standard block cipher modes
-// that can be wrapped around low-level block cipher implementations.
+// Package cipher implements standard block cipher modes that can be wrapped
+// around low-level block cipher implementations.
 // See http://csrc.nist.gov/groups/ST/toolkit/BCM/current_modes.html
 // and NIST Special Publication 800-38A.
 package cipher
diff --git a/src/pkg/crypto/crypto.go b/src/pkg/crypto/crypto.go
index be6b34a..53672a4 100644
--- a/src/pkg/crypto/crypto.go
+++ b/src/pkg/crypto/crypto.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The crypto package collects common cryptographic constants.
+// Package crypto collects common cryptographic constants.
 package crypto
 
 import (
diff --git a/src/pkg/crypto/elliptic/elliptic.go b/src/pkg/crypto/elliptic/elliptic.go
index 2296e96..335c964 100644
--- a/src/pkg/crypto/elliptic/elliptic.go
+++ b/src/pkg/crypto/elliptic/elliptic.go
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The elliptic package implements several standard elliptic curves over prime
-// fields
+// Package elliptic implements several standard elliptic curves over prime
+// fields.
 package elliptic
 
 // This package operates, internally, on Jacobian coordinates. For a given
diff --git a/src/pkg/crypto/hmac/hmac.go b/src/pkg/crypto/hmac/hmac.go
index 298fb2c..04ec86e 100644
--- a/src/pkg/crypto/hmac/hmac.go
+++ b/src/pkg/crypto/hmac/hmac.go
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The hmac package implements the Keyed-Hash Message Authentication Code (HMAC)
-// as defined in U.S. Federal Information Processing Standards Publication 198.
+// Package hmac implements the Keyed-Hash Message Authentication Code (HMAC) as
+// defined in U.S. Federal Information Processing Standards Publication 198.
 // An HMAC is a cryptographic hash that uses a key to sign a message.
 // The receiver verifies the hash by recomputing it using the same key.
 package hmac
diff --git a/src/pkg/crypto/md4/md4.go b/src/pkg/crypto/md4/md4.go
index ee46544..848d955 100644
--- a/src/pkg/crypto/md4/md4.go
+++ b/src/pkg/crypto/md4/md4.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package implements the MD4 hash algorithm as defined in RFC 1320.
+// Package md4 implements the MD4 hash algorithm as defined in RFC 1320.
 package md4
 
 import (
diff --git a/src/pkg/crypto/md5/md5.go b/src/pkg/crypto/md5/md5.go
index 8f93fc4..378faa6 100644
--- a/src/pkg/crypto/md5/md5.go
+++ b/src/pkg/crypto/md5/md5.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package implements the MD5 hash algorithm as defined in RFC 1321.
+// Package md5 implements the MD5 hash algorithm as defined in RFC 1321.
 package md5
 
 import (
diff --git a/src/pkg/crypto/ocsp/ocsp.go b/src/pkg/crypto/ocsp/ocsp.go
index f42d808..acd75b8 100644
--- a/src/pkg/crypto/ocsp/ocsp.go
+++ b/src/pkg/crypto/ocsp/ocsp.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package parses OCSP responses as specified in RFC 2560. OCSP responses
+// Package ocsp parses OCSP responses as specified in RFC 2560. OCSP responses
 // are signed messages attesting to the validity of a certificate for a small
 // period of time. This is used to manage revocation for X.509 certificates.
 package ocsp
diff --git a/src/pkg/crypto/openpgp/armor/armor.go b/src/pkg/crypto/openpgp/armor/armor.go
index d695a8c..8da612c 100644
--- a/src/pkg/crypto/openpgp/armor/armor.go
+++ b/src/pkg/crypto/openpgp/armor/armor.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package implements OpenPGP ASCII Armor, see RFC 4880. OpenPGP Armor is
+// Package armor implements OpenPGP ASCII Armor, see RFC 4880. OpenPGP Armor is
 // very similar to PEM except that it has an additional CRC checksum.
 package armor
 
diff --git a/src/pkg/crypto/openpgp/error/error.go b/src/pkg/crypto/openpgp/error/error.go
index 053d159..3759ce1 100644
--- a/src/pkg/crypto/openpgp/error/error.go
+++ b/src/pkg/crypto/openpgp/error/error.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package contains common error types for the OpenPGP packages.
+// Package error contains common error types for the OpenPGP packages.
 package error
 
 import (
diff --git a/src/pkg/crypto/openpgp/keys.go b/src/pkg/crypto/openpgp/keys.go
index ecaa86f..6c03f88 100644
--- a/src/pkg/crypto/openpgp/keys.go
+++ b/src/pkg/crypto/openpgp/keys.go
@@ -5,6 +5,7 @@
 package openpgp
 
 import (
+	"crypto/openpgp/armor"
 	"crypto/openpgp/error"
 	"crypto/openpgp/packet"
 	"io"
@@ -13,6 +14,8 @@ import (
 
 // PublicKeyType is the armor type for a PGP public key.
 var PublicKeyType = "PGP PUBLIC KEY BLOCK"
+// PrivateKeyType is the armor type for a PGP private key.
+var PrivateKeyType = "PGP PRIVATE KEY BLOCK"
 
 // An Entity represents the components of an OpenPGP key: a primary public key
 // (which must be a signing key), one or more identities claimed by that key,
@@ -101,37 +104,50 @@ func (el EntityList) DecryptionKeys() (keys []Key) {
 
 // ReadArmoredKeyRing reads one or more public/private keys from an armor keyring file.
 func ReadArmoredKeyRing(r io.Reader) (EntityList, os.Error) {
-	body, err := readArmored(r, PublicKeyType)
+	block, err := armor.Decode(r)
+	if err == os.EOF {
+		return nil, error.InvalidArgumentError("no armored data found")
+	}
 	if err != nil {
 		return nil, err
 	}
+	if block.Type != PublicKeyType && block.Type != PrivateKeyType {
+		return nil, error.InvalidArgumentError("expected public or private key block, got: " + block.Type)
+	}
 
-	return ReadKeyRing(body)
+	return ReadKeyRing(block.Body)
 }
 
-// ReadKeyRing reads one or more public/private keys, ignoring unsupported keys.
+// ReadKeyRing reads one or more public/private keys. Unsupported keys are
+// ignored as long as at least a single valid key is found.
 func ReadKeyRing(r io.Reader) (el EntityList, err os.Error) {
 	packets := packet.NewReader(r)
+	var lastUnsupportedError os.Error
 
 	for {
 		var e *Entity
 		e, err = readEntity(packets)
 		if err != nil {
 			if _, ok := err.(error.UnsupportedError); ok {
+				lastUnsupportedError = err
 				err = readToNextPublicKey(packets)
 			}
 			if err == os.EOF {
 				err = nil
-				return
+				break
 			}
 			if err != nil {
 				el = nil
-				return
+				break
 			}
 		} else {
 			el = append(el, e)
 		}
 	}
+
+	if len(el) == 0 && err == nil {
+		err = lastUnsupportedError
+	}
 	return
 }
 
@@ -197,25 +213,28 @@ EachPacket:
 			current.Name = pkt.Id
 			current.UserId = pkt
 			e.Identities[pkt.Id] = current
-			p, err = packets.Next()
-			if err == os.EOF {
-				err = io.ErrUnexpectedEOF
-			}
-			if err != nil {
-				if _, ok := err.(error.UnsupportedError); ok {
+
+			for {
+				p, err = packets.Next()
+				if err == os.EOF {
+					return nil, io.ErrUnexpectedEOF
+				} else if err != nil {
 					return nil, err
 				}
-				return nil, error.StructuralError("identity self-signature invalid: " + err.String())
-			}
-			current.SelfSignature, ok = p.(*packet.Signature)
-			if !ok {
-				return nil, error.StructuralError("user ID packet not followed by self signature")
-			}
-			if current.SelfSignature.SigType != packet.SigTypePositiveCert {
-				return nil, error.StructuralError("user ID self-signature with wrong type")
-			}
-			if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, current.SelfSignature); err != nil {
-				return nil, error.StructuralError("user ID self-signature invalid: " + err.String())
+
+				sig, ok := p.(*packet.Signature)
+				if !ok {
+					return nil, error.StructuralError("user ID packet not followed by self-signature")
+				}
+
+				if sig.SigType == packet.SigTypePositiveCert && sig.IssuerKeyId != nil && *sig.IssuerKeyId == e.PrimaryKey.KeyId {
+					if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, sig); err != nil {
+						return nil, error.StructuralError("user ID self-signature invalid: " + err.String())
+					}
+					current.SelfSignature = sig
+					break
+				}
+				current.Signatures = append(current.Signatures, sig)
 			}
 		case *packet.Signature:
 			if current == nil {
diff --git a/src/pkg/crypto/openpgp/packet/packet.go b/src/pkg/crypto/openpgp/packet/packet.go
index 57ff3af..c0ec44d 100644
--- a/src/pkg/crypto/openpgp/packet/packet.go
+++ b/src/pkg/crypto/openpgp/packet/packet.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package implements parsing and serialisation of OpenPGP packets, as
+// Package packet implements parsing and serialisation of OpenPGP packets, as
 // specified in RFC 4880.
 package packet
 
diff --git a/src/pkg/crypto/openpgp/packet/private_key.go b/src/pkg/crypto/openpgp/packet/private_key.go
index 6944823..fde2a99 100644
--- a/src/pkg/crypto/openpgp/packet/private_key.go
+++ b/src/pkg/crypto/openpgp/packet/private_key.go
@@ -164,8 +164,10 @@ func (pk *PrivateKey) parseRSAPrivateKey(data []byte) (err os.Error) {
 	}
 
 	rsaPriv.D = new(big.Int).SetBytes(d)
-	rsaPriv.P = new(big.Int).SetBytes(p)
-	rsaPriv.Q = new(big.Int).SetBytes(q)
+	rsaPriv.Primes = make([]*big.Int, 2)
+	rsaPriv.Primes[0] = new(big.Int).SetBytes(p)
+	rsaPriv.Primes[1] = new(big.Int).SetBytes(q)
+	rsaPriv.Precompute()
 	pk.PrivateKey = rsaPriv
 	pk.Encrypted = false
 	pk.encryptedData = nil
diff --git a/src/pkg/crypto/openpgp/packet/public_key.go b/src/pkg/crypto/openpgp/packet/public_key.go
index ebef481..cd4a9ae 100644
--- a/src/pkg/crypto/openpgp/packet/public_key.go
+++ b/src/pkg/crypto/openpgp/packet/public_key.go
@@ -15,6 +15,7 @@ import (
 	"hash"
 	"io"
 	"os"
+	"strconv"
 )
 
 // PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2.
@@ -47,7 +48,7 @@ func (pk *PublicKey) parse(r io.Reader) (err os.Error) {
 	case PubKeyAlgoDSA:
 		err = pk.parseDSA(r)
 	default:
-		err = error.UnsupportedError("public key type")
+		err = error.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
 	}
 	if err != nil {
 		return
diff --git a/src/pkg/crypto/openpgp/read.go b/src/pkg/crypto/openpgp/read.go
index ac6998f..4f84dff 100644
--- a/src/pkg/crypto/openpgp/read.go
+++ b/src/pkg/crypto/openpgp/read.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This openpgp package implements high level operations on OpenPGP messages.
+// Package openpgp implements high level operations on OpenPGP messages.
 package openpgp
 
 import (
diff --git a/src/pkg/crypto/openpgp/read_test.go b/src/pkg/crypto/openpgp/read_test.go
index 6218d99..423c85b 100644
--- a/src/pkg/crypto/openpgp/read_test.go
+++ b/src/pkg/crypto/openpgp/read_test.go
@@ -230,6 +230,23 @@ func TestDetachedSignatureDSA(t *testing.T) {
 	testDetachedSignature(t, kring, readerFromHex(detachedSignatureDSAHex), signedInput, "binary", testKey3KeyId)
 }
 
+func TestReadingArmoredPrivateKey(t *testing.T) {
+	el, err := ReadArmoredKeyRing(bytes.NewBufferString(armoredPrivateKeyBlock))
+	if err != nil {
+		t.Error(err)
+	}
+	if len(el) != 1 {
+		t.Errorf("got %d entities, wanted 1\n", len(el))
+	}
+}
+
+func TestNoArmoredData(t *testing.T) {
+	_, err := ReadArmoredKeyRing(bytes.NewBufferString("foo"))
+	if _, ok := err.(error.InvalidArgumentError); !ok {
+		t.Errorf("error was not an InvalidArgumentError: %s", err)
+	}
+}
+
 const testKey1KeyId = 0xA34D7E18C20C31BB
 const testKey3KeyId = 0x338934250CCC0360
 
@@ -259,3 +276,37 @@ const symmetricallyEncryptedCompressedHex = "8c0d04030302eb4a03808145d0d260c92f7
 const dsaTestKeyHex = "9901a2044d6c49de110400cb5ce438cf9250907ac2ba5bf6547931270b89f7c4b53d9d09f4d0213a5ef2ec1f26806d3d259960f872a4a102ef1581ea3f6d6882d15134f21ef6a84de933cc34c47cc9106efe3bd84c6aec12e78523661e29bc1a61f0aab17fa58a627fd5fd33f5149153fbe8cd70edf3d963bc287ef875270ff14b5bfdd1bca4483793923b00a0fe46d76cb6e4cbdc568435cd5480af3266d610d303fe33ae8273f30a96d4d34f42fa28ce1112d425b2e3bf7ea553d526e2db6b9255e9dc7419045ce817214d1a0056dbc8d5289956a4b1b69f20f1105124096e6a438f41f2e2495923b0f34b70642607d45559595c7fe94d7fa85fc41bf7d68c1fd509ebeaa5f315f6059a446b9369c277597e4f474a9591535354c7e7f4fd98a08aa60400b130c24ff20bdfbf683313f5daebf1c9b34b3bdadfc77f2ddd72ee1fb17e56c473664bc21d66467655dd74b9005e3a2bacce446f1920cd7017231ae447b67036c9b431b8179deacd5120262d894c26bc015bffe3d827ba7087ad9b700d2ca1f6d16cc1786581e5dd065f293c31209300f9b0afcc3f7c08dd26d0a22d87580b4db41054657374204b65792033202844534129886204131102002205024d6c49de021b03060b090807030206150802090a0b0416020301021e01021780000a0910338934250ccc03607e0400a0bdb9193e8a6b96fc2dfc108ae848914b504481f100a09c4dc148cb693293a67af24dd40d2b13a9e36794"
 
 const dsaTestKeyPrivateHex = "9501bb044d6c49de110400cb5ce438cf9250907ac2ba5bf6547931270b89f7c4b53d9d09f4d0213a5ef2ec1f26806d3d259960f872a4a102ef1581ea3f6d6882d15134f21ef6a84de933cc34c47cc9106efe3bd84c6aec12e78523661e29bc1a61f0aab17fa58a627fd5fd33f5149153fbe8cd70edf3d963bc287ef875270ff14b5bfdd1bca4483793923b00a0fe46d76cb6e4cbdc568435cd5480af3266d610d303fe33ae8273f30a96d4d34f42fa28ce1112d425b2e3bf7ea553d526e2db6b9255e9dc7419045ce817214d1a0056dbc8d5289956a4b1b69f20f1105124096e6a438f41f2e2495923b0f34b70642607d45559595c7fe94d7fa85fc41bf7d68c1fd509ebeaa5f315f6059a446b9369c277597e4f474a9591535354c7e7f4fd98a08aa60400b130c24ff20bdfbf683313f5daebf1c9b34b3bdadfc77f2ddd72ee1fb17e56c473664bc21d66467655dd74b9005e3a2bacce446f1920cd7017231ae447b67036c9b431b8179deacd5120262d894c26bc015bffe3d827ba7087ad9b700d2ca1f6d16cc1786581e5dd065f293c31209300f9b0afcc3f7c08dd26d0a22d87580b4d00009f592e0619d823953577d4503061706843317e4fee083db41054657374204b65792033202844534129886204131102002205024d6c49de021b03060b090807030206150802090a0b0416020301021e01021780000a0910338934250ccc03607e0400a0bdb9193e8a6b96fc2dfc108ae848914b504481f100a09c4dc148cb693293a67af24dd40d2b13a9e36794"
+
+const armoredPrivateKeyBlock = `-----BEGIN PGP PRIVATE KEY BLOCK-----
+Version: GnuPG v1.4.10 (GNU/Linux)
+
+lQHYBE2rFNoBBADFwqWQIW/DSqcB4yCQqnAFTJ27qS5AnB46ccAdw3u4Greeu3Bp
+idpoHdjULy7zSKlwR1EA873dO/k/e11Ml3dlAFUinWeejWaK2ugFP6JjiieSsrKn
+vWNicdCS4HTWn0X4sjl0ZiAygw6GNhqEQ3cpLeL0g8E9hnYzJKQ0LWJa0QARAQAB
+AAP/TB81EIo2VYNmTq0pK1ZXwUpxCrvAAIG3hwKjEzHcbQznsjNvPUihZ+NZQ6+X
+0HCfPAdPkGDCLCb6NavcSW+iNnLTrdDnSI6+3BbIONqWWdRDYJhqZCkqmG6zqSfL
+IdkJgCw94taUg5BWP/AAeQrhzjChvpMQTVKQL5mnuZbUCeMCAN5qrYMP2S9iKdnk
+VANIFj7656ARKt/nf4CBzxcpHTyB8+d2CtPDKCmlJP6vL8t58Jmih+kHJMvC0dzn
+gr5f5+sCAOOe5gt9e0am7AvQWhdbHVfJU0TQJx+m2OiCJAqGTB1nvtBLHdJnfdC9
+TnXXQ6ZXibqLyBies/xeY2sCKL5qtTMCAKnX9+9d/5yQxRyrQUHt1NYhaXZnJbHx
+q4ytu0eWz+5i68IYUSK69jJ1NWPM0T6SkqpB3KCAIv68VFm9PxqG1KmhSrQIVGVz
+dCBLZXmIuAQTAQIAIgUCTasU2gIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA
+CgkQO9o98PRieSoLhgQAkLEZex02Qt7vGhZzMwuN0R22w3VwyYyjBx+fM3JFETy1
+ut4xcLJoJfIaF5ZS38UplgakHG0FQ+b49i8dMij0aZmDqGxrew1m4kBfjXw9B/v+
+eIqpODryb6cOSwyQFH0lQkXC040pjq9YqDsO5w0WYNXYKDnzRV0p4H1pweo2VDid
+AdgETasU2gEEAN46UPeWRqKHvA99arOxee38fBt2CI08iiWyI8T3J6ivtFGixSqV
+bRcPxYO/qLpVe5l84Nb3X71GfVXlc9hyv7CD6tcowL59hg1E/DC5ydI8K8iEpUmK
+/UnHdIY5h8/kqgGxkY/T/hgp5fRQgW1ZoZxLajVlMRZ8W4tFtT0DeA+JABEBAAEA
+A/0bE1jaaZKj6ndqcw86jd+QtD1SF+Cf21CWRNeLKnUds4FRRvclzTyUMuWPkUeX
+TaNNsUOFqBsf6QQ2oHUBBK4VCHffHCW4ZEX2cd6umz7mpHW6XzN4DECEzOVksXtc
+lUC1j4UB91DC/RNQqwX1IV2QLSwssVotPMPqhOi0ZLNY7wIA3n7DWKInxYZZ4K+6
+rQ+POsz6brEoRHwr8x6XlHenq1Oki855pSa1yXIARoTrSJkBtn5oI+f8AzrnN0BN
+oyeQAwIA/7E++3HDi5aweWrViiul9cd3rcsS0dEnksPhvS0ozCJiHsq/6GFmy7J8
+QSHZPteedBnZyNp5jR+H7cIfVN3KgwH/Skq4PsuPhDq5TKK6i8Pc1WW8MA6DXTdU
+nLkX7RGmMwjC0DBf7KWAlPjFaONAX3a8ndnz//fy1q7u2l9AZwrj1qa1iJ8EGAEC
+AAkFAk2rFNoCGwwACgkQO9o98PRieSo2/QP/WTzr4ioINVsvN1akKuekmEMI3LAp
+BfHwatufxxP1U+3Si/6YIk7kuPB9Hs+pRqCXzbvPRrI8NHZBmc8qIGthishdCYad
+AHcVnXjtxrULkQFGbGvhKURLvS9WnzD/m1K2zzwxzkPTzT9/Yf06O6Mal5AdugPL
+VrM0m72/jnpKo04=
+=zNCn
+-----END PGP PRIVATE KEY BLOCK-----`
diff --git a/src/pkg/crypto/openpgp/s2k/s2k.go b/src/pkg/crypto/openpgp/s2k/s2k.go
index 873b33d..93b7582 100644
--- a/src/pkg/crypto/openpgp/s2k/s2k.go
+++ b/src/pkg/crypto/openpgp/s2k/s2k.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package implements the various OpenPGP string-to-key transforms as
+// Package s2k implements the various OpenPGP string-to-key transforms as
 // specified in RFC 4800 section 3.7.1.
 package s2k
 
diff --git a/src/pkg/crypto/rc4/rc4.go b/src/pkg/crypto/rc4/rc4.go
index 65fd195..7ee4710 100644
--- a/src/pkg/crypto/rc4/rc4.go
+++ b/src/pkg/crypto/rc4/rc4.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package implements RC4 encryption, as defined in Bruce Schneier's
+// Package rc4 implements RC4 encryption, as defined in Bruce Schneier's
 // Applied Cryptography.
 package rc4
 
diff --git a/src/pkg/crypto/ripemd160/ripemd160.go b/src/pkg/crypto/ripemd160/ripemd160.go
index 6e88521..5aaca59 100644
--- a/src/pkg/crypto/ripemd160/ripemd160.go
+++ b/src/pkg/crypto/ripemd160/ripemd160.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package implements the RIPEMD-160 hash algorithm.
+// Package ripemd160 implements the RIPEMD-160 hash algorithm.
 package ripemd160
 
 // RIPEMD-160 is designed by by Hans Dobbertin, Antoon Bosselaers, and Bart
diff --git a/src/pkg/crypto/rsa/pkcs1v15_test.go b/src/pkg/crypto/rsa/pkcs1v15_test.go
index 30a4824..d69bacf 100644
--- a/src/pkg/crypto/rsa/pkcs1v15_test.go
+++ b/src/pkg/crypto/rsa/pkcs1v15_test.go
@@ -197,12 +197,6 @@ func TestVerifyPKCS1v15(t *testing.T) {
 	}
 }
 
-func bigFromString(s string) *big.Int {
-	ret := new(big.Int)
-	ret.SetString(s, 10)
-	return ret
-}
-
 // In order to generate new test vectors you'll need the PEM form of this key:
 // -----BEGIN RSA PRIVATE KEY-----
 // MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0
@@ -216,10 +210,12 @@ func bigFromString(s string) *big.Int {
 
 var rsaPrivateKey = &PrivateKey{
 	PublicKey: PublicKey{
-		N: bigFromString("9353930466774385905609975137998169297361893554149986716853295022578535724979677252958524466350471210367835187480748268864277464700638583474144061408845077"),
+		N: fromBase10("9353930466774385905609975137998169297361893554149986716853295022578535724979677252958524466350471210367835187480748268864277464700638583474144061408845077"),
 		E: 65537,
 	},
-	D: bigFromString("7266398431328116344057699379749222532279343923819063639497049039389899328538543087657733766554155839834519529439851673014800261285757759040931985506583861"),
-	P: bigFromString("98920366548084643601728869055592650835572950932266967461790948584315647051443"),
-	Q: bigFromString("94560208308847015747498523884063394671606671904944666360068158221458669711639"),
+	D: fromBase10("7266398431328116344057699379749222532279343923819063639497049039389899328538543087657733766554155839834519529439851673014800261285757759040931985506583861"),
+	Primes: []*big.Int{
+		fromBase10("98920366548084643601728869055592650835572950932266967461790948584315647051443"),
+		fromBase10("94560208308847015747498523884063394671606671904944666360068158221458669711639"),
+	},
 }
diff --git a/src/pkg/crypto/rsa/rsa.go b/src/pkg/crypto/rsa/rsa.go
index b3b212c..e1813db 100644
--- a/src/pkg/crypto/rsa/rsa.go
+++ b/src/pkg/crypto/rsa/rsa.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package implements RSA encryption as specified in PKCS#1.
+// Package rsa implements RSA encryption as specified in PKCS#1.
 package rsa
 
 // TODO(agl): Add support for PSS padding.
@@ -13,7 +13,6 @@ import (
 	"hash"
 	"io"
 	"os"
-	"sync"
 )
 
 var bigZero = big.NewInt(0)
@@ -90,50 +89,60 @@ type PublicKey struct {
 
 // A PrivateKey represents an RSA key
 type PrivateKey struct {
-	PublicKey          // public part.
-	D         *big.Int // private exponent
-	P, Q, R   *big.Int // prime factors of N (R may be nil)
-
-	rwMutex    sync.RWMutex // protects the following
-	dP, dQ, dR *big.Int     // D mod (P-1) (or mod Q-1 etc) 
-	qInv       *big.Int     // q^-1 mod p
-	pq         *big.Int     // P*Q
-	tr         *big.Int     // pq·tr ≡ 1 mod r
+	PublicKey            // public part.
+	D         *big.Int   // private exponent
+	Primes    []*big.Int // prime factors of N, has >= 2 elements.
+
+	// Precomputed contains precomputed values that speed up private
+	// operations, if availible.
+	Precomputed PrecomputedValues
+}
+
+type PrecomputedValues struct {
+	Dp, Dq *big.Int // D mod (P-1) (or mod Q-1) 
+	Qinv   *big.Int // Q^-1 mod Q
+
+	// CRTValues is used for the 3rd and subsequent primes. Due to a
+	// historical accident, the CRT for the first two primes is handled
+	// differently in PKCS#1 and interoperability is sufficiently
+	// important that we mirror this.
+	CRTValues []CRTValue
+}
+
+// CRTValue contains the precomputed chinese remainder theorem values.
+type CRTValue struct {
+	Exp   *big.Int // D mod (prime-1).
+	Coeff *big.Int // R·Coeff ≡ 1 mod Prime.
+	R     *big.Int // product of primes prior to this (inc p and q).
 }
 
 // Validate performs basic sanity checks on the key.
 // It returns nil if the key is valid, or else an os.Error describing a problem.
 
 func (priv *PrivateKey) Validate() os.Error {
-	// Check that p, q and, maybe, r are prime. Note that this is just a
-	// sanity check. Since the random witnesses chosen by ProbablyPrime are
-	// deterministic, given the candidate number, it's easy for an attack
-	// to generate composites that pass this test.
-	if !big.ProbablyPrime(priv.P, 20) {
-		return os.ErrorString("P is composite")
-	}
-	if !big.ProbablyPrime(priv.Q, 20) {
-		return os.ErrorString("Q is composite")
-	}
-	if priv.R != nil && !big.ProbablyPrime(priv.R, 20) {
-		return os.ErrorString("R is composite")
+	// Check that the prime factors are actually prime. Note that this is
+	// just a sanity check. Since the random witnesses chosen by
+	// ProbablyPrime are deterministic, given the candidate number, it's
+	// easy for an attack to generate composites that pass this test.
+	for _, prime := range priv.Primes {
+		if !big.ProbablyPrime(prime, 20) {
+			return os.ErrorString("Prime factor is composite")
+		}
 	}
 
-	// Check that p*q*r == n.
-	modulus := new(big.Int).Mul(priv.P, priv.Q)
-	if priv.R != nil {
-		modulus.Mul(modulus, priv.R)
+	// Check that Πprimes == n.
+	modulus := new(big.Int).Set(bigOne)
+	for _, prime := range priv.Primes {
+		modulus.Mul(modulus, prime)
 	}
 	if modulus.Cmp(priv.N) != 0 {
 		return os.ErrorString("invalid modulus")
 	}
-	// Check that e and totient(p, q, r) are coprime.
-	pminus1 := new(big.Int).Sub(priv.P, bigOne)
-	qminus1 := new(big.Int).Sub(priv.Q, bigOne)
-	totient := new(big.Int).Mul(pminus1, qminus1)
-	if priv.R != nil {
-		rminus1 := new(big.Int).Sub(priv.R, bigOne)
-		totient.Mul(totient, rminus1)
+	// Check that e and totient(Πprimes) are coprime.
+	totient := new(big.Int).Set(bigOne)
+	for _, prime := range priv.Primes {
+		pminus1 := new(big.Int).Sub(prime, bigOne)
+		totient.Mul(totient, pminus1)
 	}
 	e := big.NewInt(int64(priv.E))
 	gcd := new(big.Int)
@@ -143,7 +152,7 @@ func (priv *PrivateKey) Validate() os.Error {
 	if gcd.Cmp(bigOne) != 0 {
 		return os.ErrorString("invalid public exponent E")
 	}
-	// Check that de ≡ 1 (mod totient(p, q, r))
+	// Check that de ≡ 1 (mod totient(Πprimes))
 	de := new(big.Int).Mul(priv.D, e)
 	de.Mod(de, totient)
 	if de.Cmp(bigOne) != 0 {
@@ -154,6 +163,20 @@ func (priv *PrivateKey) Validate() os.Error {
 
 // GenerateKey generates an RSA keypair of the given bit size.
 func GenerateKey(rand io.Reader, bits int) (priv *PrivateKey, err os.Error) {
+	return GenerateMultiPrimeKey(rand, 2, bits)
+}
+
+// GenerateMultiPrimeKey generates a multi-prime RSA keypair of the given bit
+// size, as suggested in [1]. Although the public keys are compatible
+// (actually, indistinguishable) from the 2-prime case, the private keys are
+// not. Thus it may not be possible to export multi-prime private keys in
+// certain formats or to subsequently import them into other code.
+//
+// Table 1 in [2] suggests maximum numbers of primes for a given size.
+//
+// [1] US patent 4405829 (1972, expired)
+// [2] http://www.cacr.math.uwaterloo.ca/techreports/2006/cacr2006-16.pdf
+func GenerateMultiPrimeKey(rand io.Reader, nprimes int, bits int) (priv *PrivateKey, err os.Error) {
 	priv = new(PrivateKey)
 	// Smaller public exponents lead to faster public key
 	// operations. Since the exponent must be coprime to
@@ -165,100 +188,41 @@ func GenerateKey(rand io.Reader, bits int) (priv *PrivateKey, err os.Error) {
 	// [1] http://marc.info/?l=cryptography&m=115694833312008&w=2
 	priv.E = 3
 
-	pminus1 := new(big.Int)
-	qminus1 := new(big.Int)
-	totient := new(big.Int)
-
-	for {
-		p, err := randomPrime(rand, bits/2)
-		if err != nil {
-			return nil, err
-		}
-
-		q, err := randomPrime(rand, bits/2)
-		if err != nil {
-			return nil, err
-		}
-
-		if p.Cmp(q) == 0 {
-			continue
-		}
-
-		n := new(big.Int).Mul(p, q)
-		pminus1.Sub(p, bigOne)
-		qminus1.Sub(q, bigOne)
-		totient.Mul(pminus1, qminus1)
-
-		g := new(big.Int)
-		priv.D = new(big.Int)
-		y := new(big.Int)
-		e := big.NewInt(int64(priv.E))
-		big.GcdInt(g, priv.D, y, e, totient)
-
-		if g.Cmp(bigOne) == 0 {
-			priv.D.Add(priv.D, totient)
-			priv.P = p
-			priv.Q = q
-			priv.N = n
-
-			break
-		}
+	if nprimes < 2 {
+		return nil, os.ErrorString("rsa.GenerateMultiPrimeKey: nprimes must be >= 2")
 	}
 
-	return
-}
-
-// Generate3PrimeKey generates a 3-prime RSA keypair of the given bit size, as
-// suggested in [1]. Although the public keys are compatible (actually,
-// indistinguishable) from the 2-prime case, the private keys are not. Thus it
-// may not be possible to export 3-prime private keys in certain formats or to
-// subsequently import them into other code.
-//
-// Table 1 in [2] suggests that size should be >= 1024 when using 3 primes.
-//
-// [1] US patent 4405829 (1972, expired)
-// [2] http://www.cacr.math.uwaterloo.ca/techreports/2006/cacr2006-16.pdf
-func Generate3PrimeKey(rand io.Reader, bits int) (priv *PrivateKey, err os.Error) {
-	priv = new(PrivateKey)
-	priv.E = 3
-
-	pminus1 := new(big.Int)
-	qminus1 := new(big.Int)
-	rminus1 := new(big.Int)
-	totient := new(big.Int)
+	primes := make([]*big.Int, nprimes)
 
+NextSetOfPrimes:
 	for {
-		p, err := randomPrime(rand, bits/3)
-		if err != nil {
-			return nil, err
-		}
-
-		todo := bits - p.BitLen()
-		q, err := randomPrime(rand, todo/2)
-		if err != nil {
-			return nil, err
+		todo := bits
+		for i := 0; i < nprimes; i++ {
+			primes[i], err = randomPrime(rand, todo/(nprimes-i))
+			if err != nil {
+				return nil, err
+			}
+			todo -= primes[i].BitLen()
 		}
 
-		todo -= q.BitLen()
-		r, err := randomPrime(rand, todo)
-		if err != nil {
-			return nil, err
+		// Make sure that primes is pairwise unequal.
+		for i, prime := range primes {
+			for j := 0; j < i; j++ {
+				if prime.Cmp(primes[j]) == 0 {
+					continue NextSetOfPrimes
+				}
+			}
 		}
 
-		if p.Cmp(q) == 0 ||
-			q.Cmp(r) == 0 ||
-			r.Cmp(p) == 0 {
-			continue
+		n := new(big.Int).Set(bigOne)
+		totient := new(big.Int).Set(bigOne)
+		pminus1 := new(big.Int)
+		for _, prime := range primes {
+			n.Mul(n, prime)
+			pminus1.Sub(prime, bigOne)
+			totient.Mul(totient, pminus1)
 		}
 
-		n := new(big.Int).Mul(p, q)
-		n.Mul(n, r)
-		pminus1.Sub(p, bigOne)
-		qminus1.Sub(q, bigOne)
-		rminus1.Sub(r, bigOne)
-		totient.Mul(pminus1, qminus1)
-		totient.Mul(totient, rminus1)
-
 		g := new(big.Int)
 		priv.D = new(big.Int)
 		y := new(big.Int)
@@ -267,15 +231,14 @@ func Generate3PrimeKey(rand io.Reader, bits int) (priv *PrivateKey, err os.Error
 
 		if g.Cmp(bigOne) == 0 {
 			priv.D.Add(priv.D, totient)
-			priv.P = p
-			priv.Q = q
-			priv.R = r
+			priv.Primes = primes
 			priv.N = n
 
 			break
 		}
 	}
 
+	priv.Precompute()
 	return
 }
 
@@ -409,23 +372,34 @@ func modInverse(a, n *big.Int) (ia *big.Int, ok bool) {
 	return x, true
 }
 
-// precompute performs some calculations that speed up private key operations
+// Precompute performs some calculations that speed up private key operations
 // in the future.
-func (priv *PrivateKey) precompute() {
-	priv.dP = new(big.Int).Sub(priv.P, bigOne)
-	priv.dP.Mod(priv.D, priv.dP)
+func (priv *PrivateKey) Precompute() {
+	if priv.Precomputed.Dp != nil {
+		return
+	}
 
-	priv.dQ = new(big.Int).Sub(priv.Q, bigOne)
-	priv.dQ.Mod(priv.D, priv.dQ)
+	priv.Precomputed.Dp = new(big.Int).Sub(priv.Primes[0], bigOne)
+	priv.Precomputed.Dp.Mod(priv.D, priv.Precomputed.Dp)
 
-	priv.qInv = new(big.Int).ModInverse(priv.Q, priv.P)
+	priv.Precomputed.Dq = new(big.Int).Sub(priv.Primes[1], bigOne)
+	priv.Precomputed.Dq.Mod(priv.D, priv.Precomputed.Dq)
 
-	if priv.R != nil {
-		priv.dR = new(big.Int).Sub(priv.R, bigOne)
-		priv.dR.Mod(priv.D, priv.dR)
+	priv.Precomputed.Qinv = new(big.Int).ModInverse(priv.Primes[1], priv.Primes[0])
 
-		priv.pq = new(big.Int).Mul(priv.P, priv.Q)
-		priv.tr = new(big.Int).ModInverse(priv.pq, priv.R)
+	r := new(big.Int).Mul(priv.Primes[0], priv.Primes[1])
+	priv.Precomputed.CRTValues = make([]CRTValue, len(priv.Primes)-2)
+	for i := 2; i < len(priv.Primes); i++ {
+		prime := priv.Primes[i]
+		values := &priv.Precomputed.CRTValues[i-2]
+
+		values.Exp = new(big.Int).Sub(prime, bigOne)
+		values.Exp.Mod(priv.D, values.Exp)
+
+		values.R = new(big.Int).Set(r)
+		values.Coeff = new(big.Int).ModInverse(r, prime)
+
+		r.Mul(r, prime)
 	}
 }
 
@@ -463,53 +437,41 @@ func decrypt(rand io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err os.E
 		}
 		bigE := big.NewInt(int64(priv.E))
 		rpowe := new(big.Int).Exp(r, bigE, priv.N)
-		c.Mul(c, rpowe)
-		c.Mod(c, priv.N)
-	}
-
-	priv.rwMutex.RLock()
-
-	if priv.dP == nil && priv.P != nil {
-		priv.rwMutex.RUnlock()
-		priv.rwMutex.Lock()
-		if priv.dP == nil && priv.P != nil {
-			priv.precompute()
-		}
-		priv.rwMutex.Unlock()
-		priv.rwMutex.RLock()
+		cCopy := new(big.Int).Set(c)
+		cCopy.Mul(cCopy, rpowe)
+		cCopy.Mod(cCopy, priv.N)
+		c = cCopy
 	}
 
-	if priv.dP == nil {
+	if priv.Precomputed.Dp == nil {
 		m = new(big.Int).Exp(c, priv.D, priv.N)
 	} else {
 		// We have the precalculated values needed for the CRT.
-		m = new(big.Int).Exp(c, priv.dP, priv.P)
-		m2 := new(big.Int).Exp(c, priv.dQ, priv.Q)
+		m = new(big.Int).Exp(c, priv.Precomputed.Dp, priv.Primes[0])
+		m2 := new(big.Int).Exp(c, priv.Precomputed.Dq, priv.Primes[1])
 		m.Sub(m, m2)
 		if m.Sign() < 0 {
-			m.Add(m, priv.P)
+			m.Add(m, priv.Primes[0])
 		}
-		m.Mul(m, priv.qInv)
-		m.Mod(m, priv.P)
-		m.Mul(m, priv.Q)
+		m.Mul(m, priv.Precomputed.Qinv)
+		m.Mod(m, priv.Primes[0])
+		m.Mul(m, priv.Primes[1])
 		m.Add(m, m2)
 
-		if priv.dR != nil {
-			// 3-prime CRT.
-			m2.Exp(c, priv.dR, priv.R)
+		for i, values := range priv.Precomputed.CRTValues {
+			prime := priv.Primes[2+i]
+			m2.Exp(c, values.Exp, prime)
 			m2.Sub(m2, m)
-			m2.Mul(m2, priv.tr)
-			m2.Mod(m2, priv.R)
+			m2.Mul(m2, values.Coeff)
+			m2.Mod(m2, prime)
 			if m2.Sign() < 0 {
-				m2.Add(m2, priv.R)
+				m2.Add(m2, prime)
 			}
-			m2.Mul(m2, priv.pq)
+			m2.Mul(m2, values.R)
 			m.Add(m, m2)
 		}
 	}
 
-	priv.rwMutex.RUnlock()
-
 	if ir != nil {
 		// Unblind.
 		m.Mul(m, ir)
diff --git a/src/pkg/crypto/rsa/rsa_test.go b/src/pkg/crypto/rsa/rsa_test.go
index d8a936e..c36bca1 100644
--- a/src/pkg/crypto/rsa/rsa_test.go
+++ b/src/pkg/crypto/rsa/rsa_test.go
@@ -30,7 +30,20 @@ func Test3PrimeKeyGeneration(t *testing.T) {
 	}
 
 	size := 768
-	priv, err := Generate3PrimeKey(rand.Reader, size)
+	priv, err := GenerateMultiPrimeKey(rand.Reader, 3, size)
+	if err != nil {
+		t.Errorf("failed to generate key")
+	}
+	testKeyBasics(t, priv)
+}
+
+func Test4PrimeKeyGeneration(t *testing.T) {
+	if testing.Short() {
+		return
+	}
+
+	size := 768
+	priv, err := GenerateMultiPrimeKey(rand.Reader, 4, size)
 	if err != nil {
 		t.Errorf("failed to generate key")
 	}
@@ -45,6 +58,7 @@ func testKeyBasics(t *testing.T, priv *PrivateKey) {
 	pub := &priv.PublicKey
 	m := big.NewInt(42)
 	c := encrypt(new(big.Int), pub, m)
+
 	m2, err := decrypt(nil, priv, c)
 	if err != nil {
 		t.Errorf("error while decrypting: %s", err)
@@ -59,7 +73,7 @@ func testKeyBasics(t *testing.T, priv *PrivateKey) {
 		t.Errorf("error while decrypting (blind): %s", err)
 	}
 	if m.Cmp(m3) != 0 {
-		t.Errorf("(blind) got:%v, want:%v", m3, m)
+		t.Errorf("(blind) got:%v, want:%v (%#v)", m3, m, priv)
 	}
 }
 
@@ -77,10 +91,12 @@ func BenchmarkRSA2048Decrypt(b *testing.B) {
 			E: 3,
 		},
 		D: fromBase10("9542755287494004433998723259516013739278699355114572217325597900889416163458809501304132487555642811888150937392013824621448709836142886006653296025093941418628992648429798282127303704957273845127141852309016655778568546006839666463451542076964744073572349705538631742281931858219480985907271975884773482372966847639853897890615456605598071088189838676728836833012254065983259638538107719766738032720239892094196108713378822882383694456030043492571063441943847195939549773271694647657549658603365629458610273821292232646334717612674519997533901052790334279661754176490593041941863932308687197618671528035670452762731"),
-		P: fromBase10("130903255182996722426771613606077755295583329135067340152947172868415809027537376306193179624298874215608270802054347609836776473930072411958753044562214537013874103802006369634761074377213995983876788718033850153719421695468704276694983032644416930879093914927146648402139231293035971427838068945045019075433"),
-		Q: fromBase10("109348945610485453577574767652527472924289229538286649661240938988020367005475727988253438647560958573506159449538793540472829815903949343191091817779240101054552748665267574271163617694640513549693841337820602726596756351006149518830932261246698766355347898158548465400674856021497190430791824869615170301029"),
+		Primes: []*big.Int{
+			fromBase10("130903255182996722426771613606077755295583329135067340152947172868415809027537376306193179624298874215608270802054347609836776473930072411958753044562214537013874103802006369634761074377213995983876788718033850153719421695468704276694983032644416930879093914927146648402139231293035971427838068945045019075433"),
+			fromBase10("109348945610485453577574767652527472924289229538286649661240938988020367005475727988253438647560958573506159449538793540472829815903949343191091817779240101054552748665267574271163617694640513549693841337820602726596756351006149518830932261246698766355347898158548465400674856021497190430791824869615170301029"),
+		},
 	}
-	priv.precompute()
+	priv.Precompute()
 
 	c := fromBase10("1000")
 
@@ -99,11 +115,13 @@ func Benchmark3PrimeRSA2048Decrypt(b *testing.B) {
 			E: 3,
 		},
 		D: fromBase10("10897585948254795600358846499957366070880176878341177571733155050184921896034527397712889205732614568234385175145686545381899460748279607074689061600935843283397424506622998458510302603922766336783617368686090042765718290914099334449154829375179958369993407724946186243249568928237086215759259909861748642124071874879861299389874230489928271621259294894142840428407196932444474088857746123104978617098858619445675532587787023228852383149557470077802718705420275739737958953794088728369933811184572620857678792001136676902250566845618813972833750098806496641114644760255910789397593428910198080271317419213080834885003"),
-		P: fromBase10("1025363189502892836833747188838978207017355117492483312747347695538428729137306368764177201532277413433182799108299960196606011786562992097313508180436744488171474690412562218914213688661311117337381958560443"),
-		Q: fromBase10("3467903426626310123395340254094941045497208049900750380025518552334536945536837294961497712862519984786362199788654739924501424784631315081391467293694361474867825728031147665777546570788493758372218019373"),
-		R: fromBase10("4597024781409332673052708605078359346966325141767460991205742124888960305710298765592730135879076084498363772408626791576005136245060321874472727132746643162385746062759369754202494417496879741537284589047"),
+		Primes: []*big.Int{
+			fromBase10("1025363189502892836833747188838978207017355117492483312747347695538428729137306368764177201532277413433182799108299960196606011786562992097313508180436744488171474690412562218914213688661311117337381958560443"),
+			fromBase10("3467903426626310123395340254094941045497208049900750380025518552334536945536837294961497712862519984786362199788654739924501424784631315081391467293694361474867825728031147665777546570788493758372218019373"),
+			fromBase10("4597024781409332673052708605078359346966325141767460991205742124888960305710298765592730135879076084498363772408626791576005136245060321874472727132746643162385746062759369754202494417496879741537284589047"),
+		},
 	}
-	priv.precompute()
+	priv.Precompute()
 
 	c := fromBase10("1000")
 
diff --git a/src/pkg/crypto/sha1/sha1.go b/src/pkg/crypto/sha1/sha1.go
index e6aa096..788d1ff 100644
--- a/src/pkg/crypto/sha1/sha1.go
+++ b/src/pkg/crypto/sha1/sha1.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package implements the SHA1 hash algorithm as defined in RFC 3174.
+// Package sha1 implements the SHA1 hash algorithm as defined in RFC 3174.
 package sha1
 
 import (
diff --git a/src/pkg/crypto/sha256/sha256.go b/src/pkg/crypto/sha256/sha256.go
index 69b356b..a2c058d 100644
--- a/src/pkg/crypto/sha256/sha256.go
+++ b/src/pkg/crypto/sha256/sha256.go
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package implements the SHA224 and SHA256 hash algorithms as defined in FIPS 180-2.
+// Package sha256 implements the SHA224 and SHA256 hash algorithms as defined
+// in FIPS 180-2.
 package sha256
 
 import (
diff --git a/src/pkg/crypto/sha512/sha512.go b/src/pkg/crypto/sha512/sha512.go
index 7e9f330..78f5fe2 100644
--- a/src/pkg/crypto/sha512/sha512.go
+++ b/src/pkg/crypto/sha512/sha512.go
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package implements the SHA384 and SHA512 hash algorithms as defined in FIPS 180-2.
+// Package sha512 implements the SHA384 and SHA512 hash algorithms as defined
+// in FIPS 180-2.
 package sha512
 
 import (
diff --git a/src/pkg/crypto/subtle/constant_time.go b/src/pkg/crypto/subtle/constant_time.go
index a3d70b9..57dbe9d 100644
--- a/src/pkg/crypto/subtle/constant_time.go
+++ b/src/pkg/crypto/subtle/constant_time.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package implements functions that are often useful in cryptographic
+// Package subtle implements functions that are often useful in cryptographic
 // code but require careful thought to use correctly.
 package subtle
 
diff --git a/src/pkg/crypto/tls/Makefile b/src/pkg/crypto/tls/Makefile
index f8ec151..000314b 100644
--- a/src/pkg/crypto/tls/Makefile
+++ b/src/pkg/crypto/tls/Makefile
@@ -7,7 +7,6 @@ include ../../../Make.inc
 TARG=crypto/tls
 GOFILES=\
 	alert.go\
-	ca_set.go\
 	cipher_suites.go\
 	common.go\
 	conn.go\
diff --git a/src/pkg/crypto/tls/ca_set.go b/src/pkg/crypto/tls/ca_set.go
deleted file mode 100644
index ae00ac5..0000000
--- a/src/pkg/crypto/tls/ca_set.go
+++ /dev/null
@@ -1,89 +0,0 @@
-// 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.
-
-package tls
-
-import (
-	"crypto/x509"
-	"encoding/pem"
-	"strings"
-)
-
-// A CASet is a set of certificates.
-type CASet struct {
-	bySubjectKeyId map[string][]*x509.Certificate
-	byName         map[string][]*x509.Certificate
-}
-
-// NewCASet returns a new, empty CASet.
-func NewCASet() *CASet {
-	return &CASet{
-		make(map[string][]*x509.Certificate),
-		make(map[string][]*x509.Certificate),
-	}
-}
-
-func nameToKey(name *x509.Name) string {
-	return strings.Join(name.Country, ",") + "/" + strings.Join(name.Organization, ",") + "/" + strings.Join(name.OrganizationalUnit, ",") + "/" + name.CommonName
-}
-
-// FindVerifiedParent attempts to find the certificate in s which has signed
-// the given certificate. If no such certificate can be found or the signature
-// doesn't match, it returns nil.
-func (s *CASet) FindVerifiedParent(cert *x509.Certificate) (parent *x509.Certificate) {
-	var candidates []*x509.Certificate
-
-	if len(cert.AuthorityKeyId) > 0 {
-		candidates = s.bySubjectKeyId[string(cert.AuthorityKeyId)]
-	}
-	if len(candidates) == 0 {
-		candidates = s.byName[nameToKey(&cert.Issuer)]
-	}
-
-	for _, c := range candidates {
-		if cert.CheckSignatureFrom(c) == nil {
-			return c
-		}
-	}
-
-	return nil
-}
-
-// AddCert adds a certificate to the set
-func (s *CASet) AddCert(cert *x509.Certificate) {
-	if len(cert.SubjectKeyId) > 0 {
-		keyId := string(cert.SubjectKeyId)
-		s.bySubjectKeyId[keyId] = append(s.bySubjectKeyId[keyId], cert)
-	}
-	name := nameToKey(&cert.Subject)
-	s.byName[name] = append(s.byName[name], cert)
-}
-
-// SetFromPEM attempts to parse a series of PEM encoded root certificates. It
-// appends any certificates found to s and returns true if any certificates
-// were successfully parsed. On many Linux systems, /etc/ssl/cert.pem will
-// contains the system wide set of root CAs in a format suitable for this
-// function.
-func (s *CASet) SetFromPEM(pemCerts []byte) (ok bool) {
-	for len(pemCerts) > 0 {
-		var block *pem.Block
-		block, pemCerts = pem.Decode(pemCerts)
-		if block == nil {
-			break
-		}
-		if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
-			continue
-		}
-
-		cert, err := x509.ParseCertificate(block.Bytes)
-		if err != nil {
-			continue
-		}
-
-		s.AddCert(cert)
-		ok = true
-	}
-
-	return
-}
diff --git a/src/pkg/crypto/tls/common.go b/src/pkg/crypto/tls/common.go
index fb2916a..204d255 100644
--- a/src/pkg/crypto/tls/common.go
+++ b/src/pkg/crypto/tls/common.go
@@ -122,7 +122,7 @@ type Config struct {
 	// RootCAs defines the set of root certificate authorities
 	// that clients use when verifying server certificates.
 	// If RootCAs is nil, TLS uses the host's root CA set.
-	RootCAs *CASet
+	RootCAs *x509.CertPool
 
 	// NextProtos is a list of supported, application level protocols.
 	NextProtos []string
@@ -158,7 +158,7 @@ func (c *Config) time() int64 {
 	return t()
 }
 
-func (c *Config) rootCAs() *CASet {
+func (c *Config) rootCAs() *x509.CertPool {
 	s := c.RootCAs
 	if s == nil {
 		s = defaultRoots()
@@ -178,6 +178,9 @@ func (c *Config) cipherSuites() []uint16 {
 type Certificate struct {
 	Certificate [][]byte
 	PrivateKey  *rsa.PrivateKey
+	// OCSPStaple contains an optional OCSP response which will be served
+	// to clients that request it.
+	OCSPStaple []byte
 }
 
 // A TLS record.
@@ -221,7 +224,7 @@ var certFiles = []string{
 
 var once sync.Once
 
-func defaultRoots() *CASet {
+func defaultRoots() *x509.CertPool {
 	once.Do(initDefaults)
 	return varDefaultRoots
 }
@@ -236,14 +239,14 @@ func initDefaults() {
 	initDefaultCipherSuites()
 }
 
-var varDefaultRoots *CASet
+var varDefaultRoots *x509.CertPool
 
 func initDefaultRoots() {
-	roots := NewCASet()
+	roots := x509.NewCertPool()
 	for _, file := range certFiles {
 		data, err := ioutil.ReadFile(file)
 		if err == nil {
-			roots.SetFromPEM(data)
+			roots.AppendCertsFromPEM(data)
 			break
 		}
 	}
diff --git a/src/pkg/crypto/tls/conn.go b/src/pkg/crypto/tls/conn.go
index b94e235..63d5631 100644
--- a/src/pkg/crypto/tls/conn.go
+++ b/src/pkg/crypto/tls/conn.go
@@ -34,6 +34,9 @@ type Conn struct {
 	cipherSuite       uint16
 	ocspResponse      []byte // stapled OCSP response
 	peerCertificates  []*x509.Certificate
+	// verifedChains contains the certificate chains that we built, as
+	// opposed to the ones presented by the server.
+	verifiedChains [][]*x509.Certificate
 
 	clientProtocol         string
 	clientProtocolFallback bool
diff --git a/src/pkg/crypto/tls/handshake_client.go b/src/pkg/crypto/tls/handshake_client.go
index 540b25c..c758c96 100644
--- a/src/pkg/crypto/tls/handshake_client.go
+++ b/src/pkg/crypto/tls/handshake_client.go
@@ -88,7 +88,6 @@ func (c *Conn) clientHandshake() os.Error {
 	finishedHash.Write(certMsg.marshal())
 
 	certs := make([]*x509.Certificate, len(certMsg.certificates))
-	chain := NewCASet()
 	for i, asn1Data := range certMsg.certificates {
 		cert, err := x509.ParseCertificate(asn1Data)
 		if err != nil {
@@ -96,47 +95,29 @@ func (c *Conn) clientHandshake() os.Error {
 			return os.ErrorString("failed to parse certificate from server: " + err.String())
 		}
 		certs[i] = cert
-		chain.AddCert(cert)
 	}
 
 	// If we don't have a root CA set configured then anything is accepted.
 	// TODO(rsc): Find certificates for OS X 10.6.
-	for cur := certs[0]; c.config.RootCAs != nil; {
-		parent := c.config.RootCAs.FindVerifiedParent(cur)
-		if parent != nil {
-			break
+	if c.config.RootCAs != nil {
+		opts := x509.VerifyOptions{
+			Roots:         c.config.RootCAs,
+			CurrentTime:   c.config.time(),
+			DNSName:       c.config.ServerName,
+			Intermediates: x509.NewCertPool(),
 		}
 
-		parent = chain.FindVerifiedParent(cur)
-		if parent == nil {
-			c.sendAlert(alertBadCertificate)
-			return os.ErrorString("could not find root certificate for chain")
+		for i, cert := range certs {
+			if i == 0 {
+				continue
+			}
+			opts.Intermediates.AddCert(cert)
 		}
-
-		if !parent.BasicConstraintsValid || !parent.IsCA {
+		c.verifiedChains, err = certs[0].Verify(opts)
+		if err != nil {
 			c.sendAlert(alertBadCertificate)
-			return os.ErrorString("intermediate certificate does not have CA bit set")
+			return err
 		}
-		// KeyUsage status flags are ignored. From Engineering
-		// Security, Peter Gutmann: A European government CA marked its
-		// signing certificates as being valid for encryption only, but
-		// no-one noticed. Another European CA marked its signature
-		// keys as not being valid for signatures. A different CA
-		// marked its own trusted root certificate as being invalid for
-		// certificate signing.  Another national CA distributed a
-		// certificate to be used to encrypt data for the country’s tax
-		// authority that was marked as only being usable for digital
-		// signatures but not for encryption. Yet another CA reversed
-		// the order of the bit flags in the keyUsage due to confusion
-		// over encoding endianness, essentially setting a random
-		// keyUsage in certificates that it issued. Another CA created
-		// a self-invalidating certificate by adding a certificate
-		// policy statement stipulating that the certificate had to be
-		// used strictly as specified in the keyUsage, and a keyUsage
-		// containing a flag indicating that the RSA encryption key
-		// could only be used for Diffie-Hellman key agreement.
-
-		cur = parent
 	}
 
 	if _, ok := certs[0].PublicKey.(*rsa.PublicKey); !ok {
@@ -145,7 +126,7 @@ func (c *Conn) clientHandshake() os.Error {
 
 	c.peerCertificates = certs
 
-	if serverHello.certStatus {
+	if serverHello.ocspStapling {
 		msg, err = c.readHandshake()
 		if err != nil {
 			return err
diff --git a/src/pkg/crypto/tls/handshake_messages.go b/src/pkg/crypto/tls/handshake_messages.go
index e5e8562..6645adc 100644
--- a/src/pkg/crypto/tls/handshake_messages.go
+++ b/src/pkg/crypto/tls/handshake_messages.go
@@ -306,7 +306,7 @@ type serverHelloMsg struct {
 	compressionMethod uint8
 	nextProtoNeg      bool
 	nextProtos        []string
-	certStatus        bool
+	ocspStapling      bool
 }
 
 func (m *serverHelloMsg) marshal() []byte {
@@ -327,7 +327,7 @@ func (m *serverHelloMsg) marshal() []byte {
 		nextProtoLen += len(m.nextProtos)
 		extensionsLength += nextProtoLen
 	}
-	if m.certStatus {
+	if m.ocspStapling {
 		numExtensions++
 	}
 	if numExtensions > 0 {
@@ -373,7 +373,7 @@ func (m *serverHelloMsg) marshal() []byte {
 			z = z[1+l:]
 		}
 	}
-	if m.certStatus {
+	if m.ocspStapling {
 		z[0] = byte(extensionStatusRequest >> 8)
 		z[1] = byte(extensionStatusRequest)
 		z = z[4:]
@@ -406,7 +406,7 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
 
 	m.nextProtoNeg = false
 	m.nextProtos = nil
-	m.certStatus = false
+	m.ocspStapling = false
 
 	if len(data) == 0 {
 		// ServerHello is optionally followed by extension data
@@ -450,7 +450,7 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
 			if length > 0 {
 				return false
 			}
-			m.certStatus = true
+			m.ocspStapling = true
 		}
 		data = data[length:]
 	}
diff --git a/src/pkg/crypto/tls/handshake_messages_test.go b/src/pkg/crypto/tls/handshake_messages_test.go
index f5e94e2..23f729d 100644
--- a/src/pkg/crypto/tls/handshake_messages_test.go
+++ b/src/pkg/crypto/tls/handshake_messages_test.go
@@ -32,7 +32,7 @@ type testMessage interface {
 func TestMarshalUnmarshal(t *testing.T) {
 	rand := rand.New(rand.NewSource(0))
 	for i, iface := range tests {
-		ty := reflect.NewValue(iface).Type()
+		ty := reflect.ValueOf(iface).Type()
 
 		n := 100
 		if testing.Short() {
@@ -125,7 +125,7 @@ func (*clientHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
 		m.supportedCurves[i] = uint16(rand.Intn(30000))
 	}
 
-	return reflect.NewValue(m)
+	return reflect.ValueOf(m)
 }
 
 func (*serverHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
@@ -146,7 +146,7 @@ func (*serverHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
 		}
 	}
 
-	return reflect.NewValue(m)
+	return reflect.ValueOf(m)
 }
 
 func (*certificateMsg) Generate(rand *rand.Rand, size int) reflect.Value {
@@ -156,7 +156,7 @@ func (*certificateMsg) Generate(rand *rand.Rand, size int) reflect.Value {
 	for i := 0; i < numCerts; i++ {
 		m.certificates[i] = randomBytes(rand.Intn(10)+1, rand)
 	}
-	return reflect.NewValue(m)
+	return reflect.ValueOf(m)
 }
 
 func (*certificateRequestMsg) Generate(rand *rand.Rand, size int) reflect.Value {
@@ -167,13 +167,13 @@ func (*certificateRequestMsg) Generate(rand *rand.Rand, size int) reflect.Value
 	for i := 0; i < numCAs; i++ {
 		m.certificateAuthorities[i] = randomBytes(rand.Intn(15)+1, rand)
 	}
-	return reflect.NewValue(m)
+	return reflect.ValueOf(m)
 }
 
 func (*certificateVerifyMsg) Generate(rand *rand.Rand, size int) reflect.Value {
 	m := &certificateVerifyMsg{}
 	m.signature = randomBytes(rand.Intn(15)+1, rand)
-	return reflect.NewValue(m)
+	return reflect.ValueOf(m)
 }
 
 func (*certificateStatusMsg) Generate(rand *rand.Rand, size int) reflect.Value {
@@ -184,23 +184,23 @@ func (*certificateStatusMsg) Generate(rand *rand.Rand, size int) reflect.Value {
 	} else {
 		m.statusType = 42
 	}
-	return reflect.NewValue(m)
+	return reflect.ValueOf(m)
 }
 
 func (*clientKeyExchangeMsg) Generate(rand *rand.Rand, size int) reflect.Value {
 	m := &clientKeyExchangeMsg{}
 	m.ciphertext = randomBytes(rand.Intn(1000)+1, rand)
-	return reflect.NewValue(m)
+	return reflect.ValueOf(m)
 }
 
 func (*finishedMsg) Generate(rand *rand.Rand, size int) reflect.Value {
 	m := &finishedMsg{}
 	m.verifyData = randomBytes(12, rand)
-	return reflect.NewValue(m)
+	return reflect.ValueOf(m)
 }
 
 func (*nextProtoMsg) Generate(rand *rand.Rand, size int) reflect.Value {
 	m := &nextProtoMsg{}
 	m.proto = randomString(rand.Intn(255), rand)
-	return reflect.NewValue(m)
+	return reflect.ValueOf(m)
 }
diff --git a/src/pkg/crypto/tls/handshake_server.go b/src/pkg/crypto/tls/handshake_server.go
index 809c8c1..37c8d15 100644
--- a/src/pkg/crypto/tls/handshake_server.go
+++ b/src/pkg/crypto/tls/handshake_server.go
@@ -103,6 +103,9 @@ FindCipherSuite:
 		hello.nextProtoNeg = true
 		hello.nextProtos = config.NextProtos
 	}
+	if clientHello.ocspStapling && len(config.Certificates[0].OCSPStaple) > 0 {
+		hello.ocspStapling = true
+	}
 
 	finishedHash.Write(hello.marshal())
 	c.writeRecord(recordTypeHandshake, hello.marshal())
@@ -116,6 +119,14 @@ FindCipherSuite:
 	finishedHash.Write(certMsg.marshal())
 	c.writeRecord(recordTypeHandshake, certMsg.marshal())
 
+	if hello.ocspStapling {
+		certStatus := new(certificateStatusMsg)
+		certStatus.statusType = statusTypeOCSP
+		certStatus.response = config.Certificates[0].OCSPStaple
+		finishedHash.Write(certStatus.marshal())
+		c.writeRecord(recordTypeHandshake, certStatus.marshal())
+	}
+
 	keyAgreement := suite.ka()
 
 	skx, err := keyAgreement.generateServerKeyExchange(config, clientHello, hello)
diff --git a/src/pkg/crypto/tls/handshake_server_test.go b/src/pkg/crypto/tls/handshake_server_test.go
index 6beb6a9..5a1e754 100644
--- a/src/pkg/crypto/tls/handshake_server_test.go
+++ b/src/pkg/crypto/tls/handshake_server_test.go
@@ -188,8 +188,10 @@ var testPrivateKey = &rsa.PrivateKey{
 		E: 65537,
 	},
 	D: bigFromString("29354450337804273969007277378287027274721892607543397931919078829901848876371746653677097639302788129485893852488285045793268732234230875671682624082413996177431586734171663258657462237320300610850244186316880055243099640544518318093544057213190320837094958164973959123058337475052510833916491060913053867729"),
-	P: bigFromString("11969277782311800166562047708379380720136961987713178380670422671426759650127150688426177829077494755200794297055316163155755835813760102405344560929062149"),
-	Q: bigFromString("10998999429884441391899182616418192492905073053684657075974935218461686523870125521822756579792315215543092255516093840728890783887287417039645833477273829"),
+	Primes: []*big.Int{
+		bigFromString("11969277782311800166562047708379380720136961987713178380670422671426759650127150688426177829077494755200794297055316163155755835813760102405344560929062149"),
+		bigFromString("10998999429884441391899182616418192492905073053684657075974935218461686523870125521822756579792315215543092255516093840728890783887287417039645833477273829"),
+	},
 }
 
 // Script of interaction with gnutls implementation.
diff --git a/src/pkg/crypto/tls/tls.go b/src/pkg/crypto/tls/tls.go
index 7de44bb..7d0bb9f 100644
--- a/src/pkg/crypto/tls/tls.go
+++ b/src/pkg/crypto/tls/tls.go
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package partially implements the TLS 1.1 protocol, as specified in RFC 4346.
+// Package tls partially implements the TLS 1.1 protocol, as specified in RFC
+// 4346.
 package tls
 
 import (
diff --git a/src/pkg/crypto/twofish/twofish.go b/src/pkg/crypto/twofish/twofish.go
index 62253e7..9303f03 100644
--- a/src/pkg/crypto/twofish/twofish.go
+++ b/src/pkg/crypto/twofish/twofish.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package implements Bruce Schneier's Twofish encryption algorithm.
+// Package twofish implements Bruce Schneier's Twofish encryption algorithm.
 package twofish
 
 // Twofish is defined in http://www.schneier.com/paper-twofish-paper.pdf [TWOFISH]
diff --git a/src/pkg/crypto/x509/Makefile b/src/pkg/crypto/x509/Makefile
index 329a61b..14ffd09 100644
--- a/src/pkg/crypto/x509/Makefile
+++ b/src/pkg/crypto/x509/Makefile
@@ -6,6 +6,8 @@ include ../../../Make.inc
 
 TARG=crypto/x509
 GOFILES=\
+	cert_pool.go\
+	verify.go\
 	x509.go\
 
 include ../../../Make.pkg
diff --git a/src/pkg/crypto/x509/cert_pool.go b/src/pkg/crypto/x509/cert_pool.go
new file mode 100644
index 0000000..c295fd9
--- /dev/null
+++ b/src/pkg/crypto/x509/cert_pool.go
@@ -0,0 +1,105 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package x509
+
+import (
+	"encoding/pem"
+	"strings"
+)
+
+// Roots is a set of certificates.
+type CertPool struct {
+	bySubjectKeyId map[string][]int
+	byName         map[string][]int
+	certs          []*Certificate
+}
+
+// NewCertPool returns a new, empty CertPool.
+func NewCertPool() *CertPool {
+	return &CertPool{
+		make(map[string][]int),
+		make(map[string][]int),
+		nil,
+	}
+}
+
+func nameToKey(name *Name) string {
+	return strings.Join(name.Country, ",") + "/" + strings.Join(name.Organization, ",") + "/" + strings.Join(name.OrganizationalUnit, ",") + "/" + name.CommonName
+}
+
+// findVerifiedParents attempts to find certificates in s which have signed the
+// given certificate. If no such certificate can be found or the signature
+// doesn't match, it returns nil.
+func (s *CertPool) findVerifiedParents(cert *Certificate) (parents []int) {
+	var candidates []int
+
+	if len(cert.AuthorityKeyId) > 0 {
+		candidates = s.bySubjectKeyId[string(cert.AuthorityKeyId)]
+	}
+	if len(candidates) == 0 {
+		candidates = s.byName[nameToKey(&cert.Issuer)]
+	}
+
+	for _, c := range candidates {
+		if cert.CheckSignatureFrom(s.certs[c]) == nil {
+			parents = append(parents, c)
+		}
+	}
+
+	return
+}
+
+// AddCert adds a certificate to a pool.
+func (s *CertPool) AddCert(cert *Certificate) {
+	if cert == nil {
+		panic("adding nil Certificate to CertPool")
+	}
+
+	// Check that the certificate isn't being added twice.
+	for _, c := range s.certs {
+		if c.Equal(cert) {
+			return
+		}
+	}
+
+	n := len(s.certs)
+	s.certs = append(s.certs, cert)
+
+	if len(cert.SubjectKeyId) > 0 {
+		keyId := string(cert.SubjectKeyId)
+		s.bySubjectKeyId[keyId] = append(s.bySubjectKeyId[keyId], n)
+	}
+	name := nameToKey(&cert.Subject)
+	s.byName[name] = append(s.byName[name], n)
+}
+
+// AppendCertsFromPEM attempts to parse a series of PEM encoded root
+// certificates. It appends any certificates found to s and returns true if any
+// certificates were successfully parsed.
+//
+// On many Linux systems, /etc/ssl/cert.pem will contains the system wide set
+// of root CAs in a format suitable for this function.
+func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) {
+	for len(pemCerts) > 0 {
+		var block *pem.Block
+		block, pemCerts = pem.Decode(pemCerts)
+		if block == nil {
+			break
+		}
+		if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
+			continue
+		}
+
+		cert, err := ParseCertificate(block.Bytes)
+		if err != nil {
+			continue
+		}
+
+		s.AddCert(cert)
+		ok = true
+	}
+
+	return
+}
diff --git a/src/pkg/crypto/x509/verify.go b/src/pkg/crypto/x509/verify.go
new file mode 100644
index 0000000..9145880
--- /dev/null
+++ b/src/pkg/crypto/x509/verify.go
@@ -0,0 +1,239 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package x509
+
+import (
+	"os"
+	"strings"
+	"time"
+)
+
+type InvalidReason int
+
+const (
+	// NotAuthorizedToSign results when a certificate is signed by another
+	// which isn't marked as a CA certificate.
+	NotAuthorizedToSign InvalidReason = iota
+	// Expired results when a certificate has expired, based on the time
+	// given in the VerifyOptions.
+	Expired
+	// CANotAuthorizedForThisName results when an intermediate or root
+	// certificate has a name constraint which doesn't include the name
+	// being checked.
+	CANotAuthorizedForThisName
+)
+
+// CertificateInvalidError results when an odd error occurs. Users of this
+// library probably want to handle all these errors uniformly.
+type CertificateInvalidError struct {
+	Cert   *Certificate
+	Reason InvalidReason
+}
+
+func (e CertificateInvalidError) String() string {
+	switch e.Reason {
+	case NotAuthorizedToSign:
+		return "x509: certificate is not authorized to sign other other certificates"
+	case Expired:
+		return "x509: certificate has expired or is not yet valid"
+	case CANotAuthorizedForThisName:
+		return "x509: a root or intermediate certificate is not authorized to sign in this domain"
+	}
+	return "x509: unknown error"
+}
+
+// HostnameError results when the set of authorized names doesn't match the
+// requested name.
+type HostnameError struct {
+	Certificate *Certificate
+	Host        string
+}
+
+func (h HostnameError) String() string {
+	var valid string
+	c := h.Certificate
+	if len(c.DNSNames) > 0 {
+		valid = strings.Join(c.DNSNames, ", ")
+	} else {
+		valid = c.Subject.CommonName
+	}
+	return "certificate is valid for " + valid + ", not " + h.Host
+}
+
+
+// UnknownAuthorityError results when the certificate issuer is unknown
+type UnknownAuthorityError struct {
+	cert *Certificate
+}
+
+func (e UnknownAuthorityError) String() string {
+	return "x509: certificate signed by unknown authority"
+}
+
+// VerifyOptions contains parameters for Certificate.Verify. It's a structure
+// because other PKIX verification APIs have ended up needing many options.
+type VerifyOptions struct {
+	DNSName       string
+	Intermediates *CertPool
+	Roots         *CertPool
+	CurrentTime   int64 // if 0, the current system time is used.
+}
+
+const (
+	leafCertificate = iota
+	intermediateCertificate
+	rootCertificate
+)
+
+// isValid performs validity checks on the c.
+func (c *Certificate) isValid(certType int, opts *VerifyOptions) os.Error {
+	if opts.CurrentTime < c.NotBefore.Seconds() ||
+		opts.CurrentTime > c.NotAfter.Seconds() {
+		return CertificateInvalidError{c, Expired}
+	}
+
+	if len(c.PermittedDNSDomains) > 0 {
+		for _, domain := range c.PermittedDNSDomains {
+			if opts.DNSName == domain ||
+				(strings.HasSuffix(opts.DNSName, domain) &&
+					len(opts.DNSName) >= 1+len(domain) &&
+					opts.DNSName[len(opts.DNSName)-len(domain)-1] == '.') {
+				continue
+			}
+
+			return CertificateInvalidError{c, CANotAuthorizedForThisName}
+		}
+	}
+
+	// KeyUsage status flags are ignored. From Engineering Security, Peter
+	// Gutmann: A European government CA marked its signing certificates as
+	// being valid for encryption only, but no-one noticed. Another
+	// European CA marked its signature keys as not being valid for
+	// signatures. A different CA marked its own trusted root certificate
+	// as being invalid for certificate signing.  Another national CA
+	// distributed a certificate to be used to encrypt data for the
+	// country’s tax authority that was marked as only being usable for
+	// digital signatures but not for encryption. Yet another CA reversed
+	// the order of the bit flags in the keyUsage due to confusion over
+	// encoding endianness, essentially setting a random keyUsage in
+	// certificates that it issued. Another CA created a self-invalidating
+	// certificate by adding a certificate policy statement stipulating
+	// that the certificate had to be used strictly as specified in the
+	// keyUsage, and a keyUsage containing a flag indicating that the RSA
+	// encryption key could only be used for Diffie-Hellman key agreement.
+
+	if certType == intermediateCertificate && (!c.BasicConstraintsValid || !c.IsCA) {
+		return CertificateInvalidError{c, NotAuthorizedToSign}
+	}
+
+	return nil
+}
+
+// Verify attempts to verify c by building one or more chains from c to a
+// certificate in opts.roots, using certificates in opts.Intermediates if
+// needed. If successful, it returns one or chains where the first element of
+// the chain is c and the last element is from opts.Roots.
+//
+// WARNING: this doesn't do any revocation checking.
+func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err os.Error) {
+	if opts.CurrentTime == 0 {
+		opts.CurrentTime = time.Seconds()
+	}
+	err = c.isValid(leafCertificate, &opts)
+	if err != nil {
+		return
+	}
+	if len(opts.DNSName) > 0 {
+		err = c.VerifyHostname(opts.DNSName)
+		if err != nil {
+			return
+		}
+	}
+	return c.buildChains(make(map[int][][]*Certificate), []*Certificate{c}, &opts)
+}
+
+func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate {
+	n := make([]*Certificate, len(chain)+1)
+	copy(n, chain)
+	n[len(chain)] = cert
+	return n
+}
+
+func (c *Certificate) buildChains(cache map[int][][]*Certificate, currentChain []*Certificate, opts *VerifyOptions) (chains [][]*Certificate, err os.Error) {
+	for _, rootNum := range opts.Roots.findVerifiedParents(c) {
+		root := opts.Roots.certs[rootNum]
+		err = root.isValid(rootCertificate, opts)
+		if err != nil {
+			continue
+		}
+		chains = append(chains, appendToFreshChain(currentChain, root))
+	}
+
+	for _, intermediateNum := range opts.Intermediates.findVerifiedParents(c) {
+		intermediate := opts.Intermediates.certs[intermediateNum]
+		err = intermediate.isValid(intermediateCertificate, opts)
+		if err != nil {
+			continue
+		}
+		var childChains [][]*Certificate
+		childChains, ok := cache[intermediateNum]
+		if !ok {
+			childChains, err = intermediate.buildChains(cache, appendToFreshChain(currentChain, intermediate), opts)
+			cache[intermediateNum] = childChains
+		}
+		chains = append(chains, childChains...)
+	}
+
+	if len(chains) > 0 {
+		err = nil
+	}
+
+	if len(chains) == 0 && err == nil {
+		err = UnknownAuthorityError{c}
+	}
+
+	return
+}
+
+func matchHostnames(pattern, host string) bool {
+	if len(pattern) == 0 || len(host) == 0 {
+		return false
+	}
+
+	patternParts := strings.Split(pattern, ".", -1)
+	hostParts := strings.Split(host, ".", -1)
+
+	if len(patternParts) != len(hostParts) {
+		return false
+	}
+
+	for i, patternPart := range patternParts {
+		if patternPart == "*" {
+			continue
+		}
+		if patternPart != hostParts[i] {
+			return false
+		}
+	}
+
+	return true
+}
+
+// VerifyHostname returns nil if c is a valid certificate for the named host.
+// Otherwise it returns an os.Error describing the mismatch.
+func (c *Certificate) VerifyHostname(h string) os.Error {
+	if len(c.DNSNames) > 0 {
+		for _, match := range c.DNSNames {
+			if matchHostnames(match, h) {
+				return nil
+			}
+		}
+		// If Subject Alt Name is given, we ignore the common name.
+	} else if matchHostnames(c.Subject.CommonName, h) {
+		return nil
+	}
+
+	return HostnameError{c, h}
+}
diff --git a/src/pkg/crypto/x509/verify_test.go b/src/pkg/crypto/x509/verify_test.go
new file mode 100644
index 0000000..6a103dc
--- /dev/null
+++ b/src/pkg/crypto/x509/verify_test.go
@@ -0,0 +1,390 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package x509
+
+import (
+	"encoding/pem"
+	"os"
+	"strings"
+	"testing"
+)
+
+type verifyTest struct {
+	leaf          string
+	intermediates []string
+	roots         []string
+	currentTime   int64
+	dnsName       string
+
+	errorCallback  func(*testing.T, int, os.Error) bool
+	expectedChains [][]string
+}
+
+var verifyTests = []verifyTest{
+	{
+		leaf:          googleLeaf,
+		intermediates: []string{thawteIntermediate},
+		roots:         []string{verisignRoot},
+		currentTime:   1302726541,
+		dnsName:       "www.google.com",
+
+		expectedChains: [][]string{
+			[]string{"Google", "Thawte", "VeriSign"},
+		},
+	},
+	{
+		leaf:          googleLeaf,
+		intermediates: []string{thawteIntermediate},
+		roots:         []string{verisignRoot},
+		currentTime:   1302726541,
+		dnsName:       "www.example.com",
+
+		errorCallback: expectHostnameError,
+	},
+	{
+		leaf:          googleLeaf,
+		intermediates: []string{thawteIntermediate},
+		roots:         []string{verisignRoot},
+		currentTime:   1,
+		dnsName:       "www.example.com",
+
+		errorCallback: expectExpired,
+	},
+	{
+		leaf:        googleLeaf,
+		roots:       []string{verisignRoot},
+		currentTime: 1302726541,
+		dnsName:     "www.google.com",
+
+		errorCallback: expectAuthorityUnknown,
+	},
+	{
+		leaf:          googleLeaf,
+		intermediates: []string{verisignRoot, thawteIntermediate},
+		roots:         []string{verisignRoot},
+		currentTime:   1302726541,
+		dnsName:       "www.google.com",
+
+		expectedChains: [][]string{
+			[]string{"Google", "Thawte", "VeriSign"},
+		},
+	},
+	{
+		leaf:          googleLeaf,
+		intermediates: []string{verisignRoot, thawteIntermediate},
+		roots:         []string{verisignRoot},
+		currentTime:   1302726541,
+
+		expectedChains: [][]string{
+			[]string{"Google", "Thawte", "VeriSign"},
+		},
+	},
+	{
+		leaf:          dnssecExpLeaf,
+		intermediates: []string{startComIntermediate},
+		roots:         []string{startComRoot},
+		currentTime:   1302726541,
+
+		expectedChains: [][]string{
+			[]string{"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority"},
+		},
+	},
+}
+
+func expectHostnameError(t *testing.T, i int, err os.Error) (ok bool) {
+	if _, ok := err.(HostnameError); !ok {
+		t.Errorf("#%d: error was not a HostnameError: %s", i, err)
+		return false
+	}
+	return true
+}
+
+func expectExpired(t *testing.T, i int, err os.Error) (ok bool) {
+	if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != Expired {
+		t.Errorf("#%d: error was not Expired: %s", i, err)
+		return false
+	}
+	return true
+}
+
+func expectAuthorityUnknown(t *testing.T, i int, err os.Error) (ok bool) {
+	if _, ok := err.(UnknownAuthorityError); !ok {
+		t.Errorf("#%d: error was not UnknownAuthorityError: %s", i, err)
+		return false
+	}
+	return true
+}
+
+func certificateFromPEM(pemBytes string) (*Certificate, os.Error) {
+	block, _ := pem.Decode([]byte(pemBytes))
+	if block == nil {
+		return nil, os.ErrorString("failed to decode PEM")
+	}
+	return ParseCertificate(block.Bytes)
+}
+
+func TestVerify(t *testing.T) {
+	for i, test := range verifyTests {
+		opts := VerifyOptions{
+			Roots:         NewCertPool(),
+			Intermediates: NewCertPool(),
+			DNSName:       test.dnsName,
+			CurrentTime:   test.currentTime,
+		}
+
+		for j, root := range test.roots {
+			ok := opts.Roots.AppendCertsFromPEM([]byte(root))
+			if !ok {
+				t.Errorf("#%d: failed to parse root #%d", i, j)
+				return
+			}
+		}
+
+		for j, intermediate := range test.intermediates {
+			ok := opts.Intermediates.AppendCertsFromPEM([]byte(intermediate))
+			if !ok {
+				t.Errorf("#%d: failed to parse intermediate #%d", i, j)
+				return
+			}
+		}
+
+		leaf, err := certificateFromPEM(test.leaf)
+		if err != nil {
+			t.Errorf("#%d: failed to parse leaf: %s", i, err)
+			return
+		}
+
+		chains, err := leaf.Verify(opts)
+
+		if test.errorCallback == nil && err != nil {
+			t.Errorf("#%d: unexpected error: %s", i, err)
+		}
+		if test.errorCallback != nil {
+			if !test.errorCallback(t, i, err) {
+				return
+			}
+		}
+
+		if len(chains) != len(test.expectedChains) {
+			t.Errorf("#%d: wanted %d chains, got %d", i, len(test.expectedChains), len(chains))
+		}
+
+		// We check that each returned chain matches a chain from
+		// expectedChains but an entry in expectedChains can't match
+		// two chains.
+		seenChains := make([]bool, len(chains))
+	NextOutputChain:
+		for _, chain := range chains {
+		TryNextExpected:
+			for j, expectedChain := range test.expectedChains {
+				if seenChains[j] {
+					continue
+				}
+				if len(chain) != len(expectedChain) {
+					continue
+				}
+				for k, cert := range chain {
+					if strings.Index(nameToKey(&cert.Subject), expectedChain[k]) == -1 {
+						continue TryNextExpected
+					}
+				}
+				// we matched
+				seenChains[j] = true
+				continue NextOutputChain
+			}
+			t.Errorf("#%d: No expected chain matched %s", i, chainToDebugString(chain))
+		}
+	}
+}
+
+func chainToDebugString(chain []*Certificate) string {
+	var chainStr string
+	for _, cert := range chain {
+		if len(chainStr) > 0 {
+			chainStr += " -> "
+		}
+		chainStr += nameToKey(&cert.Subject)
+	}
+	return chainStr
+}
+
+const verisignRoot = `-----BEGIN CERTIFICATE-----
+MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG
+A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
+cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2
+MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV
+BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt
+YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE
+BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is
+I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G
+CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do
+lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc
+AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k
+-----END CERTIFICATE-----
+`
+
+const thawteIntermediate = `-----BEGIN CERTIFICATE-----
+MIIDIzCCAoygAwIBAgIEMAAAAjANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJV
+UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsTLkNsYXNzIDMgUHVi
+bGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNTEzMDAw
+MDAwWhcNMTQwNTEyMjM1OTU5WjBMMQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhh
+d3RlIENvbnN1bHRpbmcgKFB0eSkgTHRkLjEWMBQGA1UEAxMNVGhhd3RlIFNHQyBD
+QTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1NNn0I0Vf67NMf59HZGhPwtx
+PKzMyGT7Y/wySweUvW+Aui/hBJPAM/wJMyPpC3QrccQDxtLN4i/1CWPN/0ilAL/g
+5/OIty0y3pg25gqtAHvEZEo7hHUD8nCSfQ5i9SGraTaEMXWQ+L/HbIgbBpV8yeWo
+3nWhLHpo39XKHIdYYBkCAwEAAaOB/jCB+zASBgNVHRMBAf8ECDAGAQH/AgEAMAsG
+A1UdDwQEAwIBBjARBglghkgBhvhCAQEEBAMCAQYwKAYDVR0RBCEwH6QdMBsxGTAX
+BgNVBAMTEFByaXZhdGVMYWJlbDMtMTUwMQYDVR0fBCowKDAmoCSgIoYgaHR0cDov
+L2NybC52ZXJpc2lnbi5jb20vcGNhMy5jcmwwMgYIKwYBBQUHAQEEJjAkMCIGCCsG
+AQUFBzABhhZodHRwOi8vb2NzcC50aGF3dGUuY29tMDQGA1UdJQQtMCsGCCsGAQUF
+BwMBBggrBgEFBQcDAgYJYIZIAYb4QgQBBgpghkgBhvhFAQgBMA0GCSqGSIb3DQEB
+BQUAA4GBAFWsY+reod3SkF+fC852vhNRj5PZBSvIG3dLrWlQoe7e3P3bB+noOZTc
+q3J5Lwa/q4FwxKjt6lM07e8eU9kGx1Yr0Vz00YqOtCuxN5BICEIlxT6Ky3/rbwTR
+bcV0oveifHtgPHfNDs5IAn8BL7abN+AqKjbc1YXWrOU/VG+WHgWv
+-----END CERTIFICATE-----
+`
+
+const googleLeaf = `-----BEGIN CERTIFICATE-----
+MIIDITCCAoqgAwIBAgIQL9+89q6RUm0PmqPfQDQ+mjANBgkqhkiG9w0BAQUFADBM
+MQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkg
+THRkLjEWMBQGA1UEAxMNVGhhd3RlIFNHQyBDQTAeFw0wOTEyMTgwMDAwMDBaFw0x
+MTEyMTgyMzU5NTlaMGgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlh
+MRYwFAYDVQQHFA1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKFApHb29nbGUgSW5jMRcw
+FQYDVQQDFA53d3cuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEA6PmGD5D6htffvXImttdEAoN4c9kCKO+IRTn7EOh8rqk41XXGOOsKFQebg+jN
+gtXj9xVoRaELGYW84u+E593y17iYwqG7tcFR39SDAqc9BkJb4SLD3muFXxzW2k6L
+05vuuWciKh0R73mkszeK9P4Y/bz5RiNQl/Os/CRGK1w7t0UCAwEAAaOB5zCB5DAM
+BgNVHRMBAf8EAjAAMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwudGhhd3Rl
+LmNvbS9UaGF3dGVTR0NDQS5jcmwwKAYDVR0lBCEwHwYIKwYBBQUHAwEGCCsGAQUF
+BwMCBglghkgBhvhCBAEwcgYIKwYBBQUHAQEEZjBkMCIGCCsGAQUFBzABhhZodHRw
+Oi8vb2NzcC50aGF3dGUuY29tMD4GCCsGAQUFBzAChjJodHRwOi8vd3d3LnRoYXd0
+ZS5jb20vcmVwb3NpdG9yeS9UaGF3dGVfU0dDX0NBLmNydDANBgkqhkiG9w0BAQUF
+AAOBgQCfQ89bxFApsb/isJr/aiEdLRLDLE5a+RLizrmCUi3nHX4adpaQedEkUjh5
+u2ONgJd8IyAPkU0Wueru9G2Jysa9zCRo1kNbzipYvzwY4OA8Ys+WAi0oR1A04Se6
+z5nRUP8pJcA2NhUzUnC+MY+f6H/nEQyNv4SgQhqAibAxWEEHXw==
+-----END CERTIFICATE-----`
+
+const dnssecExpLeaf = `-----BEGIN CERTIFICATE-----
+MIIGzTCCBbWgAwIBAgIDAdD6MA0GCSqGSIb3DQEBBQUAMIGMMQswCQYDVQQGEwJJ
+TDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0
+YWwgQ2VydGlmaWNhdGUgU2lnbmluZzE4MDYGA1UEAxMvU3RhcnRDb20gQ2xhc3Mg
+MSBQcmltYXJ5IEludGVybWVkaWF0ZSBTZXJ2ZXIgQ0EwHhcNMTAwNzA0MTQ1MjQ1
+WhcNMTEwNzA1MTA1NzA0WjCBwTEgMB4GA1UEDRMXMjIxMTM3LWxpOWE5dHhJRzZM
+NnNyVFMxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVQZXJzb25hIE5vdCBWYWxpZGF0
+ZWQxKTAnBgNVBAsTIFN0YXJ0Q29tIEZyZWUgQ2VydGlmaWNhdGUgTWVtYmVyMRsw
+GQYDVQQDExJ3d3cuZG5zc2VjLWV4cC5vcmcxKDAmBgkqhkiG9w0BCQEWGWhvc3Rt
+YXN0ZXJAZG5zc2VjLWV4cC5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQDEdF/22vaxrPbqpgVYMWi+alfpzBctpbfLBdPGuqOazJdCT0NbWcK8/+B4
+X6OlSOURNIlwLzhkmwVsWdVv6dVSaN7d4yI/fJkvgfDB9+au+iBJb6Pcz8ULBfe6
+D8HVvqKdORp6INzHz71z0sghxrQ0EAEkoWAZLh+kcn2ZHdcmZaBNUfjmGbyU6PRt
+RjdqoP+owIaC1aktBN7zl4uO7cRjlYFdusINrh2kPP02KAx2W84xjxX1uyj6oS6e
+7eBfvcwe8czW/N1rbE0CoR7h9+HnIrjnVG9RhBiZEiw3mUmF++Up26+4KTdRKbu3
++BL4yMpfd66z0+zzqu+HkvyLpFn5AgMBAAGjggL/MIIC+zAJBgNVHRMEAjAAMAsG
+A1UdDwQEAwIDqDATBgNVHSUEDDAKBggrBgEFBQcDATAdBgNVHQ4EFgQUy04I5guM
+drzfh2JQaXhgV86+4jUwHwYDVR0jBBgwFoAU60I00Jiwq5/0G2sI98xkLu8OLEUw
+LQYDVR0RBCYwJIISd3d3LmRuc3NlYy1leHAub3Jngg5kbnNzZWMtZXhwLm9yZzCC
+AUIGA1UdIASCATkwggE1MIIBMQYLKwYBBAGBtTcBAgIwggEgMC4GCCsGAQUFBwIB
+FiJodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS9wb2xpY3kucGRmMDQGCCsGAQUFBwIB
+FihodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS9pbnRlcm1lZGlhdGUucGRmMIG3Bggr
+BgEFBQcCAjCBqjAUFg1TdGFydENvbSBMdGQuMAMCAQEagZFMaW1pdGVkIExpYWJp
+bGl0eSwgc2VlIHNlY3Rpb24gKkxlZ2FsIExpbWl0YXRpb25zKiBvZiB0aGUgU3Rh
+cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUG9saWN5IGF2YWlsYWJsZSBh
+dCBodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS9wb2xpY3kucGRmMGEGA1UdHwRaMFgw
+KqAooCaGJGh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL2NydDEtY3JsLmNybDAqoCig
+JoYkaHR0cDovL2NybC5zdGFydHNzbC5jb20vY3J0MS1jcmwuY3JsMIGOBggrBgEF
+BQcBAQSBgTB/MDkGCCsGAQUFBzABhi1odHRwOi8vb2NzcC5zdGFydHNzbC5jb20v
+c3ViL2NsYXNzMS9zZXJ2ZXIvY2EwQgYIKwYBBQUHMAKGNmh0dHA6Ly93d3cuc3Rh
+cnRzc2wuY29tL2NlcnRzL3N1Yi5jbGFzczEuc2VydmVyLmNhLmNydDAjBgNVHRIE
+HDAahhhodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS8wDQYJKoZIhvcNAQEFBQADggEB
+ACXj6SB59KRJPenn6gUdGEqcta97U769SATyiQ87i9er64qLwvIGLMa3o2Rcgl2Y
+kghUeyLdN/EXyFBYA8L8uvZREPoc7EZukpT/ZDLXy9i2S0jkOxvF2fD/XLbcjGjM
+iEYG1/6ASw0ri9C0k4oDDoJLCoeH9++yqF7SFCCMcDkJqiAGXNb4euDpa8vCCtEQ
+CSS+ObZbfkreRt3cNCf5LfCXe9OsTnCfc8Cuq81c0oLaG+SmaLUQNBuToq8e9/Zm
++b+/a3RVjxmkV5OCcGVBxsXNDn54Q6wsdw0TBMcjwoEndzpLS7yWgFbbkq5ZiGpw
+Qibb2+CfKuQ+WFV1GkVQmVA=
+-----END CERTIFICATE-----`
+
+const startComIntermediate = `-----BEGIN CERTIFICATE-----
+MIIGNDCCBBygAwIBAgIBGDANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW
+MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg
+Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwHhcNMDcxMDI0MjA1NDE3WhcNMTcxMDI0MjA1NDE3WjCB
+jDELMAkGA1UEBhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0ZC4xKzApBgNVBAsT
+IlNlY3VyZSBEaWdpdGFsIENlcnRpZmljYXRlIFNpZ25pbmcxODA2BgNVBAMTL1N0
+YXJ0Q29tIENsYXNzIDEgUHJpbWFyeSBJbnRlcm1lZGlhdGUgU2VydmVyIENBMIIB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtonGrO8JUngHrJJj0PREGBiE
+gFYfka7hh/oyULTTRwbw5gdfcA4Q9x3AzhA2NIVaD5Ksg8asWFI/ujjo/OenJOJA
+pgh2wJJuniptTT9uYSAK21ne0n1jsz5G/vohURjXzTCm7QduO3CHtPn66+6CPAVv
+kvek3AowHpNz/gfK11+AnSJYUq4G2ouHI2mw5CrY6oPSvfNx23BaKA+vWjhwRRI/
+ME3NO68X5Q/LoKldSKqxYVDLNM08XMML6BDAjJvwAwNi/rJsPnIO7hxDKslIDlc5
+xDEhyBDBLIf+VJVSH1I8MRKbf+fAoKVZ1eKPPvDVqOHXcDGpxLPPr21TLwb0pwID
+AQABo4IBrTCCAakwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD
+VR0OBBYEFOtCNNCYsKuf9BtrCPfMZC7vDixFMB8GA1UdIwQYMBaAFE4L7xqkQFul
+F2mHMMo0aEPQQa7yMGYGCCsGAQUFBwEBBFowWDAnBggrBgEFBQcwAYYbaHR0cDov
+L29jc3Auc3RhcnRzc2wuY29tL2NhMC0GCCsGAQUFBzAChiFodHRwOi8vd3d3LnN0
+YXJ0c3NsLmNvbS9zZnNjYS5jcnQwWwYDVR0fBFQwUjAnoCWgI4YhaHR0cDovL3d3
+dy5zdGFydHNzbC5jb20vc2ZzY2EuY3JsMCegJaAjhiFodHRwOi8vY3JsLnN0YXJ0
+c3NsLmNvbS9zZnNjYS5jcmwwgYAGA1UdIAR5MHcwdQYLKwYBBAGBtTcBAgEwZjAu
+BggrBgEFBQcCARYiaHR0cDovL3d3dy5zdGFydHNzbC5jb20vcG9saWN5LnBkZjA0
+BggrBgEFBQcCARYoaHR0cDovL3d3dy5zdGFydHNzbC5jb20vaW50ZXJtZWRpYXRl
+LnBkZjANBgkqhkiG9w0BAQUFAAOCAgEAIQlJPqWIbuALi0jaMU2P91ZXouHTYlfp
+tVbzhUV1O+VQHwSL5qBaPucAroXQ+/8gA2TLrQLhxpFy+KNN1t7ozD+hiqLjfDen
+xk+PNdb01m4Ge90h2c9W/8swIkn+iQTzheWq8ecf6HWQTd35RvdCNPdFWAwRDYSw
+xtpdPvkBnufh2lWVvnQce/xNFE+sflVHfXv0pQ1JHpXo9xLBzP92piVH0PN1Nb6X
+t1gW66pceG/sUzCv6gRNzKkC4/C2BBL2MLERPZBOVmTX3DxDX3M570uvh+v2/miI
+RHLq0gfGabDBoYvvF0nXYbFFSF87ICHpW7LM9NfpMfULFWE7epTj69m8f5SuauNi
+YpaoZHy4h/OZMn6SolK+u/hlz8nyMPyLwcKmltdfieFcNID1j0cHL7SRv7Gifl9L
+WtBbnySGBVFaaQNlQ0lxxeBvlDRr9hvYqbBMflPrj0jfyjO1SPo2ShpTpjMM0InN
+SRXNiTE8kMBy12VLUjWKRhFEuT2OKGWmPnmeXAhEKa2wNREuIU640ucQPl2Eg7PD
+wuTSxv0JS3QJ3fGz0xk+gA2iCxnwOOfFwq/iI9th4p1cbiCJSS4jarJiwUW0n6+L
+p/EiO/h94pDQehn7Skzj0n1fSoMD7SfWI55rjbRZotnvbIIp3XUZPD9MEI3vu3Un
+0q6Dp6jOW6c=
+-----END CERTIFICATE-----`
+
+const startComRoot = `-----BEGIN CERTIFICATE-----
+MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW
+MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg
+Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM2WhcNMzYwOTE3MTk0NjM2WjB9
+MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi
+U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh
+cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA
+A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk
+pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf
+OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C
+Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT
+Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi
+HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM
+Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w
++2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+
+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3
+Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B
+26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID
+AQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE
+FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9j
+ZXJ0LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3Js
+LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFM
+BgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUHAgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0
+Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRwOi8vY2VydC5zdGFy
+dGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYgU3Rh
+cnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlh
+YmlsaXR5LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2Yg
+dGhlIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFp
+bGFibGUgYXQgaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL3BvbGljeS5wZGYwEQYJ
+YIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNT
+TCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAgEAFmyZ
+9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8
+jhvh3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUW
+FjgKXlf2Ysd6AgXmvB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJz
+ewT4F+irsfMuXGRuczE6Eri8sxHkfY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1
+ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3fsNrarnDy0RLrHiQi+fHLB5L
+EUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZEoalHmdkrQYu
+L6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq
+yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuC
+O3NJo2pXh5Tl1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6V
+um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh
+NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14=
+-----END CERTIFICATE-----`
diff --git a/src/pkg/crypto/x509/x509.go b/src/pkg/crypto/x509/x509.go
index 2a57f87..f2a039b 100644
--- a/src/pkg/crypto/x509/x509.go
+++ b/src/pkg/crypto/x509/x509.go
@@ -2,12 +2,13 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package parses X.509-encoded keys and certificates.
+// Package x509 parses X.509-encoded keys and certificates.
 package x509
 
 import (
 	"asn1"
 	"big"
+	"bytes"
 	"container/vector"
 	"crypto"
 	"crypto/rsa"
@@ -15,7 +16,6 @@ import (
 	"hash"
 	"io"
 	"os"
-	"strings"
 	"time"
 )
 
@@ -27,6 +27,20 @@ type pkcs1PrivateKey struct {
 	D       asn1.RawValue
 	P       asn1.RawValue
 	Q       asn1.RawValue
+	// We ignore these values, if present, because rsa will calculate them.
+	Dp   asn1.RawValue "optional"
+	Dq   asn1.RawValue "optional"
+	Qinv asn1.RawValue "optional"
+
+	AdditionalPrimes []pkcs1AddtionalRSAPrime "optional"
+}
+
+type pkcs1AddtionalRSAPrime struct {
+	Prime asn1.RawValue
+
+	// We ignore these values because rsa will calculate them.
+	Exp   asn1.RawValue
+	Coeff asn1.RawValue
 }
 
 // rawValueIsInteger returns true iff the given ASN.1 RawValue is an INTEGER type.
@@ -46,6 +60,10 @@ func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err os.Error) {
 		return
 	}
 
+	if priv.Version > 1 {
+		return nil, os.ErrorString("x509: unsupported private key version")
+	}
+
 	if !rawValueIsInteger(&priv.N) ||
 		!rawValueIsInteger(&priv.D) ||
 		!rawValueIsInteger(&priv.P) ||
@@ -61,26 +79,66 @@ func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err os.Error) {
 	}
 
 	key.D = new(big.Int).SetBytes(priv.D.Bytes)
-	key.P = new(big.Int).SetBytes(priv.P.Bytes)
-	key.Q = new(big.Int).SetBytes(priv.Q.Bytes)
+	key.Primes = make([]*big.Int, 2+len(priv.AdditionalPrimes))
+	key.Primes[0] = new(big.Int).SetBytes(priv.P.Bytes)
+	key.Primes[1] = new(big.Int).SetBytes(priv.Q.Bytes)
+	for i, a := range priv.AdditionalPrimes {
+		if !rawValueIsInteger(&a.Prime) {
+			return nil, asn1.StructuralError{"tags don't match"}
+		}
+		key.Primes[i+2] = new(big.Int).SetBytes(a.Prime.Bytes)
+		// We ignore the other two values because rsa will calculate
+		// them as needed.
+	}
 
 	err = key.Validate()
 	if err != nil {
 		return nil, err
 	}
+	key.Precompute()
 
 	return
 }
 
+// rawValueForBig returns an asn1.RawValue which represents the given integer.
+func rawValueForBig(n *big.Int) asn1.RawValue {
+	b := n.Bytes()
+	if n.Sign() >= 0 && len(b) > 0 && b[0]&0x80 != 0 {
+		// This positive number would be interpreted as a negative
+		// number in ASN.1 because the MSB is set.
+		padded := make([]byte, len(b)+1)
+		copy(padded[1:], b)
+		b = padded
+	}
+	return asn1.RawValue{Tag: 2, Bytes: b}
+}
+
 // MarshalPKCS1PrivateKey converts a private key to ASN.1 DER encoded form.
 func MarshalPKCS1PrivateKey(key *rsa.PrivateKey) []byte {
+	key.Precompute()
+
+	version := 0
+	if len(key.Primes) > 2 {
+		version = 1
+	}
+
 	priv := pkcs1PrivateKey{
-		Version: 1,
-		N:       asn1.RawValue{Tag: 2, Bytes: key.PublicKey.N.Bytes()},
+		Version: version,
+		N:       rawValueForBig(key.N),
 		E:       key.PublicKey.E,
-		D:       asn1.RawValue{Tag: 2, Bytes: key.D.Bytes()},
-		P:       asn1.RawValue{Tag: 2, Bytes: key.P.Bytes()},
-		Q:       asn1.RawValue{Tag: 2, Bytes: key.Q.Bytes()},
+		D:       rawValueForBig(key.D),
+		P:       rawValueForBig(key.Primes[0]),
+		Q:       rawValueForBig(key.Primes[1]),
+		Dp:      rawValueForBig(key.Precomputed.Dp),
+		Dq:      rawValueForBig(key.Precomputed.Dq),
+		Qinv:    rawValueForBig(key.Precomputed.Qinv),
+	}
+
+	priv.AdditionalPrimes = make([]pkcs1AddtionalRSAPrime, len(key.Precomputed.CRTValues))
+	for i, values := range key.Precomputed.CRTValues {
+		priv.AdditionalPrimes[i].Prime = rawValueForBig(key.Primes[2+i])
+		priv.AdditionalPrimes[i].Exp = rawValueForBig(values.Exp)
+		priv.AdditionalPrimes[i].Coeff = rawValueForBig(values.Coeff)
 	}
 
 	b, _ := asn1.Marshal(priv)
@@ -397,6 +455,10 @@ func (ConstraintViolationError) String() string {
 	return "invalid signature: parent certificate cannot sign this kind of certificate"
 }
 
+func (c *Certificate) Equal(other *Certificate) bool {
+	return bytes.Equal(c.Raw, other.Raw)
+}
+
 // CheckSignatureFrom verifies that the signature on c is a valid signature
 // from parent.
 func (c *Certificate) CheckSignatureFrom(parent *Certificate) (err os.Error) {
@@ -442,63 +504,6 @@ func (c *Certificate) CheckSignatureFrom(parent *Certificate) (err os.Error) {
 	return rsa.VerifyPKCS1v15(pub, hashType, digest, c.Signature)
 }
 
-func matchHostnames(pattern, host string) bool {
-	if len(pattern) == 0 || len(host) == 0 {
-		return false
-	}
-
-	patternParts := strings.Split(pattern, ".", -1)
-	hostParts := strings.Split(host, ".", -1)
-
-	if len(patternParts) != len(hostParts) {
-		return false
-	}
-
-	for i, patternPart := range patternParts {
-		if patternPart == "*" {
-			continue
-		}
-		if patternPart != hostParts[i] {
-			return false
-		}
-	}
-
-	return true
-}
-
-type HostnameError struct {
-	Certificate *Certificate
-	Host        string
-}
-
-func (h *HostnameError) String() string {
-	var valid string
-	c := h.Certificate
-	if len(c.DNSNames) > 0 {
-		valid = strings.Join(c.DNSNames, ", ")
-	} else {
-		valid = c.Subject.CommonName
-	}
-	return "certificate is valid for " + valid + ", not " + h.Host
-}
-
-// VerifyHostname returns nil if c is a valid certificate for the named host.
-// Otherwise it returns an os.Error describing the mismatch.
-func (c *Certificate) VerifyHostname(h string) os.Error {
-	if len(c.DNSNames) > 0 {
-		for _, match := range c.DNSNames {
-			if matchHostnames(match, h) {
-				return nil
-			}
-		}
-		// If Subject Alt Name is given, we ignore the common name.
-	} else if matchHostnames(c.Subject.CommonName, h) {
-		return nil
-	}
-
-	return &HostnameError{c, h}
-}
-
 type UnhandledCriticalExtension struct{}
 
 func (h UnhandledCriticalExtension) String() string {
diff --git a/src/pkg/crypto/x509/x509_test.go b/src/pkg/crypto/x509/x509_test.go
index d9511b8..a42113a 100644
--- a/src/pkg/crypto/x509/x509_test.go
+++ b/src/pkg/crypto/x509/x509_test.go
@@ -20,12 +20,13 @@ func TestParsePKCS1PrivateKey(t *testing.T) {
 	priv, err := ParsePKCS1PrivateKey(block.Bytes)
 	if err != nil {
 		t.Errorf("Failed to parse private key: %s", err)
+		return
 	}
 	if priv.PublicKey.N.Cmp(rsaPrivateKey.PublicKey.N) != 0 ||
 		priv.PublicKey.E != rsaPrivateKey.PublicKey.E ||
 		priv.D.Cmp(rsaPrivateKey.D) != 0 ||
-		priv.P.Cmp(rsaPrivateKey.P) != 0 ||
-		priv.Q.Cmp(rsaPrivateKey.Q) != 0 {
+		priv.Primes[0].Cmp(rsaPrivateKey.Primes[0]) != 0 ||
+		priv.Primes[1].Cmp(rsaPrivateKey.Primes[1]) != 0 {
 		t.Errorf("got:%+v want:%+v", priv, rsaPrivateKey)
 	}
 }
@@ -47,14 +48,54 @@ func bigFromString(s string) *big.Int {
 	return ret
 }
 
+func fromBase10(base10 string) *big.Int {
+	i := new(big.Int)
+	i.SetString(base10, 10)
+	return i
+}
+
 var rsaPrivateKey = &rsa.PrivateKey{
 	PublicKey: rsa.PublicKey{
 		N: bigFromString("9353930466774385905609975137998169297361893554149986716853295022578535724979677252958524466350471210367835187480748268864277464700638583474144061408845077"),
 		E: 65537,
 	},
 	D: bigFromString("7266398431328116344057699379749222532279343923819063639497049039389899328538543087657733766554155839834519529439851673014800261285757759040931985506583861"),
-	P: bigFromString("98920366548084643601728869055592650835572950932266967461790948584315647051443"),
-	Q: bigFromString("94560208308847015747498523884063394671606671904944666360068158221458669711639"),
+	Primes: []*big.Int{
+		bigFromString("98920366548084643601728869055592650835572950932266967461790948584315647051443"),
+		bigFromString("94560208308847015747498523884063394671606671904944666360068158221458669711639"),
+	},
+}
+
+func TestMarshalRSAPrivateKey(t *testing.T) {
+	priv := &rsa.PrivateKey{
+		PublicKey: rsa.PublicKey{
+			N: fromBase10("16346378922382193400538269749936049106320265317511766357599732575277382844051791096569333808598921852351577762718529818072849191122419410612033592401403764925096136759934497687765453905884149505175426053037420486697072448609022753683683718057795566811401938833367954642951433473337066311978821180526439641496973296037000052546108507805269279414789035461158073156772151892452251106173507240488993608650881929629163465099476849643165682709047462010581308719577053905787496296934240246311806555924593059995202856826239801816771116902778517096212527979497399966526283516447337775509777558018145573127308919204297111496233"),
+			E: 3,
+		},
+		D: fromBase10("10897585948254795600358846499957366070880176878341177571733155050184921896034527397712889205732614568234385175145686545381899460748279607074689061600935843283397424506622998458510302603922766336783617368686090042765718290914099334449154829375179958369993407724946186243249568928237086215759259909861748642124071874879861299389874230489928271621259294894142840428407196932444474088857746123104978617098858619445675532587787023228852383149557470077802718705420275739737958953794088728369933811184572620857678792001136676902250566845618813972833750098806496641114644760255910789397593428910198080271317419213080834885003"),
+		Primes: []*big.Int{
+			fromBase10("1025363189502892836833747188838978207017355117492483312747347695538428729137306368764177201532277413433182799108299960196606011786562992097313508180436744488171474690412562218914213688661311117337381958560443"),
+			fromBase10("3467903426626310123395340254094941045497208049900750380025518552334536945536837294961497712862519984786362199788654739924501424784631315081391467293694361474867825728031147665777546570788493758372218019373"),
+			fromBase10("4597024781409332673052708605078359346966325141767460991205742124888960305710298765592730135879076084498363772408626791576005136245060321874472727132746643162385746062759369754202494417496879741537284589047"),
+		},
+	}
+
+	derBytes := MarshalPKCS1PrivateKey(priv)
+
+	priv2, err := ParsePKCS1PrivateKey(derBytes)
+	if err != nil {
+		t.Errorf("error parsing serialized key: %s", err)
+		return
+	}
+	if priv.PublicKey.N.Cmp(priv2.PublicKey.N) != 0 ||
+		priv.PublicKey.E != priv2.PublicKey.E ||
+		priv.D.Cmp(priv2.D) != 0 ||
+		len(priv2.Primes) != 3 ||
+		priv.Primes[0].Cmp(priv2.Primes[0]) != 0 ||
+		priv.Primes[1].Cmp(priv2.Primes[1]) != 0 ||
+		priv.Primes[2].Cmp(priv2.Primes[2]) != 0 {
+		t.Errorf("got:%+v want:%+v", priv, priv2)
+	}
 }
 
 type matchHostnamesTest struct {
diff --git a/src/pkg/crypto/xtea/cipher.go b/src/pkg/crypto/xtea/cipher.go
index b0fa2a1..f2a5da0 100644
--- a/src/pkg/crypto/xtea/cipher.go
+++ b/src/pkg/crypto/xtea/cipher.go
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package implements XTEA encryption, as defined in Needham and
-// Wheeler's 1997 technical report, "Tea extensions."
+// Package xtea implements XTEA encryption, as defined in Needham and Wheeler's
+// 1997 technical report, "Tea extensions."
 package xtea
 
 // For details, see http://www.cix.co.uk/~klockstone/xtea.pdf
diff --git a/src/pkg/debug/dwarf/open.go b/src/pkg/debug/dwarf/open.go
index cb009e0..d9525f7 100644
--- a/src/pkg/debug/dwarf/open.go
+++ b/src/pkg/debug/dwarf/open.go
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package provides access to DWARF debugging information
-// loaded from executable files, as defined in the DWARF 2.0 Standard
-// at http://dwarfstd.org/doc/dwarf-2.0.0.pdf
+// Package dwarf provides access to DWARF debugging information loaded from
+// executable files, as defined in the DWARF 2.0 Standard at
+// http://dwarfstd.org/doc/dwarf-2.0.0.pdf
 package dwarf
 
 import (
diff --git a/src/pkg/debug/elf/elf.go b/src/pkg/debug/elf/elf.go
index 74e9799..5d45b24 100644
--- a/src/pkg/debug/elf/elf.go
+++ b/src/pkg/debug/elf/elf.go
@@ -330,29 +330,35 @@ func (i SectionIndex) GoString() string { return stringName(uint32(i), shnString
 type SectionType uint32
 
 const (
-	SHT_NULL          SectionType = 0          /* inactive */
-	SHT_PROGBITS      SectionType = 1          /* program defined information */
-	SHT_SYMTAB        SectionType = 2          /* symbol table section */
-	SHT_STRTAB        SectionType = 3          /* string table section */
-	SHT_RELA          SectionType = 4          /* relocation section with addends */
-	SHT_HASH          SectionType = 5          /* symbol hash table section */
-	SHT_DYNAMIC       SectionType = 6          /* dynamic section */
-	SHT_NOTE          SectionType = 7          /* note section */
-	SHT_NOBITS        SectionType = 8          /* no space section */
-	SHT_REL           SectionType = 9          /* relocation section - no addends */
-	SHT_SHLIB         SectionType = 10         /* reserved - purpose unknown */
-	SHT_DYNSYM        SectionType = 11         /* dynamic symbol table section */
-	SHT_INIT_ARRAY    SectionType = 14         /* Initialization function pointers. */
-	SHT_FINI_ARRAY    SectionType = 15         /* Termination function pointers. */
-	SHT_PREINIT_ARRAY SectionType = 16         /* Pre-initialization function ptrs. */
-	SHT_GROUP         SectionType = 17         /* Section group. */
-	SHT_SYMTAB_SHNDX  SectionType = 18         /* Section indexes (see SHN_XINDEX). */
-	SHT_LOOS          SectionType = 0x60000000 /* First of OS specific semantics */
-	SHT_HIOS          SectionType = 0x6fffffff /* Last of OS specific semantics */
-	SHT_LOPROC        SectionType = 0x70000000 /* reserved range for processor */
-	SHT_HIPROC        SectionType = 0x7fffffff /* specific section header types */
-	SHT_LOUSER        SectionType = 0x80000000 /* reserved range for application */
-	SHT_HIUSER        SectionType = 0xffffffff /* specific indexes */
+	SHT_NULL           SectionType = 0          /* inactive */
+	SHT_PROGBITS       SectionType = 1          /* program defined information */
+	SHT_SYMTAB         SectionType = 2          /* symbol table section */
+	SHT_STRTAB         SectionType = 3          /* string table section */
+	SHT_RELA           SectionType = 4          /* relocation section with addends */
+	SHT_HASH           SectionType = 5          /* symbol hash table section */
+	SHT_DYNAMIC        SectionType = 6          /* dynamic section */
+	SHT_NOTE           SectionType = 7          /* note section */
+	SHT_NOBITS         SectionType = 8          /* no space section */
+	SHT_REL            SectionType = 9          /* relocation section - no addends */
+	SHT_SHLIB          SectionType = 10         /* reserved - purpose unknown */
+	SHT_DYNSYM         SectionType = 11         /* dynamic symbol table section */
+	SHT_INIT_ARRAY     SectionType = 14         /* Initialization function pointers. */
+	SHT_FINI_ARRAY     SectionType = 15         /* Termination function pointers. */
+	SHT_PREINIT_ARRAY  SectionType = 16         /* Pre-initialization function ptrs. */
+	SHT_GROUP          SectionType = 17         /* Section group. */
+	SHT_SYMTAB_SHNDX   SectionType = 18         /* Section indexes (see SHN_XINDEX). */
+	SHT_LOOS           SectionType = 0x60000000 /* First of OS specific semantics */
+	SHT_GNU_ATTRIBUTES SectionType = 0x6ffffff5 /* GNU object attributes */
+	SHT_GNU_HASH       SectionType = 0x6ffffff6 /* GNU hash table */
+	SHT_GNU_LIBLIST    SectionType = 0x6ffffff7 /* GNU prelink library list */
+	SHT_GNU_VERDEF     SectionType = 0x6ffffffd /* GNU version definition section */
+	SHT_GNU_VERNEED    SectionType = 0x6ffffffe /* GNU version needs section */
+	SHT_GNU_VERSYM     SectionType = 0x6fffffff /* GNU version symbol table */
+	SHT_HIOS           SectionType = 0x6fffffff /* Last of OS specific semantics */
+	SHT_LOPROC         SectionType = 0x70000000 /* reserved range for processor */
+	SHT_HIPROC         SectionType = 0x7fffffff /* specific section header types */
+	SHT_LOUSER         SectionType = 0x80000000 /* reserved range for application */
+	SHT_HIUSER         SectionType = 0xffffffff /* specific indexes */
 )
 
 var shtStrings = []intName{
@@ -374,7 +380,12 @@ var shtStrings = []intName{
 	{17, "SHT_GROUP"},
 	{18, "SHT_SYMTAB_SHNDX"},
 	{0x60000000, "SHT_LOOS"},
-	{0x6fffffff, "SHT_HIOS"},
+	{0x6ffffff5, "SHT_GNU_ATTRIBUTES"},
+	{0x6ffffff6, "SHT_GNU_HASH"},
+	{0x6ffffff7, "SHT_GNU_LIBLIST"},
+	{0x6ffffffd, "SHT_GNU_VERDEF"},
+	{0x6ffffffe, "SHT_GNU_VERNEED"},
+	{0x6fffffff, "SHT_GNU_VERSYM"},
 	{0x70000000, "SHT_LOPROC"},
 	{0x7fffffff, "SHT_HIPROC"},
 	{0x80000000, "SHT_LOUSER"},
@@ -518,6 +529,9 @@ const (
 	DT_PREINIT_ARRAYSZ DynTag = 33         /* Size in bytes of the array of pre-initialization functions. */
 	DT_LOOS            DynTag = 0x6000000d /* First OS-specific */
 	DT_HIOS            DynTag = 0x6ffff000 /* Last OS-specific */
+	DT_VERSYM          DynTag = 0x6ffffff0
+	DT_VERNEED         DynTag = 0x6ffffffe
+	DT_VERNEEDNUM      DynTag = 0x6fffffff
 	DT_LOPROC          DynTag = 0x70000000 /* First processor-specific type. */
 	DT_HIPROC          DynTag = 0x7fffffff /* Last processor-specific type. */
 )
@@ -559,6 +573,9 @@ var dtStrings = []intName{
 	{33, "DT_PREINIT_ARRAYSZ"},
 	{0x6000000d, "DT_LOOS"},
 	{0x6ffff000, "DT_HIOS"},
+	{0x6ffffff0, "DT_VERSYM"},
+	{0x6ffffffe, "DT_VERNEED"},
+	{0x6fffffff, "DT_VERNEEDNUM"},
 	{0x70000000, "DT_LOPROC"},
 	{0x7fffffff, "DT_HIPROC"},
 }
diff --git a/src/pkg/debug/elf/file.go b/src/pkg/debug/elf/file.go
index 6fdcda6..9ae8b41 100644
--- a/src/pkg/debug/elf/file.go
+++ b/src/pkg/debug/elf/file.go
@@ -35,9 +35,11 @@ type FileHeader struct {
 // A File represents an open ELF file.
 type File struct {
 	FileHeader
-	Sections []*Section
-	Progs    []*Prog
-	closer   io.Closer
+	Sections  []*Section
+	Progs     []*Prog
+	closer    io.Closer
+	gnuNeed   []verneed
+	gnuVersym []byte
 }
 
 // A SectionHeader represents a single ELF section header.
@@ -329,8 +331,8 @@ func NewFile(r io.ReaderAt) (*File, os.Error) {
 }
 
 // getSymbols returns a slice of Symbols from parsing the symbol table
-// with the given type.
-func (f *File) getSymbols(typ SectionType) ([]Symbol, os.Error) {
+// with the given type, along with the associated string table.
+func (f *File) getSymbols(typ SectionType) ([]Symbol, []byte, os.Error) {
 	switch f.Class {
 	case ELFCLASS64:
 		return f.getSymbols64(typ)
@@ -339,27 +341,27 @@ func (f *File) getSymbols(typ SectionType) ([]Symbol, os.Error) {
 		return f.getSymbols32(typ)
 	}
 
-	return nil, os.ErrorString("not implemented")
+	return nil, nil, os.ErrorString("not implemented")
 }
 
-func (f *File) getSymbols32(typ SectionType) ([]Symbol, os.Error) {
+func (f *File) getSymbols32(typ SectionType) ([]Symbol, []byte, os.Error) {
 	symtabSection := f.SectionByType(typ)
 	if symtabSection == nil {
-		return nil, os.ErrorString("no symbol section")
+		return nil, nil, os.ErrorString("no symbol section")
 	}
 
 	data, err := symtabSection.Data()
 	if err != nil {
-		return nil, os.ErrorString("cannot load symbol section")
+		return nil, nil, os.ErrorString("cannot load symbol section")
 	}
 	symtab := bytes.NewBuffer(data)
 	if symtab.Len()%Sym32Size != 0 {
-		return nil, os.ErrorString("length of symbol section is not a multiple of SymSize")
+		return nil, nil, os.ErrorString("length of symbol section is not a multiple of SymSize")
 	}
 
 	strdata, err := f.stringTable(symtabSection.Link)
 	if err != nil {
-		return nil, os.ErrorString("cannot load string table section")
+		return nil, nil, os.ErrorString("cannot load string table section")
 	}
 
 	// The first entry is all zeros.
@@ -382,27 +384,27 @@ func (f *File) getSymbols32(typ SectionType) ([]Symbol, os.Error) {
 		i++
 	}
 
-	return symbols, nil
+	return symbols, strdata, nil
 }
 
-func (f *File) getSymbols64(typ SectionType) ([]Symbol, os.Error) {
+func (f *File) getSymbols64(typ SectionType) ([]Symbol, []byte, os.Error) {
 	symtabSection := f.SectionByType(typ)
 	if symtabSection == nil {
-		return nil, os.ErrorString("no symbol section")
+		return nil, nil, os.ErrorString("no symbol section")
 	}
 
 	data, err := symtabSection.Data()
 	if err != nil {
-		return nil, os.ErrorString("cannot load symbol section")
+		return nil, nil, os.ErrorString("cannot load symbol section")
 	}
 	symtab := bytes.NewBuffer(data)
 	if symtab.Len()%Sym64Size != 0 {
-		return nil, os.ErrorString("length of symbol section is not a multiple of Sym64Size")
+		return nil, nil, os.ErrorString("length of symbol section is not a multiple of Sym64Size")
 	}
 
 	strdata, err := f.stringTable(symtabSection.Link)
 	if err != nil {
-		return nil, os.ErrorString("cannot load string table section")
+		return nil, nil, os.ErrorString("cannot load string table section")
 	}
 
 	// The first entry is all zeros.
@@ -425,7 +427,7 @@ func (f *File) getSymbols64(typ SectionType) ([]Symbol, os.Error) {
 		i++
 	}
 
-	return symbols, nil
+	return symbols, strdata, nil
 }
 
 // getString extracts a string from an ELF string table.
@@ -468,7 +470,7 @@ func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) os.Error {
 		return os.ErrorString("length of relocation section is not a multiple of Sym64Size")
 	}
 
-	symbols, err := f.getSymbols(SHT_SYMTAB)
+	symbols, _, err := f.getSymbols(SHT_SYMTAB)
 	if err != nil {
 		return err
 	}
@@ -544,24 +546,123 @@ func (f *File) DWARF() (*dwarf.Data, os.Error) {
 	return dwarf.New(abbrev, nil, nil, info, nil, nil, nil, str)
 }
 
+type ImportedSymbol struct {
+	Name    string
+	Version string
+	Library string
+}
+
 // ImportedSymbols returns the names of all symbols
 // referred to by the binary f that are expected to be
 // satisfied by other libraries at dynamic load time.
 // It does not return weak symbols.
-func (f *File) ImportedSymbols() ([]string, os.Error) {
-	sym, err := f.getSymbols(SHT_DYNSYM)
+func (f *File) ImportedSymbols() ([]ImportedSymbol, os.Error) {
+	sym, str, err := f.getSymbols(SHT_DYNSYM)
 	if err != nil {
 		return nil, err
 	}
-	var all []string
-	for _, s := range sym {
+	f.gnuVersionInit(str)
+	var all []ImportedSymbol
+	for i, s := range sym {
 		if ST_BIND(s.Info) == STB_GLOBAL && s.Section == SHN_UNDEF {
-			all = append(all, s.Name)
+			all = append(all, ImportedSymbol{Name: s.Name})
+			f.gnuVersion(i, &all[len(all)-1])
 		}
 	}
 	return all, nil
 }
 
+type verneed struct {
+	File string
+	Name string
+}
+
+// gnuVersionInit parses the GNU version tables
+// for use by calls to gnuVersion.
+func (f *File) gnuVersionInit(str []byte) {
+	// Accumulate verneed information.
+	vn := f.SectionByType(SHT_GNU_VERNEED)
+	if vn == nil {
+		return
+	}
+	d, _ := vn.Data()
+
+	var need []verneed
+	i := 0
+	for {
+		if i+16 > len(d) {
+			break
+		}
+		vers := f.ByteOrder.Uint16(d[i : i+2])
+		if vers != 1 {
+			break
+		}
+		cnt := f.ByteOrder.Uint16(d[i+2 : i+4])
+		fileoff := f.ByteOrder.Uint32(d[i+4 : i+8])
+		aux := f.ByteOrder.Uint32(d[i+8 : i+12])
+		next := f.ByteOrder.Uint32(d[i+12 : i+16])
+		file, _ := getString(str, int(fileoff))
+
+		var name string
+		j := i + int(aux)
+		for c := 0; c < int(cnt); c++ {
+			if j+16 > len(d) {
+				break
+			}
+			// hash := f.ByteOrder.Uint32(d[j:j+4])
+			// flags := f.ByteOrder.Uint16(d[j+4:j+6])
+			other := f.ByteOrder.Uint16(d[j+6 : j+8])
+			nameoff := f.ByteOrder.Uint32(d[j+8 : j+12])
+			next := f.ByteOrder.Uint32(d[j+12 : j+16])
+			name, _ = getString(str, int(nameoff))
+			ndx := int(other)
+			if ndx >= len(need) {
+				a := make([]verneed, 2*(ndx+1))
+				copy(a, need)
+				need = a
+			}
+
+			need[ndx] = verneed{file, name}
+			if next == 0 {
+				break
+			}
+			j += int(next)
+		}
+
+		if next == 0 {
+			break
+		}
+		i += int(next)
+	}
+
+	// Versym parallels symbol table, indexing into verneed.
+	vs := f.SectionByType(SHT_GNU_VERSYM)
+	if vs == nil {
+		return
+	}
+	d, _ = vs.Data()
+
+	f.gnuNeed = need
+	f.gnuVersym = d
+}
+
+// gnuVersion adds Library and Version information to sym,
+// which came from offset i of the symbol table.
+func (f *File) gnuVersion(i int, sym *ImportedSymbol) {
+	// Each entry is two bytes; skip undef entry at beginning.
+	i = (i + 1) * 2
+	if i >= len(f.gnuVersym) {
+		return
+	}
+	j := int(f.ByteOrder.Uint16(f.gnuVersym[i:]))
+	if j < 2 || j >= len(f.gnuNeed) {
+		return
+	}
+	n := &f.gnuNeed[j]
+	sym.Library = n.File
+	sym.Version = n.Name
+}
+
 // ImportedLibraries returns the names of all libraries
 // referred to by the binary f that are expected to be
 // linked with the binary at dynamic link time.
diff --git a/src/pkg/ebnf/ebnf.go b/src/pkg/ebnf/ebnf.go
index e5aabd5..7918c45 100644
--- a/src/pkg/ebnf/ebnf.go
+++ b/src/pkg/ebnf/ebnf.go
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// A library for EBNF grammars. The input is text ([]byte) satisfying
-// the following grammar (represented itself in EBNF):
+// Package ebnf is a library for EBNF grammars. The input is text ([]byte)
+// satisfying the following grammar (represented itself in EBNF):
 //
 //	Production  = name "=" Expression "." .
 //	Expression  = Alternative { "|" Alternative } .
diff --git a/src/pkg/encoding/binary/binary.go b/src/pkg/encoding/binary/binary.go
index a4b3907..a01d0e0 100644
--- a/src/pkg/encoding/binary/binary.go
+++ b/src/pkg/encoding/binary/binary.go
@@ -126,7 +126,7 @@ func (bigEndian) GoString() string { return "binary.BigEndian" }
 // and written to successive fields of the data.
 func Read(r io.Reader, order ByteOrder, data interface{}) os.Error {
 	var v reflect.Value
-	switch d := reflect.NewValue(data); d.Kind() {
+	switch d := reflect.ValueOf(data); d.Kind() {
 	case reflect.Ptr:
 		v = d.Elem()
 	case reflect.Slice:
@@ -155,7 +155,7 @@ func Read(r io.Reader, order ByteOrder, data interface{}) os.Error {
 // Bytes written to w are encoded using the specified byte order
 // and read from successive fields of the data.
 func Write(w io.Writer, order ByteOrder, data interface{}) os.Error {
-	v := reflect.Indirect(reflect.NewValue(data))
+	v := reflect.Indirect(reflect.ValueOf(data))
 	size := TotalSize(v)
 	if size < 0 {
 		return os.NewError("binary.Write: invalid type " + v.Type().String())
diff --git a/src/pkg/encoding/binary/binary_test.go b/src/pkg/encoding/binary/binary_test.go
index d1fc1bf..7857c68 100644
--- a/src/pkg/encoding/binary/binary_test.go
+++ b/src/pkg/encoding/binary/binary_test.go
@@ -152,7 +152,7 @@ func TestWriteT(t *testing.T) {
 		t.Errorf("WriteT: have nil, want non-nil")
 	}
 
-	tv := reflect.Indirect(reflect.NewValue(ts))
+	tv := reflect.Indirect(reflect.ValueOf(ts))
 	for i, n := 0, tv.NumField(); i < n; i++ {
 		err = Write(buf, BigEndian, tv.Field(i).Interface())
 		if err == nil {
diff --git a/src/pkg/encoding/hex/hex.go b/src/pkg/encoding/hex/hex.go
index 292d917..891de18 100644
--- a/src/pkg/encoding/hex/hex.go
+++ b/src/pkg/encoding/hex/hex.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package implements hexadecimal encoding and decoding.
+// Package hex implements hexadecimal encoding and decoding.
 package hex
 
 import (
diff --git a/src/pkg/encoding/line/line.go b/src/pkg/encoding/line/line.go
index f46ce1c..123962b 100644
--- a/src/pkg/encoding/line/line.go
+++ b/src/pkg/encoding/line/line.go
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The line package implements a Reader that reads lines delimited by '\n' or ' \r\n'.
+// Package line implements a Reader that reads lines delimited by '\n' or
+// ' \r\n'.
 package line
 
 import (
diff --git a/src/pkg/encoding/pem/pem.go b/src/pkg/encoding/pem/pem.go
index 5653aeb..44e3d0a 100644
--- a/src/pkg/encoding/pem/pem.go
+++ b/src/pkg/encoding/pem/pem.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package implements the PEM data encoding, which originated in Privacy
+// Package pem implements the PEM data encoding, which originated in Privacy
 // Enhanced Mail. The most common use of PEM encoding today is in TLS keys and
 // certificates. See RFC 1421.
 package pem
diff --git a/src/pkg/exec/exec.go b/src/pkg/exec/exec.go
index 5398eb8..043f847 100644
--- a/src/pkg/exec/exec.go
+++ b/src/pkg/exec/exec.go
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The exec package runs external commands. It wraps os.StartProcess
-// to make it easier to remap stdin and stdout, connect I/O with pipes,
-// and do other adjustments.
+// Package exec runs external commands. It wraps os.StartProcess to make it
+// easier to remap stdin and stdout, connect I/O with pipes, and do other
+// adjustments.
 package exec
 
 // BUG(r): This package should be made even easier to use or merged into os.
diff --git a/src/pkg/exec/exec_test.go b/src/pkg/exec/exec_test.go
index 5e37b99..eb8cd5f 100644
--- a/src/pkg/exec/exec_test.go
+++ b/src/pkg/exec/exec_test.go
@@ -9,19 +9,14 @@ import (
 	"io/ioutil"
 	"testing"
 	"os"
-	"runtime"
 )
 
 func run(argv []string, stdin, stdout, stderr int) (p *Cmd, err os.Error) {
-	if runtime.GOOS == "windows" {
-		argv = append([]string{"cmd", "/c"}, argv...)
-	}
 	exe, err := LookPath(argv[0])
 	if err != nil {
 		return nil, err
 	}
-	p, err = Run(exe, argv, nil, "", stdin, stdout, stderr)
-	return p, err
+	return Run(exe, argv, nil, "", stdin, stdout, stderr)
 }
 
 func TestRunCat(t *testing.T) {
diff --git a/src/pkg/exp/datafmt/datafmt.go b/src/pkg/exp/datafmt/datafmt.go
index 6d816fc..a8efdc5 100644
--- a/src/pkg/exp/datafmt/datafmt.go
+++ b/src/pkg/exp/datafmt/datafmt.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-/*	The datafmt package implements syntax-directed, type-driven formatting
+/*	Package datafmt implements syntax-directed, type-driven formatting
 	of arbitrary data structures. Formatting a data structure consists of
 	two phases: first, a parser reads a format specification and builds a
 	"compiled" format. Then, the format can be applied repeatedly to
@@ -671,7 +671,7 @@ func (f Format) Eval(env Environment, args ...interface{}) ([]byte, os.Error) {
 
 	go func() {
 		for _, v := range args {
-			fld := reflect.NewValue(v)
+			fld := reflect.ValueOf(v)
 			if !fld.IsValid() {
 				errors <- os.NewError("nil argument")
 				return
diff --git a/src/pkg/exp/draw/x11/conn.go b/src/pkg/exp/draw/x11/conn.go
index 53294af..81c6726 100644
--- a/src/pkg/exp/draw/x11/conn.go
+++ b/src/pkg/exp/draw/x11/conn.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package implements an X11 backend for the exp/draw package.
+// Package x11 implements an X11 backend for the exp/draw package.
 //
 // The X protocol specification is at ftp://ftp.x.org/pub/X11R7.0/doc/PDF/proto.pdf.
 // A summary of the wire format can be found in XCB's xproto.xml.
diff --git a/src/pkg/exp/eval/bridge.go b/src/pkg/exp/eval/bridge.go
index d1efa2e..f31d9ab 100644
--- a/src/pkg/exp/eval/bridge.go
+++ b/src/pkg/exp/eval/bridge.go
@@ -128,7 +128,7 @@ func TypeFromNative(t reflect.Type) Type {
 }
 
 // TypeOfNative returns the interpreter Type of a regular Go value.
-func TypeOfNative(v interface{}) Type { return TypeFromNative(reflect.Typeof(v)) }
+func TypeOfNative(v interface{}) Type { return TypeFromNative(reflect.TypeOf(v)) }
 
 /*
  * Function bridging
diff --git a/src/pkg/exp/eval/type.go b/src/pkg/exp/eval/type.go
index 0d6dfe9..8a93d8a 100644
--- a/src/pkg/exp/eval/type.go
+++ b/src/pkg/exp/eval/type.go
@@ -86,7 +86,7 @@ func hashTypeArray(key []Type) uintptr {
 		if t == nil {
 			continue
 		}
-		addr := reflect.NewValue(t).Pointer()
+		addr := reflect.ValueOf(t).Pointer()
 		hash ^= addr
 	}
 	return hash
diff --git a/src/pkg/exp/eval/world.go b/src/pkg/exp/eval/world.go
index 02d18bd..a5f6ac7 100644
--- a/src/pkg/exp/eval/world.go
+++ b/src/pkg/exp/eval/world.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package is the beginning of an interpreter for Go.
+// Package eval is the beginning of an interpreter for Go.
 // It can run simple Go programs but does not implement
 // interface values or packages.
 package eval
diff --git a/src/pkg/exp/ogle/cmd.go b/src/pkg/exp/ogle/cmd.go
index 813d3a8..a8db523 100644
--- a/src/pkg/exp/ogle/cmd.go
+++ b/src/pkg/exp/ogle/cmd.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Ogle is the beginning of a debugger for Go.
+// Package ogle is the beginning of a debugger for Go.
 package ogle
 
 import (
diff --git a/src/pkg/exp/ogle/process.go b/src/pkg/exp/ogle/process.go
index e4f44b6..7c803b3 100644
--- a/src/pkg/exp/ogle/process.go
+++ b/src/pkg/exp/ogle/process.go
@@ -226,7 +226,7 @@ func (p *Process) bootstrap() {
 	p.runtime.G = newManualType(eval.TypeOfNative(rt1G{}), p.Arch)
 
 	// Get addresses of type.*runtime.XType for discrimination.
-	rtv := reflect.Indirect(reflect.NewValue(&p.runtime))
+	rtv := reflect.Indirect(reflect.ValueOf(&p.runtime))
 	rtvt := rtv.Type()
 	for i := 0; i < rtv.NumField(); i++ {
 		n := rtvt.Field(i).Name
diff --git a/src/pkg/exp/ogle/rruntime.go b/src/pkg/exp/ogle/rruntime.go
index e234f31..950418b 100644
--- a/src/pkg/exp/ogle/rruntime.go
+++ b/src/pkg/exp/ogle/rruntime.go
@@ -236,9 +236,9 @@ type runtimeValues struct {
 // indexes gathered from the remoteTypes recorded in a runtimeValues
 // structure.
 func fillRuntimeIndexes(runtime *runtimeValues, out *runtimeIndexes) {
-	outv := reflect.Indirect(reflect.NewValue(out))
+	outv := reflect.Indirect(reflect.ValueOf(out))
 	outt := outv.Type()
-	runtimev := reflect.Indirect(reflect.NewValue(runtime))
+	runtimev := reflect.Indirect(reflect.ValueOf(runtime))
 
 	// out contains fields corresponding to each runtime type
 	for i := 0; i < outt.NumField(); i++ {
diff --git a/src/pkg/expvar/expvar.go b/src/pkg/expvar/expvar.go
index ed6cff7..7123d4b 100644
--- a/src/pkg/expvar/expvar.go
+++ b/src/pkg/expvar/expvar.go
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The expvar package provides a standardized interface to public variables,
-// such as operation counters in servers. It exposes these variables via
-// HTTP at /debug/vars in JSON format.
+// Package expvar provides a standardized interface to public variables, such
+// as operation counters in servers. It exposes these variables via HTTP at
+// /debug/vars in JSON format.
 //
 // Operations to set or modify these public variables are atomic.
 //
@@ -180,23 +180,14 @@ func (v *String) String() string { return strconv.Quote(v.s) }
 
 func (v *String) Set(value string) { v.s = value }
 
-// IntFunc wraps a func() int64 to create a value that satisfies the Var interface.
-// The function will be called each time the Var is evaluated.
-type IntFunc func() int64
+// Func implements Var by calling the function
+// and formatting the returned value using JSON.
+type Func func() interface{}
 
-func (v IntFunc) String() string { return strconv.Itoa64(v()) }
-
-// FloatFunc wraps a func() float64 to create a value that satisfies the Var interface.
-// The function will be called each time the Var is evaluated.
-type FloatFunc func() float64
-
-func (v FloatFunc) String() string { return strconv.Ftoa64(v(), 'g', -1) }
-
-// StringFunc wraps a func() string to create value that satisfies the Var interface.
-// The function will be called each time the Var is evaluated.
-type StringFunc func() string
-
-func (f StringFunc) String() string { return strconv.Quote(f()) }
+func (f Func) String() string {
+	v, _ := json.Marshal(f())
+	return string(v)
+}
 
 
 // All published variables.
@@ -282,18 +273,16 @@ func expvarHandler(w http.ResponseWriter, r *http.Request) {
 	fmt.Fprintf(w, "\n}\n")
 }
 
-func memstats() string {
-	b, _ := json.MarshalIndent(&runtime.MemStats, "", "\t")
-	return string(b)
+func cmdline() interface{} {
+	return os.Args
 }
 
-func cmdline() string {
-	b, _ := json.Marshal(os.Args)
-	return string(b)
+func memstats() interface{} {
+	return runtime.MemStats
 }
 
 func init() {
 	http.Handle("/debug/vars", http.HandlerFunc(expvarHandler))
-	Publish("cmdline", StringFunc(cmdline))
-	Publish("memstats", StringFunc(memstats))
+	Publish("cmdline", Func(cmdline))
+	Publish("memstats", Func(memstats))
 }
diff --git a/src/pkg/expvar/expvar_test.go b/src/pkg/expvar/expvar_test.go
index a8b1a96..94926d9 100644
--- a/src/pkg/expvar/expvar_test.go
+++ b/src/pkg/expvar/expvar_test.go
@@ -114,41 +114,15 @@ func TestMapCounter(t *testing.T) {
 	}
 }
 
-func TestIntFunc(t *testing.T) {
-	x := int64(4)
-	ix := IntFunc(func() int64 { return x })
-	if s := ix.String(); s != "4" {
-		t.Errorf("ix.String() = %v, want 4", s)
+func TestFunc(t *testing.T) {
+	var x interface{} = []string{"a", "b"}
+	f := Func(func() interface{} { return x })
+	if s, exp := f.String(), `["a","b"]`; s != exp {
+		t.Errorf(`f.String() = %q, want %q`, s, exp)
 	}
 
-	x++
-	if s := ix.String(); s != "5" {
-		t.Errorf("ix.String() = %v, want 5", s)
-	}
-}
-
-func TestFloatFunc(t *testing.T) {
-	x := 8.5
-	ix := FloatFunc(func() float64 { return x })
-	if s := ix.String(); s != "8.5" {
-		t.Errorf("ix.String() = %v, want 3.14", s)
-	}
-
-	x -= 1.25
-	if s := ix.String(); s != "7.25" {
-		t.Errorf("ix.String() = %v, want 4.34", s)
-	}
-}
-
-func TestStringFunc(t *testing.T) {
-	x := "hello"
-	sx := StringFunc(func() string { return x })
-	if s, exp := sx.String(), `"hello"`; s != exp {
-		t.Errorf(`sx.String() = %q, want %q`, s, exp)
-	}
-
-	x = "goodbye"
-	if s, exp := sx.String(), `"goodbye"`; s != exp {
-		t.Errorf(`sx.String() = %q, want %q`, s, exp)
+	x = 17
+	if s, exp := f.String(), `17`; s != exp {
+		t.Errorf(`f.String() = %q, want %q`, s, exp)
 	}
 }
diff --git a/src/pkg/flag/flag.go b/src/pkg/flag/flag.go
index 19a3104..9ed20e0 100644
--- a/src/pkg/flag/flag.go
+++ b/src/pkg/flag/flag.go
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 /*
-	The flag package implements command-line flag parsing.
+	Package flag implements command-line flag parsing.
 
 	Usage:
 
diff --git a/src/pkg/fmt/doc.go b/src/pkg/fmt/doc.go
index 77ee62b..e4d4f18 100644
--- a/src/pkg/fmt/doc.go
+++ b/src/pkg/fmt/doc.go
@@ -27,7 +27,7 @@
 		%o	base 8
 		%x	base 16, with lower-case letters for a-f
 		%X	base 16, with upper-case letters for A-F
-		%U	Unicode format: U+1234; same as "U+%x" with 4 digits default
+		%U	Unicode format: U+1234; same as "U+%0.4X"
 	Floating-point and complex constituents:
 		%b	decimalless scientific notation with exponent a power
 			of two, in the manner of strconv.Ftoa32, e.g. -123456p-78
diff --git a/src/pkg/fmt/print.go b/src/pkg/fmt/print.go
index 7fca6af..10e0fe7 100644
--- a/src/pkg/fmt/print.go
+++ b/src/pkg/fmt/print.go
@@ -260,7 +260,7 @@ func getField(v reflect.Value, i int) reflect.Value {
 	val := v.Field(i)
 	if i := val; i.Kind() == reflect.Interface {
 		if inter := i.Interface(); inter != nil {
-			return reflect.NewValue(inter)
+			return reflect.ValueOf(inter)
 		}
 	}
 	return val
@@ -284,7 +284,7 @@ func (p *pp) unknownType(v interface{}) {
 		return
 	}
 	p.buf.WriteByte('?')
-	p.buf.WriteString(reflect.Typeof(v).String())
+	p.buf.WriteString(reflect.TypeOf(v).String())
 	p.buf.WriteByte('?')
 }
 
@@ -296,7 +296,7 @@ func (p *pp) badVerb(verb int, val interface{}) {
 	if val == nil {
 		p.buf.Write(nilAngleBytes)
 	} else {
-		p.buf.WriteString(reflect.Typeof(val).String())
+		p.buf.WriteString(reflect.TypeOf(val).String())
 		p.add('=')
 		p.printField(val, 'v', false, false, 0)
 	}
@@ -527,7 +527,7 @@ func (p *pp) fmtPointer(field interface{}, value reflect.Value, verb int, goSynt
 	}
 	if goSyntax {
 		p.add('(')
-		p.buf.WriteString(reflect.Typeof(field).String())
+		p.buf.WriteString(reflect.TypeOf(field).String())
 		p.add(')')
 		p.add('(')
 		if u == 0 {
@@ -542,10 +542,10 @@ func (p *pp) fmtPointer(field interface{}, value reflect.Value, verb int, goSynt
 }
 
 var (
-	intBits     = reflect.Typeof(0).Bits()
-	floatBits   = reflect.Typeof(0.0).Bits()
-	complexBits = reflect.Typeof(1i).Bits()
-	uintptrBits = reflect.Typeof(uintptr(0)).Bits()
+	intBits     = reflect.TypeOf(0).Bits()
+	floatBits   = reflect.TypeOf(0.0).Bits()
+	complexBits = reflect.TypeOf(1i).Bits()
+	uintptrBits = reflect.TypeOf(uintptr(0)).Bits()
 )
 
 func (p *pp) printField(field interface{}, verb int, plus, goSyntax bool, depth int) (wasString bool) {
@@ -562,10 +562,10 @@ func (p *pp) printField(field interface{}, verb int, plus, goSyntax bool, depth
 	// %T (the value's type) and %p (its address) are special; we always do them first.
 	switch verb {
 	case 'T':
-		p.printField(reflect.Typeof(field).String(), 's', false, false, 0)
+		p.printField(reflect.TypeOf(field).String(), 's', false, false, 0)
 		return false
 	case 'p':
-		p.fmtPointer(field, reflect.NewValue(field), verb, goSyntax)
+		p.fmtPointer(field, reflect.ValueOf(field), verb, goSyntax)
 		return false
 	}
 	// Is it a Formatter?
@@ -653,7 +653,7 @@ func (p *pp) printField(field interface{}, verb int, plus, goSyntax bool, depth
 	}
 
 	// Need to use reflection
-	value := reflect.NewValue(field)
+	value := reflect.ValueOf(field)
 
 BigSwitch:
 	switch f := value; f.Kind() {
@@ -704,7 +704,7 @@ BigSwitch:
 		}
 	case reflect.Struct:
 		if goSyntax {
-			p.buf.WriteString(reflect.Typeof(field).String())
+			p.buf.WriteString(reflect.TypeOf(field).String())
 		}
 		p.add('{')
 		v := f
@@ -730,7 +730,7 @@ BigSwitch:
 		value := f.Elem()
 		if !value.IsValid() {
 			if goSyntax {
-				p.buf.WriteString(reflect.Typeof(field).String())
+				p.buf.WriteString(reflect.TypeOf(field).String())
 				p.buf.Write(nilParenBytes)
 			} else {
 				p.buf.Write(nilAngleBytes)
@@ -756,7 +756,7 @@ BigSwitch:
 			return verb == 's'
 		}
 		if goSyntax {
-			p.buf.WriteString(reflect.Typeof(field).String())
+			p.buf.WriteString(reflect.TypeOf(field).String())
 			p.buf.WriteByte('{')
 		} else {
 			p.buf.WriteByte('[')
@@ -794,7 +794,7 @@ BigSwitch:
 		}
 		if goSyntax {
 			p.buf.WriteByte('(')
-			p.buf.WriteString(reflect.Typeof(field).String())
+			p.buf.WriteString(reflect.TypeOf(field).String())
 			p.buf.WriteByte(')')
 			p.buf.WriteByte('(')
 			if v == 0 {
@@ -915,7 +915,7 @@ func (p *pp) doPrintf(format string, a []interface{}) {
 		for ; fieldnum < len(a); fieldnum++ {
 			field := a[fieldnum]
 			if field != nil {
-				p.buf.WriteString(reflect.Typeof(field).String())
+				p.buf.WriteString(reflect.TypeOf(field).String())
 				p.buf.WriteByte('=')
 			}
 			p.printField(field, 'v', false, false, 0)
@@ -934,7 +934,7 @@ func (p *pp) doPrint(a []interface{}, addspace, addnewline bool) {
 		// always add spaces if we're doing println
 		field := a[fieldnum]
 		if fieldnum > 0 {
-			isString := field != nil && reflect.Typeof(field).Kind() == reflect.String
+			isString := field != nil && reflect.TypeOf(field).Kind() == reflect.String
 			if addspace || !isString && !prevString {
 				p.buf.WriteByte(' ')
 			}
diff --git a/src/pkg/fmt/scan.go b/src/pkg/fmt/scan.go
index b1b3975..42bc52c 100644
--- a/src/pkg/fmt/scan.go
+++ b/src/pkg/fmt/scan.go
@@ -423,7 +423,7 @@ func (s *ss) token(skipSpace bool, f func(int) bool) []byte {
 
 // typeError indicates that the type of the operand did not match the format
 func (s *ss) typeError(field interface{}, expected string) {
-	s.errorString("expected field of type pointer to " + expected + "; found " + reflect.Typeof(field).String())
+	s.errorString("expected field of type pointer to " + expected + "; found " + reflect.TypeOf(field).String())
 }
 
 var complexError = os.ErrorString("syntax error scanning complex number")
@@ -908,7 +908,7 @@ func (s *ss) scanOne(verb int, field interface{}) {
 		// If we scanned to bytes, the slice would point at the buffer.
 		*v = []byte(s.convertString(verb))
 	default:
-		val := reflect.NewValue(v)
+		val := reflect.ValueOf(v)
 		ptr := val
 		if ptr.Kind() != reflect.Ptr {
 			s.errorString("Scan: type not a pointer: " + val.Type().String())
diff --git a/src/pkg/fmt/scan_test.go b/src/pkg/fmt/scan_test.go
index b8b3ac9..da13eb2 100644
--- a/src/pkg/fmt/scan_test.go
+++ b/src/pkg/fmt/scan_test.go
@@ -370,7 +370,7 @@ func testScan(name string, t *testing.T, scan func(r io.Reader, a ...interface{}
 			continue
 		}
 		// The incoming value may be a pointer
-		v := reflect.NewValue(test.in)
+		v := reflect.ValueOf(test.in)
 		if p := v; p.Kind() == reflect.Ptr {
 			v = p.Elem()
 		}
@@ -409,7 +409,7 @@ func TestScanf(t *testing.T) {
 			continue
 		}
 		// The incoming value may be a pointer
-		v := reflect.NewValue(test.in)
+		v := reflect.ValueOf(test.in)
 		if p := v; p.Kind() == reflect.Ptr {
 			v = p.Elem()
 		}
@@ -486,7 +486,7 @@ func TestInf(t *testing.T) {
 }
 
 func testScanfMulti(name string, t *testing.T) {
-	sliceType := reflect.Typeof(make([]interface{}, 1))
+	sliceType := reflect.TypeOf(make([]interface{}, 1))
 	for _, test := range multiTests {
 		var r io.Reader
 		if name == "StringReader" {
@@ -513,7 +513,7 @@ func testScanfMulti(name string, t *testing.T) {
 		// Convert the slice of pointers into a slice of values
 		resultVal := reflect.MakeSlice(sliceType, n, n)
 		for i := 0; i < n; i++ {
-			v := reflect.NewValue(test.in[i]).Elem()
+			v := reflect.ValueOf(test.in[i]).Elem()
 			resultVal.Index(i).Set(v)
 		}
 		result := resultVal.Interface()
@@ -810,7 +810,9 @@ func TestScanInts(t *testing.T) {
 	})
 }
 
-const intCount = 1000
+// 800 is small enough to not overflow the stack when using gccgo on a
+// platform that does not support split stack.
+const intCount = 800
 
 func testScanInts(t *testing.T, scan func(*RecursiveInt, *bytes.Buffer) os.Error) {
 	r := new(RecursiveInt)
diff --git a/src/pkg/go/ast/ast.go b/src/pkg/go/ast/ast.go
index ed3e2cd..2fc1a60 100644
--- a/src/pkg/go/ast/ast.go
+++ b/src/pkg/go/ast/ast.go
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The AST package declares the types used to represent
-// syntax trees for Go packages.
+// Package ast declares the types used to represent syntax trees for Go
+// packages.
 //
 package ast
 
diff --git a/src/pkg/go/ast/print.go b/src/pkg/go/ast/print.go
index e6d4e83..81e1da1 100644
--- a/src/pkg/go/ast/print.go
+++ b/src/pkg/go/ast/print.go
@@ -62,7 +62,7 @@ func Fprint(w io.Writer, fset *token.FileSet, x interface{}, f FieldFilter) (n i
 		p.printf("nil\n")
 		return
 	}
-	p.print(reflect.NewValue(x))
+	p.print(reflect.ValueOf(x))
 	p.printf("\n")
 
 	return
diff --git a/src/pkg/go/doc/doc.go b/src/pkg/go/doc/doc.go
index e7a8d3f..29d205d 100644
--- a/src/pkg/go/doc/doc.go
+++ b/src/pkg/go/doc/doc.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The doc package extracts source code documentation from a Go AST.
+// Package doc extracts source code documentation from a Go AST.
 package doc
 
 import (
diff --git a/src/pkg/go/parser/parser.go b/src/pkg/go/parser/parser.go
index 84a0da6..5c57e41 100644
--- a/src/pkg/go/parser/parser.go
+++ b/src/pkg/go/parser/parser.go
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// A parser for Go source files. Input may be provided in a variety of
-// forms (see the various Parse* functions); the output is an abstract
-// syntax tree (AST) representing the Go source. The parser is invoked
-// through one of the Parse* functions.
+// Package parser implements a parser for Go source files. Input may be
+// provided in a variety of forms (see the various Parse* functions); the
+// output is an abstract syntax tree (AST) representing the Go source. The
+// parser is invoked through one of the Parse* functions.
 //
 package parser
 
diff --git a/src/pkg/go/printer/printer.go b/src/pkg/go/printer/printer.go
index 697a83f..01ebf78 100644
--- a/src/pkg/go/printer/printer.go
+++ b/src/pkg/go/printer/printer.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The printer package implements printing of AST nodes.
+// Package printer implements printing of AST nodes.
 package printer
 
 import (
diff --git a/src/pkg/go/scanner/scanner.go b/src/pkg/go/scanner/scanner.go
index 2f949ad..07b7454 100644
--- a/src/pkg/go/scanner/scanner.go
+++ b/src/pkg/go/scanner/scanner.go
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// A scanner for Go source text. Takes a []byte as source which can
-// then be tokenized through repeated calls to the Scan function.
-// Typical use:
+// Package scanner implements a scanner for Go source text. Takes a []byte as
+// source which can then be tokenized through repeated calls to the Scan
+// function. Typical use:
 //
 //	var s Scanner
 //	fset := token.NewFileSet()  // position information is relative to fset
diff --git a/src/pkg/go/token/token.go b/src/pkg/go/token/token.go
index a5f21df..c2ec80a 100644
--- a/src/pkg/go/token/token.go
+++ b/src/pkg/go/token/token.go
@@ -2,9 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package defines constants representing the lexical
-// tokens of the Go programming language and basic operations
-// on tokens (printing, predicates).
+// Package token defines constants representing the lexical tokens of the Go
+// programming language and basic operations on tokens (printing, predicates).
 //
 package token
 
diff --git a/src/pkg/go/types/gcimporter.go b/src/pkg/go/types/gcimporter.go
index 9e0ae62..30adc04 100644
--- a/src/pkg/go/types/gcimporter.go
+++ b/src/pkg/go/types/gcimporter.go
@@ -461,7 +461,13 @@ func (p *gcParser) parseFuncType() Type {
 // MethodSpec = identifier Signature .
 //
 func (p *gcParser) parseMethodSpec(scope *ast.Scope) {
-	p.expect(scanner.Ident)
+	if p.tok == scanner.Ident {
+		p.expect(scanner.Ident)
+	} else {
+		p.parsePkgId()
+		p.expect('.')
+		p.parseDotIdent()
+	}
 	isVariadic := false
 	p.parseSignature(scope, &isVariadic)
 }
diff --git a/src/pkg/go/types/types.go b/src/pkg/go/types/types.go
index 72384e1..2ee645d 100644
--- a/src/pkg/go/types/types.go
+++ b/src/pkg/go/types/types.go
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // PACKAGE UNDER CONSTRUCTION. ANY AND ALL PARTS MAY CHANGE.
-// The types package declares the types used to represent Go types.
+// Package types declares the types used to represent Go types.
 //
 package types
 
diff --git a/src/pkg/gob/codec_test.go b/src/pkg/gob/codec_test.go
index 28042cc..8961336 100644
--- a/src/pkg/gob/codec_test.go
+++ b/src/pkg/gob/codec_test.go
@@ -999,13 +999,12 @@ type Bad0 struct {
 	C  float64
 }
 
-
 func TestInvalidField(t *testing.T) {
 	var bad0 Bad0
 	bad0.CH = make(chan int)
 	b := new(bytes.Buffer)
 	dummyEncoder := new(Encoder) // sufficient for this purpose.
-	dummyEncoder.encode(b, reflect.NewValue(&bad0), userType(reflect.Typeof(&bad0)))
+	dummyEncoder.encode(b, reflect.ValueOf(&bad0), userType(reflect.TypeOf(&bad0)))
 	if err := dummyEncoder.err; err == nil {
 		t.Error("expected error; got none")
 	} else if strings.Index(err.String(), "type") < 0 {
diff --git a/src/pkg/gob/debug.go b/src/pkg/gob/debug.go
index 69c83bd..79aee77 100644
--- a/src/pkg/gob/debug.go
+++ b/src/pkg/gob/debug.go
@@ -335,7 +335,7 @@ func (deb *debugger) string() string {
 func (deb *debugger) delta(expect int) int {
 	delta := int(deb.uint64())
 	if delta < 0 || (expect >= 0 && delta != expect) {
-		errorf("gob decode: corrupted type: delta %d expected %d", delta, expect)
+		errorf("decode: corrupted type: delta %d expected %d", delta, expect)
 	}
 	return delta
 }
diff --git a/src/pkg/gob/decode.go b/src/pkg/gob/decode.go
index 51fac79..0e86df6 100644
--- a/src/pkg/gob/decode.go
+++ b/src/pkg/gob/decode.go
@@ -406,7 +406,7 @@ func decUint8Array(i *decInstr, state *decoderState, p unsafe.Pointer) {
 func decString(i *decInstr, state *decoderState, p unsafe.Pointer) {
 	if i.indir > 0 {
 		if *(*unsafe.Pointer)(p) == nil {
-			*(*unsafe.Pointer)(p) = unsafe.Pointer(new([]byte))
+			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(string))
 		}
 		p = *(*unsafe.Pointer)(p)
 	}
@@ -468,7 +468,7 @@ func (dec *Decoder) decodeSingle(engine *decEngine, ut *userTypeInfo, p uintptr)
 	basep := p
 	delta := int(state.decodeUint())
 	if delta != 0 {
-		errorf("gob decode: corrupted data: non-zero delta for singleton")
+		errorf("decode: corrupted data: non-zero delta for singleton")
 	}
 	instr := &engine.instr[singletonField]
 	ptr := unsafe.Pointer(basep) // offset will be zero
@@ -493,7 +493,7 @@ func (dec *Decoder) decodeStruct(engine *decEngine, ut *userTypeInfo, p uintptr,
 	for state.b.Len() > 0 {
 		delta := int(state.decodeUint())
 		if delta < 0 {
-			errorf("gob decode: corrupted data: negative delta")
+			errorf("decode: corrupted data: negative delta")
 		}
 		if delta == 0 { // struct terminator is zero delta fieldnum
 			break
@@ -521,7 +521,7 @@ func (dec *Decoder) ignoreStruct(engine *decEngine) {
 	for state.b.Len() > 0 {
 		delta := int(state.decodeUint())
 		if delta < 0 {
-			errorf("gob ignore decode: corrupted data: negative delta")
+			errorf("ignore decode: corrupted data: negative delta")
 		}
 		if delta == 0 { // struct terminator is zero delta fieldnum
 			break
@@ -544,7 +544,7 @@ func (dec *Decoder) ignoreSingle(engine *decEngine) {
 	state.fieldnum = singletonField
 	delta := int(state.decodeUint())
 	if delta != 0 {
-		errorf("gob decode: corrupted data: non-zero delta for singleton")
+		errorf("decode: corrupted data: non-zero delta for singleton")
 	}
 	instr := &engine.instr[singletonField]
 	instr.op(instr, state, unsafe.Pointer(nil))
@@ -572,7 +572,7 @@ func (dec *Decoder) decodeArray(atyp reflect.Type, state *decoderState, p uintpt
 		p = allocate(atyp, p, 1) // All but the last level has been allocated by dec.Indirect
 	}
 	if n := state.decodeUint(); n != uint64(length) {
-		errorf("gob: length mismatch in decodeArray")
+		errorf("length mismatch in decodeArray")
 	}
 	dec.decodeArrayHelper(state, p, elemOp, elemWid, length, elemIndir, ovfl)
 }
@@ -581,7 +581,7 @@ func (dec *Decoder) decodeArray(atyp reflect.Type, state *decoderState, p uintpt
 // unlike the other items we can't use a pointer directly.
 func decodeIntoValue(state *decoderState, op decOp, indir int, v reflect.Value, ovfl os.ErrorString) reflect.Value {
 	instr := &decInstr{op, 0, indir, 0, ovfl}
-	up := unsafe.Pointer(v.UnsafeAddr())
+	up := unsafe.Pointer(unsafeAddr(v))
 	if indir > 1 {
 		up = decIndirect(up, indir)
 	}
@@ -605,11 +605,11 @@ func (dec *Decoder) decodeMap(mtyp reflect.Type, state *decoderState, p uintptr,
 	// Maps cannot be accessed by moving addresses around the way
 	// that slices etc. can.  We must recover a full reflection value for
 	// the iteration.
-	v := reflect.NewValue(unsafe.Unreflect(mtyp, unsafe.Pointer(p)))
+	v := reflect.ValueOf(unsafe.Unreflect(mtyp, unsafe.Pointer(p)))
 	n := int(state.decodeUint())
 	for i := 0; i < n; i++ {
-		key := decodeIntoValue(state, keyOp, keyIndir, reflect.Zero(mtyp.Key()), ovfl)
-		elem := decodeIntoValue(state, elemOp, elemIndir, reflect.Zero(mtyp.Elem()), ovfl)
+		key := decodeIntoValue(state, keyOp, keyIndir, allocValue(mtyp.Key()), ovfl)
+		elem := decodeIntoValue(state, elemOp, elemIndir, allocValue(mtyp.Elem()), ovfl)
 		v.SetMapIndex(key, elem)
 	}
 }
@@ -625,7 +625,7 @@ func (dec *Decoder) ignoreArrayHelper(state *decoderState, elemOp decOp, length
 // ignoreArray discards the data for an array value with no destination.
 func (dec *Decoder) ignoreArray(state *decoderState, elemOp decOp, length int) {
 	if n := state.decodeUint(); n != uint64(length) {
-		errorf("gob: length mismatch in ignoreArray")
+		errorf("length mismatch in ignoreArray")
 	}
 	dec.ignoreArrayHelper(state, elemOp, length)
 }
@@ -667,18 +667,12 @@ func (dec *Decoder) ignoreSlice(state *decoderState, elemOp decOp) {
 	dec.ignoreArrayHelper(state, elemOp, int(state.decodeUint()))
 }
 
-// setInterfaceValue sets an interface value to a concrete value through
-// reflection.  If the concrete value does not implement the interface, the
-// setting will panic.  This routine turns the panic into an error return.
-// This dance avoids manually checking that the value satisfies the
-// interface.
-// TODO(rsc): avoid panic+recover after fixing issue 327.
+// setInterfaceValue sets an interface value to a concrete value,
+// but first it checks that the assignment will succeed.
 func setInterfaceValue(ivalue reflect.Value, value reflect.Value) {
-	defer func() {
-		if e := recover(); e != nil {
-			error(e.(os.Error))
-		}
-	}()
+	if !value.Type().AssignableTo(ivalue.Type()) {
+		errorf("cannot assign value of type %s to %s", value.Type(), ivalue.Type())
+	}
 	ivalue.Set(value)
 }
 
@@ -686,8 +680,8 @@ func setInterfaceValue(ivalue reflect.Value, value reflect.Value) {
 // Interfaces are encoded as the name of a concrete type followed by a value.
 // If the name is empty, the value is nil and no value is sent.
 func (dec *Decoder) decodeInterface(ityp reflect.Type, state *decoderState, p uintptr, indir int) {
-	// Create an interface reflect.Value.  We need one even for the nil case.
-	ivalue := reflect.Zero(ityp)
+	// Create a writable interface reflect.Value.  We need one even for the nil case.
+	ivalue := allocValue(ityp)
 	// Read the name of the concrete type.
 	b := make([]byte, state.decodeUint())
 	state.b.Read(b)
@@ -701,7 +695,7 @@ func (dec *Decoder) decodeInterface(ityp reflect.Type, state *decoderState, p ui
 	// The concrete type must be registered.
 	typ, ok := nameToConcreteType[name]
 	if !ok {
-		errorf("gob: name not registered for interface: %q", name)
+		errorf("name not registered for interface: %q", name)
 	}
 	// Read the type id of the concrete value.
 	concreteId := dec.decodeTypeSequence(true)
@@ -712,7 +706,7 @@ func (dec *Decoder) decodeInterface(ityp reflect.Type, state *decoderState, p ui
 	// in case we want to ignore the value by skipping it completely).
 	state.decodeUint()
 	// Read the concrete value.
-	value := reflect.Zero(typ)
+	value := allocValue(typ)
 	dec.decodeValue(concreteId, value)
 	if dec.err != nil {
 		error(dec.err)
@@ -880,7 +874,7 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg
 		}
 	}
 	if op == nil {
-		errorf("gob: decode can't handle type %s", rt.String())
+		errorf("decode can't handle type %s", rt.String())
 	}
 	return &op, indir
 }
@@ -901,7 +895,7 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp {
 		wire := dec.wireType[wireId]
 		switch {
 		case wire == nil:
-			errorf("gob: bad data: undefined type %s", wireId.string())
+			errorf("bad data: undefined type %s", wireId.string())
 		case wire.ArrayT != nil:
 			elemId := wire.ArrayT.Elem
 			elemOp := dec.decIgnoreOpFor(elemId)
@@ -943,7 +937,7 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp {
 		}
 	}
 	if op == nil {
-		errorf("gob: bad data: ignore can't handle type %s", wireId.string())
+		errorf("bad data: ignore can't handle type %s", wireId.string())
 	}
 	return op
 }
@@ -951,32 +945,33 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp {
 // gobDecodeOpFor returns the op for a type that is known to implement
 // GobDecoder.
 func (dec *Decoder) gobDecodeOpFor(ut *userTypeInfo) (*decOp, int) {
-	rt := ut.user
+	rcvrType := ut.user
 	if ut.decIndir == -1 {
-		rt = reflect.PtrTo(rt)
+		rcvrType = reflect.PtrTo(rcvrType)
 	} else if ut.decIndir > 0 {
 		for i := int8(0); i < ut.decIndir; i++ {
-			rt = rt.Elem()
+			rcvrType = rcvrType.Elem()
 		}
 	}
 	var op decOp
 	op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
-		// Allocate the underlying data, but hold on to the address we have,
-		// since we need it to get to the receiver's address.
-		allocate(ut.base, uintptr(p), ut.indir)
+		// Caller has gotten us to within one indirection of our value.
+		if i.indir > 0 {
+			if *(*unsafe.Pointer)(p) == nil {
+				*(*unsafe.Pointer)(p) = unsafe.New(ut.base)
+			}
+		}
+		// Now p is a pointer to the base type.  Do we need to climb out to
+		// get to the receiver type?
 		var v reflect.Value
 		if ut.decIndir == -1 {
-			// Need to climb up one level to turn value into pointer.
-			v = reflect.NewValue(unsafe.Unreflect(rt, unsafe.Pointer(&p)))
+			v = reflect.ValueOf(unsafe.Unreflect(rcvrType, unsafe.Pointer(&p)))
 		} else {
-			if ut.decIndir > 0 {
-				p = decIndirect(p, int(ut.decIndir))
-			}
-			v = reflect.NewValue(unsafe.Unreflect(rt, p))
+			v = reflect.ValueOf(unsafe.Unreflect(rcvrType, p))
 		}
-		state.dec.decodeGobDecoder(state, v, methodIndex(rt, gobDecodeMethodName))
+		state.dec.decodeGobDecoder(state, v, methodIndex(rcvrType, gobDecodeMethodName))
 	}
-	return &op, int(ut.decIndir)
+	return &op, int(ut.indir)
 
 }
 
@@ -1111,7 +1106,7 @@ func (dec *Decoder) compileDec(remoteId typeId, ut *userTypeInfo) (engine *decEn
 		wireStruct = wire.StructT
 	}
 	if wireStruct == nil {
-		errorf("gob: type mismatch in decoder: want struct type %s; got non-struct", rt.String())
+		errorf("type mismatch in decoder: want struct type %s; got non-struct", rt.String())
 	}
 	engine = new(decEngine)
 	engine.instr = make([]decInstr, len(wireStruct.Field))
@@ -1120,7 +1115,7 @@ func (dec *Decoder) compileDec(remoteId typeId, ut *userTypeInfo) (engine *decEn
 	for fieldnum := 0; fieldnum < len(wireStruct.Field); fieldnum++ {
 		wireField := wireStruct.Field[fieldnum]
 		if wireField.Name == "" {
-			errorf("gob: empty name for remote field of type %s", wireStruct.Name)
+			errorf("empty name for remote field of type %s", wireStruct.Name)
 		}
 		ovfl := overflow(wireField.Name)
 		// Find the field of the local type with the same name.
@@ -1132,7 +1127,7 @@ func (dec *Decoder) compileDec(remoteId typeId, ut *userTypeInfo) (engine *decEn
 			continue
 		}
 		if !dec.compatibleType(localField.Type, wireField.Id, make(map[reflect.Type]typeId)) {
-			errorf("gob: wrong type (%s) for received field %s.%s", localField.Type, wireStruct.Name, wireField.Name)
+			errorf("wrong type (%s) for received field %s.%s", localField.Type, wireStruct.Name, wireField.Name)
 		}
 		op, indir := dec.decOpFor(wireField.Id, localField.Type, localField.Name, seen)
 		engine.instr[fieldnum] = decInstr{*op, fieldnum, indir, uintptr(localField.Offset), ovfl}
@@ -1164,7 +1159,7 @@ func (dec *Decoder) getDecEnginePtr(remoteId typeId, ut *userTypeInfo) (enginePt
 // emptyStruct is the type we compile into when ignoring a struct value.
 type emptyStruct struct{}
 
-var emptyStructType = reflect.Typeof(emptyStruct{})
+var emptyStructType = reflect.TypeOf(emptyStruct{})
 
 // getDecEnginePtr returns the engine for the specified type when the value is to be discarded.
 func (dec *Decoder) getIgnoreEnginePtr(wireId typeId) (enginePtr **decEngine, err os.Error) {
@@ -1197,10 +1192,6 @@ func (dec *Decoder) decodeValue(wireId typeId, val reflect.Value) {
 	// Dereference down to the underlying struct type.
 	ut := userType(val.Type())
 	base := ut.base
-	indir := ut.indir
-	if ut.isGobDecoder {
-		indir = int(ut.decIndir)
-	}
 	var enginePtr **decEngine
 	enginePtr, dec.err = dec.getDecEnginePtr(wireId, ut)
 	if dec.err != nil {
@@ -1210,11 +1201,11 @@ func (dec *Decoder) decodeValue(wireId typeId, val reflect.Value) {
 	if st := base; st.Kind() == reflect.Struct && !ut.isGobDecoder {
 		if engine.numInstr == 0 && st.NumField() > 0 && len(dec.wireType[wireId].StructT.Field) > 0 {
 			name := base.Name()
-			errorf("gob: type mismatch: no fields matched compiling decoder for %s", name)
+			errorf("type mismatch: no fields matched compiling decoder for %s", name)
 		}
-		dec.decodeStruct(engine, ut, uintptr(val.UnsafeAddr()), indir)
+		dec.decodeStruct(engine, ut, uintptr(unsafeAddr(val)), ut.indir)
 	} else {
-		dec.decodeSingle(engine, ut, uintptr(val.UnsafeAddr()))
+		dec.decodeSingle(engine, ut, uintptr(unsafeAddr(val)))
 	}
 }
 
@@ -1235,7 +1226,7 @@ func (dec *Decoder) decodeIgnoredValue(wireId typeId) {
 
 func init() {
 	var iop, uop decOp
-	switch reflect.Typeof(int(0)).Bits() {
+	switch reflect.TypeOf(int(0)).Bits() {
 	case 32:
 		iop = decInt32
 		uop = decUint32
@@ -1249,7 +1240,7 @@ func init() {
 	decOpTable[reflect.Uint] = uop
 
 	// Finally uintptr
-	switch reflect.Typeof(uintptr(0)).Bits() {
+	switch reflect.TypeOf(uintptr(0)).Bits() {
 	case 32:
 		uop = decUint32
 	case 64:
@@ -1259,3 +1250,26 @@ func init() {
 	}
 	decOpTable[reflect.Uintptr] = uop
 }
+
+// Gob assumes it can call UnsafeAddr on any Value
+// in order to get a pointer it can copy data from.
+// Values that have just been created and do not point
+// into existing structs or slices cannot be addressed,
+// so simulate it by returning a pointer to a copy.
+// Each call allocates once.
+func unsafeAddr(v reflect.Value) uintptr {
+	if v.CanAddr() {
+		return v.UnsafeAddr()
+	}
+	x := reflect.New(v.Type()).Elem()
+	x.Set(v)
+	return x.UnsafeAddr()
+}
+
+// Gob depends on being able to take the address
+// of zeroed Values it creates, so use this wrapper instead
+// of the standard reflect.Zero.
+// Each call allocates once.
+func allocValue(t reflect.Type) reflect.Value {
+	return reflect.New(t).Elem()
+}
diff --git a/src/pkg/gob/decoder.go b/src/pkg/gob/decoder.go
index a631c27..ea2f62e 100644
--- a/src/pkg/gob/decoder.go
+++ b/src/pkg/gob/decoder.go
@@ -50,7 +50,7 @@ func (dec *Decoder) recvType(id typeId) {
 
 	// Type:
 	wire := new(wireType)
-	dec.decodeValue(tWireType, reflect.NewValue(wire))
+	dec.decodeValue(tWireType, reflect.ValueOf(wire))
 	if dec.err != nil {
 		return
 	}
@@ -161,7 +161,7 @@ func (dec *Decoder) Decode(e interface{}) os.Error {
 	if e == nil {
 		return dec.DecodeValue(reflect.Value{})
 	}
-	value := reflect.NewValue(e)
+	value := reflect.ValueOf(e)
 	// If e represents a value as opposed to a pointer, the answer won't
 	// get back to the caller.  Make sure it's a pointer.
 	if value.Type().Kind() != reflect.Ptr {
@@ -171,12 +171,18 @@ func (dec *Decoder) Decode(e interface{}) os.Error {
 	return dec.DecodeValue(value)
 }
 
-// DecodeValue reads the next value from the connection and stores
-// it in the data represented by the reflection value.
-// The value must be the correct type for the next
-// data item received, or it may be nil, which means the
-// value will be discarded.
-func (dec *Decoder) DecodeValue(value reflect.Value) os.Error {
+// DecodeValue reads the next value from the connection.
+// If v is the zero reflect.Value (v.Kind() == Invalid), DecodeValue discards the value.
+// Otherwise, it stores the value into v.  In that case, v must represent
+// a non-nil pointer to data or be an assignable reflect.Value (v.CanSet())
+func (dec *Decoder) DecodeValue(v reflect.Value) os.Error {
+	if v.IsValid() {
+		if v.Kind() == reflect.Ptr && !v.IsNil() {
+			// That's okay, we'll store through the pointer.
+		} else if !v.CanSet() {
+			return os.ErrorString("gob: DecodeValue of unassignable value")
+		}
+	}
 	// Make sure we're single-threaded through here.
 	dec.mutex.Lock()
 	defer dec.mutex.Unlock()
@@ -185,7 +191,7 @@ func (dec *Decoder) DecodeValue(value reflect.Value) os.Error {
 	dec.err = nil
 	id := dec.decodeTypeSequence(false)
 	if dec.err == nil {
-		dec.decodeValue(id, value)
+		dec.decodeValue(id, v)
 	}
 	return dec.err
 }
diff --git a/src/pkg/gob/doc.go b/src/pkg/gob/doc.go
index 613974a..189086f 100644
--- a/src/pkg/gob/doc.go
+++ b/src/pkg/gob/doc.go
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 /*
-The gob package manages streams of gobs - binary values exchanged between an
+Package gob manages streams of gobs - binary values exchanged between an
 Encoder (transmitter) and a Decoder (receiver).  A typical use is transporting
 arguments and results of remote procedure calls (RPCs) such as those provided by
 package "rpc".
diff --git a/src/pkg/gob/encode.go b/src/pkg/gob/encode.go
index 36bde08..f9e691a 100644
--- a/src/pkg/gob/encode.go
+++ b/src/pkg/gob/encode.go
@@ -384,7 +384,7 @@ func (enc *Encoder) encodeArray(b *bytes.Buffer, p uintptr, op encOp, elemWid ui
 		up := unsafe.Pointer(elemp)
 		if elemIndir > 0 {
 			if up = encIndirect(up, elemIndir); up == nil {
-				errorf("gob: encodeArray: nil element")
+				errorf("encodeArray: nil element")
 			}
 			elemp = uintptr(up)
 		}
@@ -400,9 +400,9 @@ func encodeReflectValue(state *encoderState, v reflect.Value, op encOp, indir in
 		v = reflect.Indirect(v)
 	}
 	if !v.IsValid() {
-		errorf("gob: encodeReflectValue: nil element")
+		errorf("encodeReflectValue: nil element")
 	}
-	op(nil, state, unsafe.Pointer(v.UnsafeAddr()))
+	op(nil, state, unsafe.Pointer(unsafeAddr(v)))
 }
 
 // encodeMap encodes a map as unsigned count followed by key:value pairs.
@@ -438,7 +438,7 @@ func (enc *Encoder) encodeInterface(b *bytes.Buffer, iv reflect.Value) {
 	ut := userType(iv.Elem().Type())
 	name, ok := concreteTypeToName[ut.base]
 	if !ok {
-		errorf("gob: type not registered for interface: %s", ut.base)
+		errorf("type not registered for interface: %s", ut.base)
 	}
 	// Send the name.
 	state.encodeUint(uint64(len(name)))
@@ -555,7 +555,7 @@ func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp
 				// Maps cannot be accessed by moving addresses around the way
 				// that slices etc. can.  We must recover a full reflection value for
 				// the iteration.
-				v := reflect.NewValue(unsafe.Unreflect(t, unsafe.Pointer(p)))
+				v := reflect.ValueOf(unsafe.Unreflect(t, unsafe.Pointer(p)))
 				mv := reflect.Indirect(v)
 				if !state.sendZero && mv.Len() == 0 {
 					return
@@ -576,7 +576,7 @@ func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp
 			op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
 				// Interfaces transmit the name and contents of the concrete
 				// value they contain.
-				v := reflect.NewValue(unsafe.Unreflect(t, unsafe.Pointer(p)))
+				v := reflect.ValueOf(unsafe.Unreflect(t, unsafe.Pointer(p)))
 				iv := reflect.Indirect(v)
 				if !state.sendZero && (!iv.IsValid() || iv.IsNil()) {
 					return
@@ -587,7 +587,7 @@ func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp
 		}
 	}
 	if op == nil {
-		errorf("gob enc: can't happen: encode type %s", rt.String())
+		errorf("can't happen: encode type %s", rt.String())
 	}
 	return &op, indir
 }
@@ -599,7 +599,7 @@ func methodIndex(rt reflect.Type, method string) int {
 			return i
 		}
 	}
-	errorf("gob: internal error: can't find method %s", method)
+	errorf("internal error: can't find method %s", method)
 	return 0
 }
 
@@ -619,9 +619,9 @@ func (enc *Encoder) gobEncodeOpFor(ut *userTypeInfo) (*encOp, int) {
 		var v reflect.Value
 		if ut.encIndir == -1 {
 			// Need to climb up one level to turn value into pointer.
-			v = reflect.NewValue(unsafe.Unreflect(rt, unsafe.Pointer(&p)))
+			v = reflect.ValueOf(unsafe.Unreflect(rt, unsafe.Pointer(&p)))
 		} else {
-			v = reflect.NewValue(unsafe.Unreflect(rt, p))
+			v = reflect.ValueOf(unsafe.Unreflect(rt, p))
 		}
 		state.update(i)
 		state.enc.encodeGobEncoder(state.b, v, methodIndex(rt, gobEncodeMethodName))
@@ -650,7 +650,7 @@ func (enc *Encoder) compileEnc(ut *userTypeInfo) *encEngine {
 			wireFieldNum++
 		}
 		if srt.NumField() > 0 && len(engine.instr) == 0 {
-			errorf("gob: type %s has no exported fields", rt)
+			errorf("type %s has no exported fields", rt)
 		}
 		engine.instr = append(engine.instr, encInstr{encStructTerminator, 0, 0, 0})
 	} else {
@@ -695,8 +695,8 @@ func (enc *Encoder) encode(b *bytes.Buffer, value reflect.Value, ut *userTypeInf
 		value = reflect.Indirect(value)
 	}
 	if !ut.isGobEncoder && value.Type().Kind() == reflect.Struct {
-		enc.encodeStruct(b, engine, value.UnsafeAddr())
+		enc.encodeStruct(b, engine, unsafeAddr(value))
 	} else {
-		enc.encodeSingle(b, engine, value.UnsafeAddr())
+		enc.encodeSingle(b, engine, unsafeAddr(value))
 	}
 }
diff --git a/src/pkg/gob/encoder.go b/src/pkg/gob/encoder.go
index 928f3b2..65ee5bf 100644
--- a/src/pkg/gob/encoder.go
+++ b/src/pkg/gob/encoder.go
@@ -97,7 +97,7 @@ func (enc *Encoder) sendActualType(w io.Writer, state *encoderState, ut *userTyp
 	// Id:
 	state.encodeInt(-int64(info.id))
 	// Type:
-	enc.encode(state.b, reflect.NewValue(info.wire), wireTypeUserInfo)
+	enc.encode(state.b, reflect.ValueOf(info.wire), wireTypeUserInfo)
 	enc.writeMessage(w, state.b)
 	if enc.err != nil {
 		return
@@ -116,6 +116,9 @@ func (enc *Encoder) sendActualType(w io.Writer, state *encoderState, ut *userTyp
 		}
 	case reflect.Array, reflect.Slice:
 		enc.sendType(w, state, st.Elem())
+	case reflect.Map:
+		enc.sendType(w, state, st.Key())
+		enc.sendType(w, state, st.Elem())
 	}
 	return true
 }
@@ -162,7 +165,7 @@ func (enc *Encoder) sendType(w io.Writer, state *encoderState, origt reflect.Typ
 // Encode transmits the data item represented by the empty interface value,
 // guaranteeing that all necessary type information has been transmitted first.
 func (enc *Encoder) Encode(e interface{}) os.Error {
-	return enc.EncodeValue(reflect.NewValue(e))
+	return enc.EncodeValue(reflect.ValueOf(e))
 }
 
 // sendTypeDescriptor makes sure the remote side knows about this type.
diff --git a/src/pkg/gob/encoder_test.go b/src/pkg/gob/encoder_test.go
index 3d5dfdb..792afbd 100644
--- a/src/pkg/gob/encoder_test.go
+++ b/src/pkg/gob/encoder_test.go
@@ -170,7 +170,7 @@ func TestTypeToPtrType(t *testing.T) {
 		A int
 	}
 	t0 := Type0{7}
-	t0p := (*Type0)(nil)
+	t0p := new(Type0)
 	if err := encAndDec(t0, t0p); err != nil {
 		t.Error(err)
 	}
@@ -339,7 +339,7 @@ func TestSingletons(t *testing.T) {
 			continue
 		}
 		// Get rid of the pointer in the rhs
-		val := reflect.NewValue(test.out).Elem().Interface()
+		val := reflect.ValueOf(test.out).Elem().Interface()
 		if !reflect.DeepEqual(test.in, val) {
 			t.Errorf("decoding singleton: expected %v got %v", test.in, val)
 		}
@@ -514,3 +514,38 @@ func TestNestedInterfaces(t *testing.T) {
 		t.Fatalf("final value %d; expected %d", inner.A, 7)
 	}
 }
+
+// The bugs keep coming. We forgot to send map subtypes before the map.
+
+type Bug1Elem struct {
+	Name string
+	Id   int
+}
+
+type Bug1StructMap map[string]Bug1Elem
+
+func bug1EncDec(in Bug1StructMap, out *Bug1StructMap) os.Error {
+	return nil
+}
+
+func TestMapBug1(t *testing.T) {
+	in := make(Bug1StructMap)
+	in["val1"] = Bug1Elem{"elem1", 1}
+	in["val2"] = Bug1Elem{"elem2", 2}
+
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	err := enc.Encode(in)
+	if err != nil {
+		t.Fatal("encode:", err)
+	}
+	dec := NewDecoder(b)
+	out := make(Bug1StructMap)
+	err = dec.Decode(&out)
+	if err != nil {
+		t.Fatal("decode:", err)
+	}
+	if !reflect.DeepEqual(in, out) {
+		t.Errorf("mismatch: %v %v", in, out)
+	}
+}
diff --git a/src/pkg/gob/error.go b/src/pkg/gob/error.go
index b053761..bfd38fc 100644
--- a/src/pkg/gob/error.go
+++ b/src/pkg/gob/error.go
@@ -22,8 +22,9 @@ type gobError struct {
 }
 
 // errorf is like error but takes Printf-style arguments to construct an os.Error.
+// It always prefixes the message with "gob: ".
 func errorf(format string, args ...interface{}) {
-	error(fmt.Errorf(format, args...))
+	error(fmt.Errorf("gob: "+format, args...))
 }
 
 // error wraps the argument error and uses it as the argument to panic.
diff --git a/src/pkg/gob/gobencdec_test.go b/src/pkg/gob/gobencdec_test.go
index 012b099..e94534f 100644
--- a/src/pkg/gob/gobencdec_test.go
+++ b/src/pkg/gob/gobencdec_test.go
@@ -24,6 +24,10 @@ type StringStruct struct {
 	s string // not an exported field
 }
 
+type ArrayStruct struct {
+	a [8192]byte // not an exported field
+}
+
 type Gobber int
 
 type ValueGobber string // encodes with a value, decodes with a pointer.
@@ -74,6 +78,18 @@ func (g *StringStruct) GobDecode(data []byte) os.Error {
 	return nil
 }
 
+func (a *ArrayStruct) GobEncode() ([]byte, os.Error) {
+	return a.a[:], nil
+}
+
+func (a *ArrayStruct) GobDecode(data []byte) os.Error {
+	if len(data) != len(a.a) {
+		return os.ErrorString("wrong length in array decode")
+	}
+	copy(a.a[:], data)
+	return nil
+}
+
 func (g *Gobber) GobEncode() ([]byte, os.Error) {
 	return []byte(fmt.Sprintf("VALUE=%d", *g)), nil
 }
@@ -138,6 +154,16 @@ type GobTestIndirectEncDec struct {
 	G ***StringStruct // indirections to the receiver.
 }
 
+type GobTestArrayEncDec struct {
+	X int         // guarantee we have  something in common with GobTest*
+	A ArrayStruct // not a pointer.
+}
+
+type GobTestIndirectArrayEncDec struct {
+	X int            // guarantee we have  something in common with GobTest*
+	A ***ArrayStruct // indirections to a large receiver.
+}
+
 func TestGobEncoderField(t *testing.T) {
 	b := new(bytes.Buffer)
 	// First a field that's a structure.
@@ -216,6 +242,64 @@ func TestGobEncoderIndirectField(t *testing.T) {
 	}
 }
 
+// Test with a large field with methods.
+func TestGobEncoderArrayField(t *testing.T) {
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	var a GobTestArrayEncDec
+	a.X = 17
+	for i := range a.A.a {
+		a.A.a[i] = byte(i)
+	}
+	err := enc.Encode(a)
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+	dec := NewDecoder(b)
+	x := new(GobTestArrayEncDec)
+	err = dec.Decode(x)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+	for i, v := range x.A.a {
+		if v != byte(i) {
+			t.Errorf("expected %x got %x", byte(i), v)
+			break
+		}
+	}
+}
+
+// Test an indirection to a large field with methods.
+func TestGobEncoderIndirectArrayField(t *testing.T) {
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	var a GobTestIndirectArrayEncDec
+	a.X = 17
+	var array ArrayStruct
+	ap := &array
+	app := &ap
+	a.A = &app
+	for i := range array.a {
+		array.a[i] = byte(i)
+	}
+	err := enc.Encode(a)
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+	dec := NewDecoder(b)
+	x := new(GobTestIndirectArrayEncDec)
+	err = dec.Decode(x)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+	for i, v := range (***x.A).a {
+		if v != byte(i) {
+			t.Errorf("expected %x got %x", byte(i), v)
+			break
+		}
+	}
+}
+
 // As long as the fields have the same name and implement the
 // interface, we can cross-connect them.  Not sure it's useful
 // and may even be bad but it works and it's hard to prevent
diff --git a/src/pkg/gob/type.go b/src/pkg/gob/type.go
index 8fd1748..c5b8fb5 100644
--- a/src/pkg/gob/type.go
+++ b/src/pkg/gob/type.go
@@ -74,8 +74,8 @@ func validUserType(rt reflect.Type) (ut *userTypeInfo, err os.Error) {
 		}
 		ut.indir++
 	}
-	ut.isGobEncoder, ut.encIndir = implementsInterface(ut.user, gobEncoderCheck)
-	ut.isGobDecoder, ut.decIndir = implementsInterface(ut.user, gobDecoderCheck)
+	ut.isGobEncoder, ut.encIndir = implementsInterface(ut.user, gobEncoderInterfaceType)
+	ut.isGobDecoder, ut.decIndir = implementsInterface(ut.user, gobDecoderInterfaceType)
 	userTypeCache[rt] = ut
 	return
 }
@@ -85,32 +85,16 @@ const (
 	gobDecodeMethodName = "GobDecode"
 )
 
-// implements returns whether the type implements the interface, as encoded
-// in the check function.
-func implements(typ reflect.Type, check func(typ reflect.Type) bool) bool {
-	if typ.NumMethod() == 0 { // avoid allocations etc. unless there's some chance
-		return false
-	}
-	return check(typ)
-}
-
-// gobEncoderCheck makes the type assertion a boolean function.
-func gobEncoderCheck(typ reflect.Type) bool {
-	_, ok := reflect.Zero(typ).Interface().(GobEncoder)
-	return ok
-}
-
-// gobDecoderCheck makes the type assertion a boolean function.
-func gobDecoderCheck(typ reflect.Type) bool {
-	_, ok := reflect.Zero(typ).Interface().(GobDecoder)
-	return ok
-}
+var (
+	gobEncoderInterfaceType = reflect.TypeOf(new(GobEncoder)).Elem()
+	gobDecoderInterfaceType = reflect.TypeOf(new(GobDecoder)).Elem()
+)
 
 // implementsInterface reports whether the type implements the
-// interface. (The actual check is done through the provided function.)
+// gobEncoder/gobDecoder interface.
 // It also returns the number of indirections required to get to the
 // implementation.
-func implementsInterface(typ reflect.Type, check func(typ reflect.Type) bool) (success bool, indir int8) {
+func implementsInterface(typ, gobEncDecType reflect.Type) (success bool, indir int8) {
 	if typ == nil {
 		return
 	}
@@ -118,7 +102,7 @@ func implementsInterface(typ reflect.Type, check func(typ reflect.Type) bool) (s
 	// The type might be a pointer and we need to keep
 	// dereferencing to the base type until we find an implementation.
 	for {
-		if implements(rt, check) {
+		if rt.Implements(gobEncDecType) {
 			return true, indir
 		}
 		if p := rt; p.Kind() == reflect.Ptr {
@@ -134,7 +118,7 @@ func implementsInterface(typ reflect.Type, check func(typ reflect.Type) bool) (s
 	// No luck yet, but if this is a base type (non-pointer), the pointer might satisfy.
 	if typ.Kind() != reflect.Ptr {
 		// Not a pointer, but does the pointer work?
-		if implements(reflect.PtrTo(typ), check) {
+		if reflect.PtrTo(typ).Implements(gobEncDecType) {
 			return true, -1
 		}
 	}
@@ -243,18 +227,18 @@ var (
 )
 
 // Predefined because it's needed by the Decoder
-var tWireType = mustGetTypeInfo(reflect.Typeof(wireType{})).id
+var tWireType = mustGetTypeInfo(reflect.TypeOf(wireType{})).id
 var wireTypeUserInfo *userTypeInfo // userTypeInfo of (*wireType)
 
 func init() {
 	// Some magic numbers to make sure there are no surprises.
 	checkId(16, tWireType)
-	checkId(17, mustGetTypeInfo(reflect.Typeof(arrayType{})).id)
-	checkId(18, mustGetTypeInfo(reflect.Typeof(CommonType{})).id)
-	checkId(19, mustGetTypeInfo(reflect.Typeof(sliceType{})).id)
-	checkId(20, mustGetTypeInfo(reflect.Typeof(structType{})).id)
-	checkId(21, mustGetTypeInfo(reflect.Typeof(fieldType{})).id)
-	checkId(23, mustGetTypeInfo(reflect.Typeof(mapType{})).id)
+	checkId(17, mustGetTypeInfo(reflect.TypeOf(arrayType{})).id)
+	checkId(18, mustGetTypeInfo(reflect.TypeOf(CommonType{})).id)
+	checkId(19, mustGetTypeInfo(reflect.TypeOf(sliceType{})).id)
+	checkId(20, mustGetTypeInfo(reflect.TypeOf(structType{})).id)
+	checkId(21, mustGetTypeInfo(reflect.TypeOf(fieldType{})).id)
+	checkId(23, mustGetTypeInfo(reflect.TypeOf(mapType{})).id)
 
 	builtinIdToType = make(map[typeId]gobType)
 	for k, v := range idToType {
@@ -268,7 +252,7 @@ func init() {
 	}
 	nextId = firstUserId
 	registerBasics()
-	wireTypeUserInfo = userType(reflect.Typeof((*wireType)(nil)))
+	wireTypeUserInfo = userType(reflect.TypeOf((*wireType)(nil)))
 }
 
 // Array type
@@ -569,7 +553,7 @@ func checkId(want, got typeId) {
 // used for building the basic types; called only from init().  the incoming
 // interface always refers to a pointer.
 func bootstrapType(name string, e interface{}, expect typeId) typeId {
-	rt := reflect.Typeof(e).Elem()
+	rt := reflect.TypeOf(e).Elem()
 	_, present := types[rt]
 	if present {
 		panic("bootstrap type already present: " + name + ", " + rt.String())
@@ -723,7 +707,7 @@ func RegisterName(name string, value interface{}) {
 		// reserved for nil
 		panic("attempt to register empty name")
 	}
-	base := userType(reflect.Typeof(value)).base
+	base := userType(reflect.TypeOf(value)).base
 	// Check for incompatible duplicates.
 	if t, ok := nameToConcreteType[name]; ok && t != base {
 		panic("gob: registering duplicate types for " + name)
@@ -732,7 +716,7 @@ func RegisterName(name string, value interface{}) {
 		panic("gob: registering duplicate names for " + base.String())
 	}
 	// Store the name and type provided by the user....
-	nameToConcreteType[name] = reflect.Typeof(value)
+	nameToConcreteType[name] = reflect.TypeOf(value)
 	// but the flattened type in the type table, since that's what decode needs.
 	concreteTypeToName[base] = name
 }
@@ -745,7 +729,7 @@ func RegisterName(name string, value interface{}) {
 // between types and names is not a bijection.
 func Register(value interface{}) {
 	// Default to printed representation for unnamed types
-	rt := reflect.Typeof(value)
+	rt := reflect.TypeOf(value)
 	name := rt.String()
 
 	// But for named types (or pointers to them), qualify with import path.
diff --git a/src/pkg/gob/type_test.go b/src/pkg/gob/type_test.go
index ffd1345..411ffb7 100644
--- a/src/pkg/gob/type_test.go
+++ b/src/pkg/gob/type_test.go
@@ -47,15 +47,15 @@ func TestBasic(t *testing.T) {
 
 // Reregister some basic types to check registration is idempotent.
 func TestReregistration(t *testing.T) {
-	newtyp := getTypeUnlocked("int", reflect.Typeof(int(0)))
+	newtyp := getTypeUnlocked("int", reflect.TypeOf(int(0)))
 	if newtyp != tInt.gobType() {
 		t.Errorf("reregistration of %s got new type", newtyp.string())
 	}
-	newtyp = getTypeUnlocked("uint", reflect.Typeof(uint(0)))
+	newtyp = getTypeUnlocked("uint", reflect.TypeOf(uint(0)))
 	if newtyp != tUint.gobType() {
 		t.Errorf("reregistration of %s got new type", newtyp.string())
 	}
-	newtyp = getTypeUnlocked("string", reflect.Typeof("hello"))
+	newtyp = getTypeUnlocked("string", reflect.TypeOf("hello"))
 	if newtyp != tString.gobType() {
 		t.Errorf("reregistration of %s got new type", newtyp.string())
 	}
@@ -63,18 +63,18 @@ func TestReregistration(t *testing.T) {
 
 func TestArrayType(t *testing.T) {
 	var a3 [3]int
-	a3int := getTypeUnlocked("foo", reflect.Typeof(a3))
-	newa3int := getTypeUnlocked("bar", reflect.Typeof(a3))
+	a3int := getTypeUnlocked("foo", reflect.TypeOf(a3))
+	newa3int := getTypeUnlocked("bar", reflect.TypeOf(a3))
 	if a3int != newa3int {
 		t.Errorf("second registration of [3]int creates new type")
 	}
 	var a4 [4]int
-	a4int := getTypeUnlocked("goo", reflect.Typeof(a4))
+	a4int := getTypeUnlocked("goo", reflect.TypeOf(a4))
 	if a3int == a4int {
 		t.Errorf("registration of [3]int creates same type as [4]int")
 	}
 	var b3 [3]bool
-	a3bool := getTypeUnlocked("", reflect.Typeof(b3))
+	a3bool := getTypeUnlocked("", reflect.TypeOf(b3))
 	if a3int == a3bool {
 		t.Errorf("registration of [3]bool creates same type as [3]int")
 	}
@@ -87,14 +87,14 @@ func TestArrayType(t *testing.T) {
 
 func TestSliceType(t *testing.T) {
 	var s []int
-	sint := getTypeUnlocked("slice", reflect.Typeof(s))
+	sint := getTypeUnlocked("slice", reflect.TypeOf(s))
 	var news []int
-	newsint := getTypeUnlocked("slice1", reflect.Typeof(news))
+	newsint := getTypeUnlocked("slice1", reflect.TypeOf(news))
 	if sint != newsint {
 		t.Errorf("second registration of []int creates new type")
 	}
 	var b []bool
-	sbool := getTypeUnlocked("", reflect.Typeof(b))
+	sbool := getTypeUnlocked("", reflect.TypeOf(b))
 	if sbool == sint {
 		t.Errorf("registration of []bool creates same type as []int")
 	}
@@ -107,14 +107,14 @@ func TestSliceType(t *testing.T) {
 
 func TestMapType(t *testing.T) {
 	var m map[string]int
-	mapStringInt := getTypeUnlocked("map", reflect.Typeof(m))
+	mapStringInt := getTypeUnlocked("map", reflect.TypeOf(m))
 	var newm map[string]int
-	newMapStringInt := getTypeUnlocked("map1", reflect.Typeof(newm))
+	newMapStringInt := getTypeUnlocked("map1", reflect.TypeOf(newm))
 	if mapStringInt != newMapStringInt {
 		t.Errorf("second registration of map[string]int creates new type")
 	}
 	var b map[string]bool
-	mapStringBool := getTypeUnlocked("", reflect.Typeof(b))
+	mapStringBool := getTypeUnlocked("", reflect.TypeOf(b))
 	if mapStringBool == mapStringInt {
 		t.Errorf("registration of map[string]bool creates same type as map[string]int")
 	}
@@ -143,7 +143,7 @@ type Foo struct {
 }
 
 func TestStructType(t *testing.T) {
-	sstruct := getTypeUnlocked("Foo", reflect.Typeof(Foo{}))
+	sstruct := getTypeUnlocked("Foo", reflect.TypeOf(Foo{}))
 	str := sstruct.string()
 	// If we can print it correctly, we built it correctly.
 	expected := "Foo = struct { A int; B int; C string; D bytes; E float; F float; G Bar = struct { X string; }; H Bar; I Foo; }"
diff --git a/src/pkg/hash/adler32/adler32.go b/src/pkg/hash/adler32/adler32.go
index cd0c259..84943d9 100644
--- a/src/pkg/hash/adler32/adler32.go
+++ b/src/pkg/hash/adler32/adler32.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package implements the Adler-32 checksum.
+// Package adler32 implements the Adler-32 checksum.
 // Defined in RFC 1950:
 //	Adler-32 is composed of two sums accumulated per byte: s1 is
 //	the sum of all bytes, s2 is the sum of all s1 values. Both sums
@@ -43,8 +43,8 @@ func (d *digest) Size() int { return Size }
 
 // Add p to the running checksum a, b.
 func update(a, b uint32, p []byte) (aa, bb uint32) {
-	for i := 0; i < len(p); i++ {
-		a += uint32(p[i])
+	for _, pi := range p {
+		a += uint32(pi)
 		b += a
 		// invariant: a <= b
 		if b > (0xffffffff-255)/2 {
diff --git a/src/pkg/hash/adler32/adler32_test.go b/src/pkg/hash/adler32/adler32_test.go
index ffa5569..01f931c 100644
--- a/src/pkg/hash/adler32/adler32_test.go
+++ b/src/pkg/hash/adler32/adler32_test.go
@@ -5,6 +5,7 @@
 package adler32
 
 import (
+	"bytes"
 	"io"
 	"testing"
 )
@@ -61,3 +62,16 @@ func TestGolden(t *testing.T) {
 		}
 	}
 }
+
+func BenchmarkGolden(b *testing.B) {
+	b.StopTimer()
+	c := New()
+	var buf bytes.Buffer
+	for _, g := range golden {
+		buf.Write([]byte(g.in))
+	}
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		c.Write(buf.Bytes())
+	}
+}
diff --git a/src/pkg/hash/crc32/crc32.go b/src/pkg/hash/crc32/crc32.go
index 2ab0c54..88a4499 100644
--- a/src/pkg/hash/crc32/crc32.go
+++ b/src/pkg/hash/crc32/crc32.go
@@ -2,8 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package implements the 32-bit cyclic redundancy check, or CRC-32, checksum.
-// See http://en.wikipedia.org/wiki/Cyclic_redundancy_check for information.
+// Package crc32 implements the 32-bit cyclic redundancy check, or CRC-32,
+// checksum. See http://en.wikipedia.org/wiki/Cyclic_redundancy_check for
+// information.
 package crc32
 
 import (
diff --git a/src/pkg/hash/crc64/crc64.go b/src/pkg/hash/crc64/crc64.go
index 8443865..ae37e78 100644
--- a/src/pkg/hash/crc64/crc64.go
+++ b/src/pkg/hash/crc64/crc64.go
@@ -2,8 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package implements the 64-bit cyclic redundancy check, or CRC-64, checksum.
-// See http://en.wikipedia.org/wiki/Cyclic_redundancy_check for information.
+// Package crc64 implements the 64-bit cyclic redundancy check, or CRC-64,
+// checksum. See http://en.wikipedia.org/wiki/Cyclic_redundancy_check for
+// information.
 package crc64
 
 import (
diff --git a/src/pkg/hash/fnv/fnv.go b/src/pkg/hash/fnv/fnv.go
index 66ab5a6..9a1c6a0 100644
--- a/src/pkg/hash/fnv/fnv.go
+++ b/src/pkg/hash/fnv/fnv.go
@@ -2,9 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The fnv package implements FNV-1 and FNV-1a,
-// non-cryptographic hash functions created by
-// Glenn Fowler, Landon Curt Noll, and Phong Vo.
+// Package fnv implements FNV-1 and FNV-1a, non-cryptographic hash functions
+// created by Glenn Fowler, Landon Curt Noll, and Phong Vo.
 // See http://isthe.com/chongo/tech/comp/fnv/.
 package fnv
 
diff --git a/src/pkg/hash/hash.go b/src/pkg/hash/hash.go
index 56ac259..3536c0b 100644
--- a/src/pkg/hash/hash.go
+++ b/src/pkg/hash/hash.go
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// Package hash provides interfaces for hash functions.
 package hash
 
 import "io"
diff --git a/src/pkg/html/doc.go b/src/pkg/html/doc.go
index 4f5dee7..55135c3 100644
--- a/src/pkg/html/doc.go
+++ b/src/pkg/html/doc.go
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 /*
-The html package implements an HTML5-compliant tokenizer and parser.
+Package html implements an HTML5-compliant tokenizer and parser.
 
 Tokenization is done by creating a Tokenizer for an io.Reader r. It is the
 caller's responsibility to ensure that r provides UTF-8 encoded HTML.
diff --git a/src/pkg/html/parse_test.go b/src/pkg/html/parse_test.go
index fe95543..3fa35d5 100644
--- a/src/pkg/html/parse_test.go
+++ b/src/pkg/html/parse_test.go
@@ -15,12 +15,6 @@ import (
 	"testing"
 )
 
-type devNull struct{}
-
-func (devNull) Write(p []byte) (int, os.Error) {
-	return len(p), nil
-}
-
 func pipeErr(err os.Error) io.Reader {
 	pr, pw := io.Pipe()
 	pw.CloseWithError(err)
@@ -141,7 +135,7 @@ func TestParser(t *testing.T) {
 				t.Fatal(err)
 			}
 			// Skip the #error section.
-			if _, err := io.Copy(devNull{}, <-rc); err != nil {
+			if _, err := io.Copy(ioutil.Discard, <-rc); err != nil {
 				t.Fatal(err)
 			}
 			// Compare the parsed tree to the #document section.
diff --git a/src/pkg/http/Makefile b/src/pkg/http/Makefile
index 389b042..2a2a2a3 100644
--- a/src/pkg/http/Makefile
+++ b/src/pkg/http/Makefile
@@ -16,6 +16,7 @@ GOFILES=\
 	persist.go\
 	request.go\
 	response.go\
+	reverseproxy.go\
 	server.go\
 	status.go\
 	transfer.go\
diff --git a/src/pkg/http/cgi/host.go b/src/pkg/http/cgi/host.go
index a713d7c..136d4e4 100644
--- a/src/pkg/http/cgi/host.go
+++ b/src/pkg/http/cgi/host.go
@@ -25,20 +25,40 @@ import (
 	"os"
 	"path/filepath"
 	"regexp"
+	"runtime"
 	"strconv"
 	"strings"
 )
 
 var trailingPort = regexp.MustCompile(`:([0-9]+)$`)
 
+var osDefaultInheritEnv = map[string][]string{
+	"darwin":  []string{"DYLD_LIBRARY_PATH"},
+	"freebsd": []string{"LD_LIBRARY_PATH"},
+	"hpux":    []string{"LD_LIBRARY_PATH", "SHLIB_PATH"},
+	"linux":   []string{"LD_LIBRARY_PATH"},
+	"windows": []string{"SystemRoot", "COMSPEC", "PATHEXT", "WINDIR"},
+}
+
 // Handler runs an executable in a subprocess with a CGI environment.
 type Handler struct {
 	Path string // path to the CGI executable
 	Root string // root URI prefix of handler or empty for "/"
 
-	Env    []string    // extra environment variables to set, if any
-	Logger *log.Logger // optional log for errors or nil to use log.Print
-	Args   []string    // optional arguments to pass to child process
+	Env        []string    // extra environment variables to set, if any, as "key=value"
+	InheritEnv []string    // environment variables to inherit from host, as "key"
+	Logger     *log.Logger // optional log for errors or nil to use log.Print
+	Args       []string    // optional arguments to pass to child process
+
+	// PathLocationHandler specifies the root http Handler that
+	// should handle internal redirects when the CGI process
+	// returns a Location header value starting with a "/", as
+	// specified in RFC 3875 § 6.3.2. This will likely be
+	// http.DefaultServeMux.
+	//
+	// If nil, a CGI response with a local URI path is instead sent
+	// back to the client and not redirected internally.
+	PathLocationHandler http.Handler
 }
 
 func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
@@ -110,6 +130,24 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
 		env = append(env, h.Env...)
 	}
 
+	path := os.Getenv("PATH")
+	if path == "" {
+		path = "/bin:/usr/bin:/usr/ucb:/usr/bsd:/usr/local/bin"
+	}
+	env = append(env, "PATH="+path)
+
+	for _, e := range h.InheritEnv {
+		if v := os.Getenv(e); v != "" {
+			env = append(env, e+"="+v)
+		}
+	}
+
+	for _, e := range osDefaultInheritEnv[runtime.GOOS] {
+		if v := os.Getenv(e); v != "" {
+			env = append(env, e+"="+v)
+		}
+	}
+
 	cwd, pathBase := filepath.Split(h.Path)
 	if cwd == "" {
 		cwd = "."
@@ -143,13 +181,13 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
 	}
 
 	linebody, _ := bufio.NewReaderSize(cmd.Stdout, 1024)
-	headers := rw.Header()
-	statusCode := http.StatusOK
+	headers := make(http.Header)
+	statusCode := 0
 	for {
 		line, isPrefix, err := linebody.ReadLine()
 		if isPrefix {
 			rw.WriteHeader(http.StatusInternalServerError)
-			h.printf("CGI: long header line from subprocess.")
+			h.printf("cgi: long header line from subprocess.")
 			return
 		}
 		if err == os.EOF {
@@ -157,7 +195,7 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
 		}
 		if err != nil {
 			rw.WriteHeader(http.StatusInternalServerError)
-			h.printf("CGI: error reading headers: %v", err)
+			h.printf("cgi: error reading headers: %v", err)
 			return
 		}
 		if len(line) == 0 {
@@ -165,7 +203,7 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
 		}
 		parts := strings.Split(string(line), ":", 2)
 		if len(parts) < 2 {
-			h.printf("CGI: bogus header line: %s", string(line))
+			h.printf("cgi: bogus header line: %s", string(line))
 			continue
 		}
 		header, val := parts[0], parts[1]
@@ -174,13 +212,13 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
 		switch {
 		case header == "Status":
 			if len(val) < 3 {
-				h.printf("CGI: bogus status (short): %q", val)
+				h.printf("cgi: bogus status (short): %q", val)
 				return
 			}
 			code, err := strconv.Atoi(val[0:3])
 			if err != nil {
-				h.printf("CGI: bogus status: %q", val)
-				h.printf("CGI: line was %q", line)
+				h.printf("cgi: bogus status: %q", val)
+				h.printf("cgi: line was %q", line)
 				return
 			}
 			statusCode = code
@@ -188,11 +226,35 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
 			headers.Add(header, val)
 		}
 	}
+
+	if loc := headers.Get("Location"); loc != "" {
+		if strings.HasPrefix(loc, "/") && h.PathLocationHandler != nil {
+			h.handleInternalRedirect(rw, req, loc)
+			return
+		}
+		if statusCode == 0 {
+			statusCode = http.StatusFound
+		}
+	}
+
+	if statusCode == 0 {
+		statusCode = http.StatusOK
+	}
+
+	// Copy headers to rw's headers, after we've decided not to
+	// go into handleInternalRedirect, which won't want its rw
+	// headers to have been touched.
+	for k, vv := range headers {
+		for _, v := range vv {
+			rw.Header().Add(k, v)
+		}
+	}
+
 	rw.WriteHeader(statusCode)
 
 	_, err = io.Copy(rw, linebody)
 	if err != nil {
-		h.printf("CGI: copy error: %v", err)
+		h.printf("cgi: copy error: %v", err)
 	}
 }
 
@@ -204,6 +266,37 @@ func (h *Handler) printf(format string, v ...interface{}) {
 	}
 }
 
+func (h *Handler) handleInternalRedirect(rw http.ResponseWriter, req *http.Request, path string) {
+	url, err := req.URL.ParseURL(path)
+	if err != nil {
+		rw.WriteHeader(http.StatusInternalServerError)
+		h.printf("cgi: error resolving local URI path %q: %v", path, err)
+		return
+	}
+	// TODO: RFC 3875 isn't clear if only GET is supported, but it
+	// suggests so: "Note that any message-body attached to the
+	// request (such as for a POST request) may not be available
+	// to the resource that is the target of the redirect."  We
+	// should do some tests against Apache to see how it handles
+	// POST, HEAD, etc. Does the internal redirect get the same
+	// method or just GET? What about incoming headers?
+	// (e.g. Cookies) Which headers, if any, are copied into the
+	// second request?
+	newReq := &http.Request{
+		Method:     "GET",
+		URL:        url,
+		RawURL:     path,
+		Proto:      "HTTP/1.1",
+		ProtoMajor: 1,
+		ProtoMinor: 1,
+		Header:     make(http.Header),
+		Host:       url.Host,
+		RemoteAddr: req.RemoteAddr,
+		TLS:        req.TLS,
+	}
+	h.PathLocationHandler.ServeHTTP(rw, newReq)
+}
+
 func upperCaseAndUnderscore(rune int) int {
 	switch {
 	case rune >= 'a' && rune <= 'z':
diff --git a/src/pkg/http/cgi/host_test.go b/src/pkg/http/cgi/host_test.go
index e8084b1..9ac085f 100644
--- a/src/pkg/http/cgi/host_test.go
+++ b/src/pkg/http/cgi/host_test.go
@@ -271,3 +271,40 @@ Transfer-Encoding: chunked
 			expected, got)
 	}
 }
+
+func TestRedirect(t *testing.T) {
+	if skipTest(t) {
+		return
+	}
+	h := &Handler{
+		Path: "testdata/test.cgi",
+		Root: "/test.cgi",
+	}
+	rec := runCgiTest(t, h, "GET /test.cgi?loc=http://foo.com/ HTTP/1.0\nHost: example.com\n\n", nil)
+	if e, g := 302, rec.Code; e != g {
+		t.Errorf("expected status code %d; got %d", e, g)
+	}
+	if e, g := "http://foo.com/", rec.Header().Get("Location"); e != g {
+		t.Errorf("expected Location header of %q; got %q", e, g)
+	}
+}
+
+func TestInternalRedirect(t *testing.T) {
+	if skipTest(t) {
+		return
+	}
+	baseHandler := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
+		fmt.Fprintf(rw, "basepath=%s\n", req.URL.Path)
+		fmt.Fprintf(rw, "remoteaddr=%s\n", req.RemoteAddr)
+	})
+	h := &Handler{
+		Path:                "testdata/test.cgi",
+		Root:                "/test.cgi",
+		PathLocationHandler: baseHandler,
+	}
+	expectedMap := map[string]string{
+		"basepath":   "/foo",
+		"remoteaddr": "1.2.3.4",
+	}
+	runCgiTest(t, h, "GET /test.cgi?loc=/foo HTTP/1.0\nHost: example.com\n\n", expectedMap)
+}
diff --git a/src/pkg/http/cgi/testdata/test.cgi b/src/pkg/http/cgi/testdata/test.cgi
index 253589e..a1b2ff8 100755
--- a/src/pkg/http/cgi/testdata/test.cgi
+++ b/src/pkg/http/cgi/testdata/test.cgi
@@ -11,6 +11,11 @@ use CGI;
 my $q = CGI->new;
 my $params = $q->Vars;
 
+if ($params->{"loc"}) {
+    print "Location: $params->{loc}\r\n\r\n";
+    exit(0);
+}
+
 my $NL = "\r\n";
 $NL = "\n" if $params->{mode} eq "NL";
 
diff --git a/src/pkg/http/client.go b/src/pkg/http/client.go
index daba3a8..d73cbc8 100644
--- a/src/pkg/http/client.go
+++ b/src/pkg/http/client.go
@@ -22,6 +22,16 @@ import (
 // Client is not yet very configurable.
 type Client struct {
 	Transport RoundTripper // if nil, DefaultTransport is used
+
+	// If CheckRedirect is not nil, the client calls it before
+	// following an HTTP redirect. The arguments req and via
+	// are the upcoming request and the requests made already,
+	// oldest first. If CheckRedirect returns an error, the client
+	// returns that error instead of issue the Request req.
+	//
+	// If CheckRedirect is nil, the Client uses its default policy,
+	// which is to stop after 10 consecutive requests.
+	CheckRedirect func(req *Request, via []*Request) os.Error
 }
 
 // DefaultClient is the default Client and is used by Get, Head, and Post.
@@ -109,7 +119,7 @@ func shouldRedirect(statusCode int) bool {
 }
 
 // Get issues a GET to the specified URL.  If the response is one of the following
-// redirect codes, it follows the redirect, up to a maximum of 10 redirects:
+// redirect codes, Get follows the redirect, up to a maximum of 10 redirects:
 //
 //    301 (Moved Permanently)
 //    302 (Found)
@@ -126,35 +136,33 @@ func Get(url string) (r *Response, finalURL string, err os.Error) {
 	return DefaultClient.Get(url)
 }
 
-// Get issues a GET to the specified URL.  If the response is one of the following
-// redirect codes, it follows the redirect, up to a maximum of 10 redirects:
+// Get issues a GET to the specified URL.  If the response is one of the
+// following redirect codes, Get follows the redirect after calling the
+// Client's CheckRedirect function.
 //
 //    301 (Moved Permanently)
 //    302 (Found)
 //    303 (See Other)
 //    307 (Temporary Redirect)
 //
-// finalURL is the URL from which the response was fetched -- identical to the
-// input URL unless redirects were followed.
+// finalURL is the URL from which the response was fetched -- identical
+// to the input URL unless redirects were followed.
 //
 // Caller should close r.Body when done reading from it.
 func (c *Client) Get(url string) (r *Response, finalURL string, err os.Error) {
 	// TODO: if/when we add cookie support, the redirected request shouldn't
 	// necessarily supply the same cookies as the original.
-	// TODO: set referrer header on redirects.
 	var base *URL
-	// TODO: remove this hard-coded 10 and use the Client's policy
-	// (ClientConfig) instead.
-	for redirect := 0; ; redirect++ {
-		if redirect >= 10 {
-			err = os.ErrorString("stopped after 10 redirects")
-			break
-		}
+	redirectChecker := c.CheckRedirect
+	if redirectChecker == nil {
+		redirectChecker = defaultCheckRedirect
+	}
+	var via []*Request
 
+	for redirect := 0; ; redirect++ {
 		var req Request
 		req.Method = "GET"
-		req.ProtoMajor = 1
-		req.ProtoMinor = 1
+		req.Header = make(Header)
 		if base == nil {
 			req.URL, err = ParseURL(url)
 		} else {
@@ -163,6 +171,19 @@ func (c *Client) Get(url string) (r *Response, finalURL string, err os.Error) {
 		if err != nil {
 			break
 		}
+		if len(via) > 0 {
+			// Add the Referer header.
+			lastReq := via[len(via)-1]
+			if lastReq.URL.Scheme != "https" {
+				req.Referer = lastReq.URL.String()
+			}
+
+			err = redirectChecker(&req, via)
+			if err != nil {
+				break
+			}
+		}
+
 		url = req.URL.String()
 		if r, err = send(&req, c.Transport); err != nil {
 			break
@@ -174,6 +195,7 @@ func (c *Client) Get(url string) (r *Response, finalURL string, err os.Error) {
 				break
 			}
 			base = req.URL
+			via = append(via, &req)
 			continue
 		}
 		finalURL = url
@@ -184,6 +206,13 @@ func (c *Client) Get(url string) (r *Response, finalURL string, err os.Error) {
 	return
 }
 
+func defaultCheckRedirect(req *Request, via []*Request) os.Error {
+	if len(via) >= 10 {
+		return os.ErrorString("stopped after 10 redirects")
+	}
+	return nil
+}
+
 // Post issues a POST to the specified URL.
 //
 // Caller should close r.Body when done reading from it.
diff --git a/src/pkg/http/client_test.go b/src/pkg/http/client_test.go
index 3a6f834..59d62c1 100644
--- a/src/pkg/http/client_test.go
+++ b/src/pkg/http/client_test.go
@@ -12,6 +12,7 @@ import (
 	"http/httptest"
 	"io/ioutil"
 	"os"
+	"strconv"
 	"strings"
 	"testing"
 )
@@ -75,3 +76,51 @@ func TestGetRequestFormat(t *testing.T) {
 		t.Errorf("expected non-nil request Header")
 	}
 }
+
+func TestRedirects(t *testing.T) {
+	var ts *httptest.Server
+	ts = httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		n, _ := strconv.Atoi(r.FormValue("n"))
+		// Test Referer header. (7 is arbitrary position to test at)
+		if n == 7 {
+			if g, e := r.Referer, ts.URL+"/?n=6"; e != g {
+				t.Errorf("on request ?n=7, expected referer of %q; got %q", e, g)
+			}
+		}
+		if n < 15 {
+			Redirect(w, r, fmt.Sprintf("/?n=%d", n+1), StatusFound)
+			return
+		}
+		fmt.Fprintf(w, "n=%d", n)
+	}))
+	defer ts.Close()
+
+	c := &Client{}
+	_, _, err := c.Get(ts.URL)
+	if e, g := "Get /?n=10: stopped after 10 redirects", fmt.Sprintf("%v", err); e != g {
+		t.Errorf("with default client, expected error %q, got %q", e, g)
+	}
+
+	var checkErr os.Error
+	var lastVia []*Request
+	c = &Client{CheckRedirect: func(_ *Request, via []*Request) os.Error {
+		lastVia = via
+		return checkErr
+	}}
+	_, finalUrl, err := c.Get(ts.URL)
+	if e, g := "<nil>", fmt.Sprintf("%v", err); e != g {
+		t.Errorf("with custom client, expected error %q, got %q", e, g)
+	}
+	if !strings.HasSuffix(finalUrl, "/?n=15") {
+		t.Errorf("expected final url to end in /?n=15; got url %q", finalUrl)
+	}
+	if e, g := 15, len(lastVia); e != g {
+		t.Errorf("expected lastVia to have contained %d elements; got %d", e, g)
+	}
+
+	checkErr = os.NewError("no redirects allowed")
+	_, finalUrl, err = c.Get(ts.URL)
+	if e, g := "Get /?n=1: no redirects allowed", fmt.Sprintf("%v", err); e != g {
+		t.Errorf("with redirects forbidden, expected error %q, got %q", e, g)
+	}
+}
diff --git a/src/pkg/http/cookie.go b/src/pkg/http/cookie.go
index 2bb66e5..2c01826 100644
--- a/src/pkg/http/cookie.go
+++ b/src/pkg/http/cookie.go
@@ -142,12 +142,12 @@ func writeSetCookies(w io.Writer, kk []*Cookie) os.Error {
 	var b bytes.Buffer
 	for _, c := range kk {
 		b.Reset()
-		fmt.Fprintf(&b, "%s=%s", c.Name, c.Value)
+		fmt.Fprintf(&b, "%s=%s", sanitizeName(c.Name), sanitizeValue(c.Value))
 		if len(c.Path) > 0 {
-			fmt.Fprintf(&b, "; Path=%s", URLEscape(c.Path))
+			fmt.Fprintf(&b, "; Path=%s", sanitizeValue(c.Path))
 		}
 		if len(c.Domain) > 0 {
-			fmt.Fprintf(&b, "; Domain=%s", URLEscape(c.Domain))
+			fmt.Fprintf(&b, "; Domain=%s", sanitizeValue(c.Domain))
 		}
 		if len(c.Expires.Zone) > 0 {
 			fmt.Fprintf(&b, "; Expires=%s", c.Expires.Format(time.RFC1123))
@@ -225,7 +225,7 @@ func readCookies(h Header) []*Cookie {
 func writeCookies(w io.Writer, kk []*Cookie) os.Error {
 	lines := make([]string, 0, len(kk))
 	for _, c := range kk {
-		lines = append(lines, fmt.Sprintf("Cookie: %s=%s\r\n", c.Name, c.Value))
+		lines = append(lines, fmt.Sprintf("Cookie: %s=%s\r\n", sanitizeName(c.Name), sanitizeValue(c.Value)))
 	}
 	sort.SortStrings(lines)
 	for _, l := range lines {
@@ -236,6 +236,19 @@ func writeCookies(w io.Writer, kk []*Cookie) os.Error {
 	return nil
 }
 
+func sanitizeName(n string) string {
+	n = strings.Replace(n, "\n", "-", -1)
+	n = strings.Replace(n, "\r", "-", -1)
+	return n
+}
+
+func sanitizeValue(v string) string {
+	v = strings.Replace(v, "\n", " ", -1)
+	v = strings.Replace(v, "\r", " ", -1)
+	v = strings.Replace(v, ";", " ", -1)
+	return v
+}
+
 func unquoteCookieValue(v string) string {
 	if len(v) > 1 && v[0] == '"' && v[len(v)-1] == '"' {
 		return v[1 : len(v)-1]
diff --git a/src/pkg/http/cookie_test.go b/src/pkg/http/cookie_test.go
index db09970..a3ae85c 100644
--- a/src/pkg/http/cookie_test.go
+++ b/src/pkg/http/cookie_test.go
@@ -21,9 +21,13 @@ var writeSetCookiesTests = []struct {
 		[]*Cookie{
 			&Cookie{Name: "cookie-1", Value: "v$1"},
 			&Cookie{Name: "cookie-2", Value: "two", MaxAge: 3600},
+			&Cookie{Name: "cookie-3", Value: "three", Domain: ".example.com"},
+			&Cookie{Name: "cookie-4", Value: "four", Path: "/restricted/"},
 		},
 		"Set-Cookie: cookie-1=v$1\r\n" +
-			"Set-Cookie: cookie-2=two; Max-Age=3600\r\n",
+			"Set-Cookie: cookie-2=two; Max-Age=3600\r\n" +
+			"Set-Cookie: cookie-3=three; Domain=.example.com\r\n" +
+			"Set-Cookie: cookie-4=four; Path=/restricted/\r\n",
 	},
 }
 
diff --git a/src/pkg/http/dump.go b/src/pkg/http/dump.go
index 306c45b..358980f 100644
--- a/src/pkg/http/dump.go
+++ b/src/pkg/http/dump.go
@@ -31,6 +31,8 @@ func drainBody(b io.ReadCloser) (r1, r2 io.ReadCloser, err os.Error) {
 // DumpRequest is semantically a no-op, but in order to
 // dump the body, it reads the body data into memory and
 // changes req.Body to refer to the in-memory copy.
+// The documentation for Request.Write details which fields
+// of req are used.
 func DumpRequest(req *Request, body bool) (dump []byte, err os.Error) {
 	var b bytes.Buffer
 	save := req.Body
diff --git a/src/pkg/http/export_test.go b/src/pkg/http/export_test.go
index 47c6877..3fe6586 100644
--- a/src/pkg/http/export_test.go
+++ b/src/pkg/http/export_test.go
@@ -32,3 +32,10 @@ func (t *Transport) IdleConnCountForTesting(cacheKey string) int {
 	}
 	return len(conns)
 }
+
+func NewTestTimeoutHandler(handler Handler, ch <-chan int64) Handler {
+	f := func() <-chan int64 {
+		return ch
+	}
+	return &timeoutHandler{handler, f, ""}
+}
diff --git a/src/pkg/http/fcgi/Makefile b/src/pkg/http/fcgi/Makefile
new file mode 100644
index 0000000..bc01cde
--- /dev/null
+++ b/src/pkg/http/fcgi/Makefile
@@ -0,0 +1,12 @@
+# Copyright 2011 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=http/fcgi
+GOFILES=\
+	child.go\
+	fcgi.go\
+
+include ../../../Make.pkg
diff --git a/src/pkg/http/fcgi/child.go b/src/pkg/http/fcgi/child.go
new file mode 100644
index 0000000..114052b
--- /dev/null
+++ b/src/pkg/http/fcgi/child.go
@@ -0,0 +1,328 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package fcgi
+
+// This file implements FastCGI from the perspective of a child process.
+
+import (
+	"fmt"
+	"http"
+	"io"
+	"net"
+	"os"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// request holds the state for an in-progress request. As soon as it's complete,
+// it's converted to an http.Request.
+type request struct {
+	pw        *io.PipeWriter
+	reqId     uint16
+	params    map[string]string
+	buf       [1024]byte
+	rawParams []byte
+	keepConn  bool
+}
+
+func newRequest(reqId uint16, flags uint8) *request {
+	r := &request{
+		reqId:    reqId,
+		params:   map[string]string{},
+		keepConn: flags&flagKeepConn != 0,
+	}
+	r.rawParams = r.buf[:0]
+	return r
+}
+
+// TODO(eds): copied from http/cgi
+var skipHeader = map[string]bool{
+	"HTTP_HOST":       true,
+	"HTTP_REFERER":    true,
+	"HTTP_USER_AGENT": true,
+}
+
+// httpRequest converts r to an http.Request.
+// TODO(eds): this is very similar to http/cgi's requestFromEnvironment
+func (r *request) httpRequest(body io.ReadCloser) (*http.Request, os.Error) {
+	req := &http.Request{
+		Method:  r.params["REQUEST_METHOD"],
+		RawURL:  r.params["REQUEST_URI"],
+		Body:    body,
+		Header:  http.Header{},
+		Trailer: http.Header{},
+		Proto:   r.params["SERVER_PROTOCOL"],
+	}
+
+	var ok bool
+	req.ProtoMajor, req.ProtoMinor, ok = http.ParseHTTPVersion(req.Proto)
+	if !ok {
+		return nil, os.NewError("fcgi: invalid HTTP version")
+	}
+
+	req.Host = r.params["HTTP_HOST"]
+	req.Referer = r.params["HTTP_REFERER"]
+	req.UserAgent = r.params["HTTP_USER_AGENT"]
+
+	if lenstr := r.params["CONTENT_LENGTH"]; lenstr != "" {
+		clen, err := strconv.Atoi64(r.params["CONTENT_LENGTH"])
+		if err != nil {
+			return nil, os.NewError("fcgi: bad CONTENT_LENGTH parameter: " + lenstr)
+		}
+		req.ContentLength = clen
+	}
+
+	if req.Host != "" {
+		req.RawURL = "http://" + req.Host + r.params["REQUEST_URI"]
+		url, err := http.ParseURL(req.RawURL)
+		if err != nil {
+			return nil, os.NewError("fcgi: failed to parse host and REQUEST_URI into a URL: " + req.RawURL)
+		}
+		req.URL = url
+	}
+	if req.URL == nil {
+		req.RawURL = r.params["REQUEST_URI"]
+		url, err := http.ParseURL(req.RawURL)
+		if err != nil {
+			return nil, os.NewError("fcgi: failed to parse REQUEST_URI into a URL: " + req.RawURL)
+		}
+		req.URL = url
+	}
+
+	for key, val := range r.params {
+		if strings.HasPrefix(key, "HTTP_") && !skipHeader[key] {
+			req.Header.Add(strings.Replace(key[5:], "_", "-", -1), val)
+		}
+	}
+	return req, nil
+}
+
+// parseParams reads an encoded []byte into Params.
+func (r *request) parseParams() {
+	text := r.rawParams
+	r.rawParams = nil
+	for len(text) > 0 {
+		keyLen, n := readSize(text)
+		if n == 0 {
+			return
+		}
+		text = text[n:]
+		valLen, n := readSize(text)
+		if n == 0 {
+			return
+		}
+		text = text[n:]
+		key := readString(text, keyLen)
+		text = text[keyLen:]
+		val := readString(text, valLen)
+		text = text[valLen:]
+		r.params[key] = val
+	}
+}
+
+// response implements http.ResponseWriter.
+type response struct {
+	req         *request
+	header      http.Header
+	w           *bufWriter
+	wroteHeader bool
+}
+
+func newResponse(c *child, req *request) *response {
+	return &response{
+		req:    req,
+		header: http.Header{},
+		w:      newWriter(c.conn, typeStdout, req.reqId),
+	}
+}
+
+func (r *response) Header() http.Header {
+	return r.header
+}
+
+func (r *response) Write(data []byte) (int, os.Error) {
+	if !r.wroteHeader {
+		r.WriteHeader(http.StatusOK)
+	}
+	return r.w.Write(data)
+}
+
+func (r *response) WriteHeader(code int) {
+	if r.wroteHeader {
+		return
+	}
+	r.wroteHeader = true
+	if code == http.StatusNotModified {
+		// Must not have body.
+		r.header.Del("Content-Type")
+		r.header.Del("Content-Length")
+		r.header.Del("Transfer-Encoding")
+	} else if r.header.Get("Content-Type") == "" {
+		r.header.Set("Content-Type", "text/html; charset=utf-8")
+	}
+
+	if r.header.Get("Date") == "" {
+		r.header.Set("Date", time.UTC().Format(http.TimeFormat))
+	}
+
+	fmt.Fprintf(r.w, "Status: %d %s\r\n", code, http.StatusText(code))
+	// TODO(eds): this is duplicated in http and http/cgi
+	for k, vv := range r.header {
+		for _, v := range vv {
+			v = strings.Replace(v, "\n", "", -1)
+			v = strings.Replace(v, "\r", "", -1)
+			v = strings.TrimSpace(v)
+			fmt.Fprintf(r.w, "%s: %s\r\n", k, v)
+		}
+	}
+	r.w.WriteString("\r\n")
+}
+
+func (r *response) Flush() {
+	if !r.wroteHeader {
+		r.WriteHeader(http.StatusOK)
+	}
+	r.w.Flush()
+}
+
+func (r *response) Close() os.Error {
+	r.Flush()
+	return r.w.Close()
+}
+
+type child struct {
+	conn    *conn
+	handler http.Handler
+}
+
+func newChild(rwc net.Conn, handler http.Handler) *child {
+	return &child{newConn(rwc), handler}
+}
+
+func (c *child) serve() {
+	requests := map[uint16]*request{}
+	defer c.conn.Close()
+	var rec record
+	var br beginRequest
+	for {
+		if err := rec.read(c.conn.rwc); err != nil {
+			return
+		}
+
+		req, ok := requests[rec.h.Id]
+		if !ok && rec.h.Type != typeBeginRequest && rec.h.Type != typeGetValues {
+			// The spec says to ignore unknown request IDs.
+			continue
+		}
+		if ok && rec.h.Type == typeBeginRequest {
+			// The server is trying to begin a request with the same ID
+			// as an in-progress request. This is an error.
+			return
+		}
+
+		switch rec.h.Type {
+		case typeBeginRequest:
+			if err := br.read(rec.content()); err != nil {
+				return
+			}
+			if br.role != roleResponder {
+				c.conn.writeEndRequest(rec.h.Id, 0, statusUnknownRole)
+				break
+			}
+			requests[rec.h.Id] = newRequest(rec.h.Id, br.flags)
+		case typeParams:
+			// NOTE(eds): Technically a key-value pair can straddle the boundary
+			// between two packets. We buffer until we've received all parameters.
+			if len(rec.content()) > 0 {
+				req.rawParams = append(req.rawParams, rec.content()...)
+				break
+			}
+			req.parseParams()
+		case typeStdin:
+			content := rec.content()
+			if req.pw == nil {
+				var body io.ReadCloser
+				if len(content) > 0 {
+					// body could be an io.LimitReader, but it shouldn't matter
+					// as long as both sides are behaving.
+					body, req.pw = io.Pipe()
+				}
+				go c.serveRequest(req, body)
+			}
+			if len(content) > 0 {
+				// TODO(eds): This blocks until the handler reads from the pipe.
+				// If the handler takes a long time, it might be a problem.
+				req.pw.Write(content)
+			} else if req.pw != nil {
+				req.pw.Close()
+			}
+		case typeGetValues:
+			values := map[string]string{"FCGI_MPXS_CONNS": "1"}
+			c.conn.writePairs(0, typeGetValuesResult, values)
+		case typeData:
+			// If the filter role is implemented, read the data stream here.
+		case typeAbortRequest:
+			requests[rec.h.Id] = nil, false
+			c.conn.writeEndRequest(rec.h.Id, 0, statusRequestComplete)
+			if !req.keepConn {
+				// connection will close upon return
+				return
+			}
+		default:
+			b := make([]byte, 8)
+			b[0] = rec.h.Type
+			c.conn.writeRecord(typeUnknownType, 0, b)
+		}
+	}
+}
+
+func (c *child) serveRequest(req *request, body io.ReadCloser) {
+	r := newResponse(c, req)
+	httpReq, err := req.httpRequest(body)
+	if err != nil {
+		// there was an error reading the request
+		r.WriteHeader(http.StatusInternalServerError)
+		c.conn.writeRecord(typeStderr, req.reqId, []byte(err.String()))
+	} else {
+		c.handler.ServeHTTP(r, httpReq)
+	}
+	if body != nil {
+		body.Close()
+	}
+	r.Close()
+	c.conn.writeEndRequest(req.reqId, 0, statusRequestComplete)
+	if !req.keepConn {
+		c.conn.Close()
+	}
+}
+
+// Serve accepts incoming FastCGI connections on the listener l, creating a new
+// service thread for each. The service threads read requests and then call handler
+// to reply to them.
+// If l is nil, Serve accepts connections on stdin.
+// If handler is nil, http.DefaultServeMux is used.
+func Serve(l net.Listener, handler http.Handler) os.Error {
+	if l == nil {
+		var err os.Error
+		l, err = net.FileListener(os.Stdin)
+		if err != nil {
+			return err
+		}
+		defer l.Close()
+	}
+	if handler == nil {
+		handler = http.DefaultServeMux
+	}
+	for {
+		rw, err := l.Accept()
+		if err != nil {
+			return err
+		}
+		c := newChild(rw, handler)
+		go c.serve()
+	}
+	panic("unreachable")
+}
diff --git a/src/pkg/http/fcgi/fcgi.go b/src/pkg/http/fcgi/fcgi.go
new file mode 100644
index 0000000..8e2e1cd
--- /dev/null
+++ b/src/pkg/http/fcgi/fcgi.go
@@ -0,0 +1,271 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package fcgi implements the FastCGI protocol.
+// Currently only the responder role is supported.
+// The protocol is defined at http://www.fastcgi.com/drupal/node/6?q=node/22
+package fcgi
+
+// This file defines the raw protocol and some utilities used by the child and
+// the host.
+
+import (
+	"bufio"
+	"bytes"
+	"encoding/binary"
+	"io"
+	"os"
+	"sync"
+)
+
+const (
+	// Packet Types
+	typeBeginRequest = iota + 1
+	typeAbortRequest
+	typeEndRequest
+	typeParams
+	typeStdin
+	typeStdout
+	typeStderr
+	typeData
+	typeGetValues
+	typeGetValuesResult
+	typeUnknownType
+)
+
+// keep the connection between web-server and responder open after request
+const flagKeepConn = 1
+
+const (
+	maxWrite = 65535 // maximum record body
+	maxPad   = 255
+)
+
+const (
+	roleResponder = iota + 1 // only Responders are implemented.
+	roleAuthorizer
+	roleFilter
+)
+
+const (
+	statusRequestComplete = iota
+	statusCantMultiplex
+	statusOverloaded
+	statusUnknownRole
+)
+
+const headerLen = 8
+
+type header struct {
+	Version       uint8
+	Type          uint8
+	Id            uint16
+	ContentLength uint16
+	PaddingLength uint8
+	Reserved      uint8
+}
+
+type beginRequest struct {
+	role     uint16
+	flags    uint8
+	reserved [5]uint8
+}
+
+func (br *beginRequest) read(content []byte) os.Error {
+	if len(content) != 8 {
+		return os.NewError("fcgi: invalid begin request record")
+	}
+	br.role = binary.BigEndian.Uint16(content)
+	br.flags = content[2]
+	return nil
+}
+
+// for padding so we don't have to allocate all the time
+// not synchronized because we don't care what the contents are
+var pad [maxPad]byte
+
+func (h *header) init(recType uint8, reqId uint16, contentLength int) {
+	h.Version = 1
+	h.Type = recType
+	h.Id = reqId
+	h.ContentLength = uint16(contentLength)
+	h.PaddingLength = uint8(-contentLength & 7)
+}
+
+// conn sends records over rwc
+type conn struct {
+	mutex sync.Mutex
+	rwc   io.ReadWriteCloser
+
+	// to avoid allocations
+	buf bytes.Buffer
+	h   header
+}
+
+func newConn(rwc io.ReadWriteCloser) *conn {
+	return &conn{rwc: rwc}
+}
+
+func (c *conn) Close() os.Error {
+	c.mutex.Lock()
+	defer c.mutex.Unlock()
+	return c.rwc.Close()
+}
+
+type record struct {
+	h   header
+	buf [maxWrite + maxPad]byte
+}
+
+func (rec *record) read(r io.Reader) (err os.Error) {
+	if err = binary.Read(r, binary.BigEndian, &rec.h); err != nil {
+		return err
+	}
+	if rec.h.Version != 1 {
+		return os.NewError("fcgi: invalid header version")
+	}
+	n := int(rec.h.ContentLength) + int(rec.h.PaddingLength)
+	if _, err = io.ReadFull(r, rec.buf[:n]); err != nil {
+		return err
+	}
+	return nil
+}
+
+func (r *record) content() []byte {
+	return r.buf[:r.h.ContentLength]
+}
+
+// writeRecord writes and sends a single record.
+func (c *conn) writeRecord(recType uint8, reqId uint16, b []byte) os.Error {
+	c.mutex.Lock()
+	defer c.mutex.Unlock()
+	c.buf.Reset()
+	c.h.init(recType, reqId, len(b))
+	if err := binary.Write(&c.buf, binary.BigEndian, c.h); err != nil {
+		return err
+	}
+	if _, err := c.buf.Write(b); err != nil {
+		return err
+	}
+	if _, err := c.buf.Write(pad[:c.h.PaddingLength]); err != nil {
+		return err
+	}
+	_, err := c.rwc.Write(c.buf.Bytes())
+	return err
+}
+
+func (c *conn) writeBeginRequest(reqId uint16, role uint16, flags uint8) os.Error {
+	b := [8]byte{byte(role >> 8), byte(role), flags}
+	return c.writeRecord(typeBeginRequest, reqId, b[:])
+}
+
+func (c *conn) writeEndRequest(reqId uint16, appStatus int, protocolStatus uint8) os.Error {
+	b := make([]byte, 8)
+	binary.BigEndian.PutUint32(b, uint32(appStatus))
+	b[4] = protocolStatus
+	return c.writeRecord(typeEndRequest, reqId, b)
+}
+
+func (c *conn) writePairs(recType uint8, reqId uint16, pairs map[string]string) os.Error {
+	w := newWriter(c, recType, reqId)
+	b := make([]byte, 8)
+	for k, v := range pairs {
+		n := encodeSize(b, uint32(len(k)))
+		n += encodeSize(b[n:], uint32(len(k)))
+		if _, err := w.Write(b[:n]); err != nil {
+			return err
+		}
+		if _, err := w.WriteString(k); err != nil {
+			return err
+		}
+		if _, err := w.WriteString(v); err != nil {
+			return err
+		}
+	}
+	w.Close()
+	return nil
+}
+
+func readSize(s []byte) (uint32, int) {
+	if len(s) == 0 {
+		return 0, 0
+	}
+	size, n := uint32(s[0]), 1
+	if size&(1<<7) != 0 {
+		if len(s) < 4 {
+			return 0, 0
+		}
+		n = 4
+		size = binary.BigEndian.Uint32(s)
+		size &^= 1 << 31
+	}
+	return size, n
+}
+
+func readString(s []byte, size uint32) string {
+	if size > uint32(len(s)) {
+		return ""
+	}
+	return string(s[:size])
+}
+
+func encodeSize(b []byte, size uint32) int {
+	if size > 127 {
+		size |= 1 << 31
+		binary.BigEndian.PutUint32(b, size)
+		return 4
+	}
+	b[0] = byte(size)
+	return 1
+}
+
+// bufWriter encapsulates bufio.Writer but also closes the underlying stream when
+// Closed.
+type bufWriter struct {
+	closer io.Closer
+	*bufio.Writer
+}
+
+func (w *bufWriter) Close() os.Error {
+	if err := w.Writer.Flush(); err != nil {
+		w.closer.Close()
+		return err
+	}
+	return w.closer.Close()
+}
+
+func newWriter(c *conn, recType uint8, reqId uint16) *bufWriter {
+	s := &streamWriter{c: c, recType: recType, reqId: reqId}
+	w, _ := bufio.NewWriterSize(s, maxWrite)
+	return &bufWriter{s, w}
+}
+
+// streamWriter abstracts out the separation of a stream into discrete records.
+// It only writes maxWrite bytes at a time.
+type streamWriter struct {
+	c       *conn
+	recType uint8
+	reqId   uint16
+}
+
+func (w *streamWriter) Write(p []byte) (int, os.Error) {
+	nn := 0
+	for len(p) > 0 {
+		n := len(p)
+		if n > maxWrite {
+			n = maxWrite
+		}
+		if err := w.c.writeRecord(w.recType, w.reqId, p[:n]); err != nil {
+			return nn, err
+		}
+		nn += n
+		p = p[n:]
+	}
+	return nn, nil
+}
+
+func (w *streamWriter) Close() os.Error {
+	// send empty record to close the stream
+	return w.c.writeRecord(w.recType, w.reqId, nil)
+}
diff --git a/src/pkg/http/fcgi/fcgi_test.go b/src/pkg/http/fcgi/fcgi_test.go
new file mode 100644
index 0000000..16a6243
--- /dev/null
+++ b/src/pkg/http/fcgi/fcgi_test.go
@@ -0,0 +1,114 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package fcgi
+
+import (
+	"bytes"
+	"io"
+	"os"
+	"testing"
+)
+
+var sizeTests = []struct {
+	size  uint32
+	bytes []byte
+}{
+	{0, []byte{0x00}},
+	{127, []byte{0x7F}},
+	{128, []byte{0x80, 0x00, 0x00, 0x80}},
+	{1000, []byte{0x80, 0x00, 0x03, 0xE8}},
+	{33554431, []byte{0x81, 0xFF, 0xFF, 0xFF}},
+}
+
+func TestSize(t *testing.T) {
+	b := make([]byte, 4)
+	for i, test := range sizeTests {
+		n := encodeSize(b, test.size)
+		if !bytes.Equal(b[:n], test.bytes) {
+			t.Errorf("%d expected %x, encoded %x", i, test.bytes, b)
+		}
+		size, n := readSize(test.bytes)
+		if size != test.size {
+			t.Errorf("%d expected %d, read %d", i, test.size, size)
+		}
+		if len(test.bytes) != n {
+			t.Errorf("%d did not consume all the bytes", i)
+		}
+	}
+}
+
+var streamTests = []struct {
+	desc    string
+	recType uint8
+	reqId   uint16
+	content []byte
+	raw     []byte
+}{
+	{"single record", typeStdout, 1, nil,
+		[]byte{1, typeStdout, 0, 1, 0, 0, 0, 0},
+	},
+	// this data will have to be split into two records
+	{"two records", typeStdin, 300, make([]byte, 66000),
+		bytes.Join([][]byte{
+			// header for the first record
+			[]byte{1, typeStdin, 0x01, 0x2C, 0xFF, 0xFF, 1, 0},
+			make([]byte, 65536),
+			// header for the second
+			[]byte{1, typeStdin, 0x01, 0x2C, 0x01, 0xD1, 7, 0},
+			make([]byte, 472),
+			// header for the empty record
+			[]byte{1, typeStdin, 0x01, 0x2C, 0, 0, 0, 0},
+		},
+			nil),
+	},
+}
+
+type nilCloser struct {
+	io.ReadWriter
+}
+
+func (c *nilCloser) Close() os.Error { return nil }
+
+func TestStreams(t *testing.T) {
+	var rec record
+outer:
+	for _, test := range streamTests {
+		buf := bytes.NewBuffer(test.raw)
+		var content []byte
+		for buf.Len() > 0 {
+			if err := rec.read(buf); err != nil {
+				t.Errorf("%s: error reading record: %v", test.desc, err)
+				continue outer
+			}
+			content = append(content, rec.content()...)
+		}
+		if rec.h.Type != test.recType {
+			t.Errorf("%s: got type %d expected %d", test.desc, rec.h.Type, test.recType)
+			continue
+		}
+		if rec.h.Id != test.reqId {
+			t.Errorf("%s: got request ID %d expected %d", test.desc, rec.h.Id, test.reqId)
+			continue
+		}
+		if !bytes.Equal(content, test.content) {
+			t.Errorf("%s: read wrong content", test.desc)
+			continue
+		}
+		buf.Reset()
+		c := newConn(&nilCloser{buf})
+		w := newWriter(c, test.recType, test.reqId)
+		if _, err := w.Write(test.content); err != nil {
+			t.Errorf("%s: error writing record: %v", test.desc, err)
+			continue
+		}
+		if err := w.Close(); err != nil {
+			t.Errorf("%s: error closing stream: %v", test.desc, err)
+			continue
+		}
+		if !bytes.Equal(buf.Bytes(), test.raw) {
+			t.Errorf("%s: wrote wrong content", test.desc)
+		}
+	}
+}
diff --git a/src/pkg/http/fs.go b/src/pkg/http/fs.go
index c5efffc..17d5297 100644
--- a/src/pkg/http/fs.go
+++ b/src/pkg/http/fs.go
@@ -143,7 +143,7 @@ func serveFile(w ResponseWriter, r *Request, name string, redirect bool) {
 			n, _ := io.ReadFull(f, buf[:])
 			b := buf[:n]
 			if isText(b) {
-				ctype = "text-plain; charset=utf-8"
+				ctype = "text/plain; charset=utf-8"
 			} else {
 				// generic binary
 				ctype = "application/octet-stream"
diff --git a/src/pkg/http/fs_test.go b/src/pkg/http/fs_test.go
index 692b986..09d0981 100644
--- a/src/pkg/http/fs_test.go
+++ b/src/pkg/http/fs_test.go
@@ -104,7 +104,7 @@ func TestServeFileContentType(t *testing.T) {
 			t.Errorf("Content-Type mismatch: got %q, want %q", h, want)
 		}
 	}
-	get("text-plain; charset=utf-8")
+	get("text/plain; charset=utf-8")
 	override = true
 	get(ctype)
 }
diff --git a/src/pkg/http/httptest/recorder.go b/src/pkg/http/httptest/recorder.go
index 0dd19a6..f2fedef 100644
--- a/src/pkg/http/httptest/recorder.go
+++ b/src/pkg/http/httptest/recorder.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The httptest package provides utilities for HTTP testing.
+// Package httptest provides utilities for HTTP testing.
 package httptest
 
 import (
diff --git a/src/pkg/http/persist.go b/src/pkg/http/persist.go
index b93c5fe..e4eea68 100644
--- a/src/pkg/http/persist.go
+++ b/src/pkg/http/persist.go
@@ -20,8 +20,8 @@ var (
 
 // A ServerConn reads requests and sends responses over an underlying
 // connection, until the HTTP keepalive logic commands an end. ServerConn
-// does not close the underlying connection. Instead, the user calls Close
-// and regains control over the connection. ServerConn supports pipe-lining,
+// also allows hijacking the underlying connection by calling Hijack
+// to regain control over the connection. ServerConn supports pipe-lining,
 // i.e. requests can be read out of sync (but in the same order) while the
 // respective responses are sent.
 type ServerConn struct {
@@ -45,11 +45,11 @@ func NewServerConn(c net.Conn, r *bufio.Reader) *ServerConn {
 	return &ServerConn{c: c, r: r, pipereq: make(map[*Request]uint)}
 }
 
-// Close detaches the ServerConn and returns the underlying connection as well
-// as the read-side bufio which may have some left over data. Close may be
+// Hijack detaches the ServerConn and returns the underlying connection as well
+// as the read-side bufio which may have some left over data. Hijack may be
 // called before Read has signaled the end of the keep-alive logic. The user
-// should not call Close while Read or Write is in progress.
-func (sc *ServerConn) Close() (c net.Conn, r *bufio.Reader) {
+// should not call Hijack while Read or Write is in progress.
+func (sc *ServerConn) Hijack() (c net.Conn, r *bufio.Reader) {
 	sc.lk.Lock()
 	defer sc.lk.Unlock()
 	c = sc.c
@@ -59,6 +59,15 @@ func (sc *ServerConn) Close() (c net.Conn, r *bufio.Reader) {
 	return
 }
 
+// Close calls Hijack and then also closes the underlying connection
+func (sc *ServerConn) Close() os.Error {
+	c, _ := sc.Hijack()
+	if c != nil {
+		return c.Close()
+	}
+	return nil
+}
+
 // Read returns the next request on the wire. An ErrPersistEOF is returned if
 // it is gracefully determined that there are no more requests (e.g. after the
 // first request on an HTTP/1.0 connection, or after a Connection:close on a
@@ -199,9 +208,9 @@ func (sc *ServerConn) Write(req *Request, resp *Response) os.Error {
 }
 
 // A ClientConn sends request and receives headers over an underlying
-// connection, while respecting the HTTP keepalive logic. ClientConn is not
-// responsible for closing the underlying connection. One must call Close to
-// regain control of that connection and deal with it as desired.
+// connection, while respecting the HTTP keepalive logic. ClientConn
+// supports hijacking the connection calling Hijack to
+// regain control of the underlying net.Conn and deal with it as desired.
 type ClientConn struct {
 	lk              sync.Mutex // read-write protects the following fields
 	c               net.Conn
@@ -239,11 +248,11 @@ func NewProxyClientConn(c net.Conn, r *bufio.Reader) *ClientConn {
 	return cc
 }
 
-// Close detaches the ClientConn and returns the underlying connection as well
-// as the read-side bufio which may have some left over data. Close may be
+// Hijack detaches the ClientConn and returns the underlying connection as well
+// as the read-side bufio which may have some left over data. Hijack may be
 // called before the user or Read have signaled the end of the keep-alive
-// logic. The user should not call Close while Read or Write is in progress.
-func (cc *ClientConn) Close() (c net.Conn, r *bufio.Reader) {
+// logic. The user should not call Hijack while Read or Write is in progress.
+func (cc *ClientConn) Hijack() (c net.Conn, r *bufio.Reader) {
 	cc.lk.Lock()
 	defer cc.lk.Unlock()
 	c = cc.c
@@ -253,6 +262,15 @@ func (cc *ClientConn) Close() (c net.Conn, r *bufio.Reader) {
 	return
 }
 
+// Close calls Hijack and then also closes the underlying connection
+func (cc *ClientConn) Close() os.Error {
+	c, _ := cc.Hijack()
+	if c != nil {
+		return c.Close()
+	}
+	return nil
+}
+
 // Write writes a request. An ErrPersistEOF error is returned if the connection
 // has been closed in an HTTP keepalive sense. If req.Close equals true, the
 // keepalive connection is logically closed after this request and the opposing
diff --git a/src/pkg/http/proxy_test.go b/src/pkg/http/proxy_test.go
index 7050ef5..308bf44 100644
--- a/src/pkg/http/proxy_test.go
+++ b/src/pkg/http/proxy_test.go
@@ -16,9 +16,15 @@ var UseProxyTests = []struct {
 	host  string
 	match bool
 }{
-	{"localhost", false},      // match completely
+	// Never proxy localhost:
+	{"localhost:80", false},
+	{"127.0.0.1", false},
+	{"127.0.0.2", false},
+	{"[::1]", false},
+	{"[::2]", true}, // not a loopback address
+
 	{"barbaz.net", false},     // match as .barbaz.net
-	{"foobar.com:443", false}, // have a port but match 
+	{"foobar.com", false},     // have a port but match 
 	{"foofoobar.com", true},   // not match as a part of foobar.com
 	{"baz.com", true},         // not match as a part of barbaz.com
 	{"localhost.net", true},   // not match as suffix of address
@@ -29,19 +35,16 @@ var UseProxyTests = []struct {
 
 func TestUseProxy(t *testing.T) {
 	oldenv := os.Getenv("NO_PROXY")
-	no_proxy := "foobar.com, .barbaz.net   , localhost"
-	os.Setenv("NO_PROXY", no_proxy)
 	defer os.Setenv("NO_PROXY", oldenv)
 
+	no_proxy := "foobar.com, .barbaz.net"
+	os.Setenv("NO_PROXY", no_proxy)
+
 	tr := &Transport{}
 
 	for _, test := range UseProxyTests {
-		if tr.useProxy(test.host) != test.match {
-			if test.match {
-				t.Errorf("useProxy(%v) = %v, want %v", test.host, !test.match, test.match)
-			} else {
-				t.Errorf("not expected: '%s' shouldn't match as '%s'", test.host, no_proxy)
-			}
+		if tr.useProxy(test.host+":80") != test.match {
+			t.Errorf("useProxy(%v) = %v, want %v", test.host, !test.match, test.match)
 		}
 	}
 }
diff --git a/src/pkg/http/request.go b/src/pkg/http/request.go
index d82894f..b8e9a21 100644
--- a/src/pkg/http/request.go
+++ b/src/pkg/http/request.go
@@ -4,9 +4,8 @@
 
 // HTTP Request reading and parsing.
 
-// The http package implements parsing of HTTP requests, replies,
-// and URLs and provides an extensible HTTP server and a basic
-// HTTP client.
+// Package http implements parsing of HTTP requests, replies, and URLs and
+// provides an extensible HTTP server and a basic HTTP client.
 package http
 
 import (
@@ -25,12 +24,17 @@ import (
 )
 
 const (
-	maxLineLength  = 4096 // assumed <= bufio.defaultBufSize
-	maxValueLength = 4096
-	maxHeaderLines = 1024
-	chunkSize      = 4 << 10 // 4 KB chunks
+	maxLineLength    = 4096 // assumed <= bufio.defaultBufSize
+	maxValueLength   = 4096
+	maxHeaderLines   = 1024
+	chunkSize        = 4 << 10  // 4 KB chunks
+	defaultMaxMemory = 32 << 20 // 32 MB
 )
 
+// ErrMissingFile is returned by FormFile when the provided file field name
+// is either not present in the request or not a file field.
+var ErrMissingFile = os.ErrorString("http: no such file")
+
 // HTTP request parsing errors.
 type ProtocolError struct {
 	os.ErrorString
@@ -65,9 +69,12 @@ var reqExcludeHeader = map[string]bool{
 
 // A Request represents a parsed HTTP request header.
 type Request struct {
-	Method     string // GET, POST, PUT, etc.
-	RawURL     string // The raw URL given in the request.
-	URL        *URL   // Parsed URL.
+	Method string // GET, POST, PUT, etc.
+	RawURL string // The raw URL given in the request.
+	URL    *URL   // Parsed URL.
+
+	// The protocol version for incoming requests.
+	// Outgoing requests always use HTTP/1.1.
 	Proto      string // "HTTP/1.0"
 	ProtoMajor int    // 1
 	ProtoMinor int    // 0
@@ -134,6 +141,10 @@ type Request struct {
 	// The parsed form. Only available after ParseForm is called.
 	Form map[string][]string
 
+	// The parsed multipart form, including file uploads.
+	// Only available after ParseMultipartForm is called.
+	MultipartForm *multipart.Form
+
 	// Trailer maps trailer keys to values.  Like for Header, if the
 	// response has multiple trailer lines with the same key, they will be
 	// concatenated, delimited by commas.
@@ -163,9 +174,30 @@ func (r *Request) ProtoAtLeast(major, minor int) bool {
 		r.ProtoMajor == major && r.ProtoMinor >= minor
 }
 
+// multipartByReader is a sentinel value.
+// Its presence in Request.MultipartForm indicates that parsing of the request
+// body has been handed off to a MultipartReader instead of ParseMultipartFrom.
+var multipartByReader = &multipart.Form{
+	Value: make(map[string][]string),
+	File:  make(map[string][]*multipart.FileHeader),
+}
+
 // MultipartReader returns a MIME multipart reader if this is a
 // multipart/form-data POST request, else returns nil and an error.
+// Use this function instead of ParseMultipartForm to
+// process the request body as a stream.
 func (r *Request) MultipartReader() (multipart.Reader, os.Error) {
+	if r.MultipartForm == multipartByReader {
+		return nil, os.NewError("http: MultipartReader called twice")
+	}
+	if r.MultipartForm != nil {
+		return nil, os.NewError("http: multipart handled by ParseMultipartForm")
+	}
+	r.MultipartForm = multipartByReader
+	return r.multipartReader()
+}
+
+func (r *Request) multipartReader() (multipart.Reader, os.Error) {
 	v := r.Header.Get("Content-Type")
 	if v == "" {
 		return nil, ErrNotMultipart
@@ -199,10 +231,14 @@ const defaultUserAgent = "Go http package"
 //	UserAgent (defaults to defaultUserAgent)
 //	Referer
 //	Header
+//	Cookie
+//	ContentLength
+//	TransferEncoding
 //	Body
 //
-// If Body is present, Write forces "Transfer-Encoding: chunked" as a header
-// and then closes Body when finished sending it.
+// If Body is present but Content-Length is <= 0, Write adds
+// "Transfer-Encoding: chunked" to the header. Body is closed after
+// it is sent.
 func (req *Request) Write(w io.Writer) os.Error {
 	return req.write(w, false)
 }
@@ -420,6 +456,29 @@ func (cr *chunkedReader) Read(b []uint8) (n int, err os.Error) {
 	return n, cr.err
 }
 
+// NewRequest returns a new Request given a method, URL, and optional body.
+func NewRequest(method, url string, body io.Reader) (*Request, os.Error) {
+	u, err := ParseURL(url)
+	if err != nil {
+		return nil, err
+	}
+	rc, ok := body.(io.ReadCloser)
+	if !ok && body != nil {
+		rc = ioutil.NopCloser(body)
+	}
+	req := &Request{
+		Method:     method,
+		URL:        u,
+		Proto:      "HTTP/1.1",
+		ProtoMajor: 1,
+		ProtoMinor: 1,
+		Header:     make(Header),
+		Body:       rc,
+		Host:       u.Host,
+	}
+	return req, nil
+}
+
 // ReadRequest reads and parses a request from b.
 func ReadRequest(b *bufio.Reader) (req *Request, err os.Error) {
 
@@ -549,7 +608,9 @@ func parseQuery(m map[string][]string, query string) (err os.Error) {
 	return err
 }
 
-// ParseForm parses the request body as a form for POST requests, or the raw query for GET requests.
+// ParseForm parses the raw query.
+// For POST requests, it also parses the request body as a form.
+// ParseMultipartForm calls ParseForm automatically.
 // It is idempotent.
 func (r *Request) ParseForm() (err os.Error) {
 	if r.Form != nil {
@@ -567,18 +628,23 @@ func (r *Request) ParseForm() (err os.Error) {
 		ct := r.Header.Get("Content-Type")
 		switch strings.Split(ct, ";", 2)[0] {
 		case "text/plain", "application/x-www-form-urlencoded", "":
-			b, e := ioutil.ReadAll(r.Body)
+			const maxFormSize = int64(10 << 20) // 10 MB is a lot of text.
+			b, e := ioutil.ReadAll(io.LimitReader(r.Body, maxFormSize+1))
 			if e != nil {
 				if err == nil {
 					err = e
 				}
 				break
 			}
+			if int64(len(b)) > maxFormSize {
+				return os.NewError("http: POST too large")
+			}
 			e = parseQuery(r.Form, string(b))
 			if err == nil {
 				err = e
 			}
-		// TODO(dsymonds): Handle multipart/form-data
+		case "multipart/form-data":
+			// handled by ParseMultipartForm
 		default:
 			return &badStringError{"unknown Content-Type", ct}
 		}
@@ -586,11 +652,50 @@ func (r *Request) ParseForm() (err os.Error) {
 	return err
 }
 
+// ParseMultipartForm parses a request body as multipart/form-data.
+// The whole request body is parsed and up to a total of maxMemory bytes of
+// its file parts are stored in memory, with the remainder stored on
+// disk in temporary files.
+// ParseMultipartForm calls ParseForm if necessary.
+// After one call to ParseMultipartForm, subsequent calls have no effect.
+func (r *Request) ParseMultipartForm(maxMemory int64) os.Error {
+	if r.Form == nil {
+		err := r.ParseForm()
+		if err != nil {
+			return err
+		}
+	}
+	if r.MultipartForm != nil {
+		return nil
+	}
+	if r.MultipartForm == multipartByReader {
+		return os.NewError("http: multipart handled by MultipartReader")
+	}
+
+	mr, err := r.multipartReader()
+	if err == ErrNotMultipart {
+		return nil
+	} else if err != nil {
+		return err
+	}
+
+	f, err := mr.ReadForm(maxMemory)
+	if err != nil {
+		return err
+	}
+	for k, v := range f.Value {
+		r.Form[k] = append(r.Form[k], v...)
+	}
+	r.MultipartForm = f
+
+	return nil
+}
+
 // FormValue returns the first value for the named component of the query.
-// FormValue calls ParseForm if necessary.
+// FormValue calls ParseMultipartForm and ParseForm if necessary.
 func (r *Request) FormValue(key string) string {
 	if r.Form == nil {
-		r.ParseForm()
+		r.ParseMultipartForm(defaultMaxMemory)
 	}
 	if vs := r.Form[key]; len(vs) > 0 {
 		return vs[0]
@@ -598,6 +703,25 @@ func (r *Request) FormValue(key string) string {
 	return ""
 }
 
+// FormFile returns the first file for the provided form key.
+// FormFile calls ParseMultipartForm and ParseForm if necessary.
+func (r *Request) FormFile(key string) (multipart.File, *multipart.FileHeader, os.Error) {
+	if r.MultipartForm == multipartByReader {
+		return nil, nil, os.NewError("http: multipart handled by MultipartReader")
+	}
+	if r.MultipartForm == nil {
+		err := r.ParseMultipartForm(defaultMaxMemory)
+		if err != nil {
+			return nil, nil, err
+		}
+	}
+	if fhs := r.MultipartForm.File[key]; len(fhs) > 0 {
+		f, err := fhs[0].Open()
+		return f, fhs[0], err
+	}
+	return nil, nil, ErrMissingFile
+}
+
 func (r *Request) expectsContinue() bool {
 	return strings.ToLower(r.Header.Get("Expect")) == "100-continue"
 }
diff --git a/src/pkg/http/request_test.go b/src/pkg/http/request_test.go
index 19083ad..f982471 100644
--- a/src/pkg/http/request_test.go
+++ b/src/pkg/http/request_test.go
@@ -10,6 +10,8 @@ import (
 	. "http"
 	"http/httptest"
 	"io"
+	"io/ioutil"
+	"mime/multipart"
 	"os"
 	"reflect"
 	"regexp"
@@ -82,7 +84,7 @@ func TestPostQuery(t *testing.T) {
 	req.Header = Header{
 		"Content-Type": {"application/x-www-form-urlencoded; boo!"},
 	}
-	req.Body = nopCloser{strings.NewReader("z=post&both=y")}
+	req.Body = ioutil.NopCloser(strings.NewReader("z=post&both=y"))
 	if q := req.FormValue("q"); q != "foo" {
 		t.Errorf(`req.FormValue("q") = %q, want "foo"`, q)
 	}
@@ -115,7 +117,7 @@ func TestPostContentTypeParsing(t *testing.T) {
 		req := &Request{
 			Method: "POST",
 			Header: Header(test.contentType),
-			Body:   nopCloser{bytes.NewBufferString("body")},
+			Body:   ioutil.NopCloser(bytes.NewBufferString("body")),
 		}
 		err := req.ParseForm()
 		if !test.error && err != nil {
@@ -131,7 +133,7 @@ func TestMultipartReader(t *testing.T) {
 	req := &Request{
 		Method: "POST",
 		Header: Header{"Content-Type": {`multipart/form-data; boundary="foo123"`}},
-		Body:   nopCloser{new(bytes.Buffer)},
+		Body:   ioutil.NopCloser(new(bytes.Buffer)),
 	}
 	multipart, err := req.MultipartReader()
 	if multipart == nil {
@@ -170,9 +172,115 @@ func TestRedirect(t *testing.T) {
 	}
 }
 
-// TODO: stop copy/pasting this around.  move to io/ioutil?
-type nopCloser struct {
-	io.Reader
+func TestMultipartRequest(t *testing.T) {
+	// Test that we can read the values and files of a 
+	// multipart request with FormValue and FormFile,
+	// and that ParseMultipartForm can be called multiple times.
+	req := newTestMultipartRequest(t)
+	if err := req.ParseMultipartForm(25); err != nil {
+		t.Fatal("ParseMultipartForm first call:", err)
+	}
+	defer req.MultipartForm.RemoveAll()
+	validateTestMultipartContents(t, req, false)
+	if err := req.ParseMultipartForm(25); err != nil {
+		t.Fatal("ParseMultipartForm second call:", err)
+	}
+	validateTestMultipartContents(t, req, false)
+}
+
+func TestMultipartRequestAuto(t *testing.T) {
+	// Test that FormValue and FormFile automatically invoke
+	// ParseMultipartForm and return the right values.
+	req := newTestMultipartRequest(t)
+	defer func() {
+		if req.MultipartForm != nil {
+			req.MultipartForm.RemoveAll()
+		}
+	}()
+	validateTestMultipartContents(t, req, true)
+}
+
+func newTestMultipartRequest(t *testing.T) *Request {
+	b := bytes.NewBufferString(strings.Replace(message, "\n", "\r\n", -1))
+	req, err := NewRequest("POST", "/", b)
+	if err != nil {
+		t.Fatalf("NewRequest:", err)
+	}
+	ctype := fmt.Sprintf(`multipart/form-data; boundary="%s"`, boundary)
+	req.Header.Set("Content-type", ctype)
+	return req
+}
+
+func validateTestMultipartContents(t *testing.T, req *Request, allMem bool) {
+	if g, e := req.FormValue("texta"), textaValue; g != e {
+		t.Errorf("texta value = %q, want %q", g, e)
+	}
+	if g, e := req.FormValue("texta"), textaValue; g != e {
+		t.Errorf("texta value = %q, want %q", g, e)
+	}
+
+	assertMem := func(n string, fd multipart.File) {
+		if _, ok := fd.(*os.File); ok {
+			t.Error(n, " is *os.File, should not be")
+		}
+	}
+	fd := testMultipartFile(t, req, "filea", "filea.txt", fileaContents)
+	assertMem("filea", fd)
+	fd = testMultipartFile(t, req, "fileb", "fileb.txt", filebContents)
+	if allMem {
+		assertMem("fileb", fd)
+	} else {
+		if _, ok := fd.(*os.File); !ok {
+			t.Errorf("fileb has unexpected underlying type %T", fd)
+		}
+	}
+}
+
+func testMultipartFile(t *testing.T, req *Request, key, expectFilename, expectContent string) multipart.File {
+	f, fh, err := req.FormFile(key)
+	if err != nil {
+		t.Fatalf("FormFile(%q):", key, err)
+	}
+	if fh.Filename != expectFilename {
+		t.Errorf("filename = %q, want %q", fh.Filename, expectFilename)
+	}
+	var b bytes.Buffer
+	_, err = io.Copy(&b, f)
+	if err != nil {
+		t.Fatal("copying contents:", err)
+	}
+	if g := b.String(); g != expectContent {
+		t.Errorf("contents = %q, want %q", g, expectContent)
+	}
+	return f
 }
 
-func (nopCloser) Close() os.Error { return nil }
+const (
+	fileaContents = "This is a test file."
+	filebContents = "Another test file."
+	textaValue    = "foo"
+	textbValue    = "bar"
+	boundary      = `MyBoundary`
+)
+
+const message = `
+--MyBoundary
+Content-Disposition: form-data; name="filea"; filename="filea.txt"
+Content-Type: text/plain
+
+` + fileaContents + `
+--MyBoundary
+Content-Disposition: form-data; name="fileb"; filename="fileb.txt"
+Content-Type: text/plain
+
+` + filebContents + `
+--MyBoundary
+Content-Disposition: form-data; name="texta"
+
+` + textaValue + `
+--MyBoundary
+Content-Disposition: form-data; name="textb"
+
+` + textbValue + `
+--MyBoundary--
+`
diff --git a/src/pkg/http/requestwrite_test.go b/src/pkg/http/requestwrite_test.go
index 726baa2..bb000c7 100644
--- a/src/pkg/http/requestwrite_test.go
+++ b/src/pkg/http/requestwrite_test.go
@@ -6,7 +6,10 @@ package http
 
 import (
 	"bytes"
+	"io"
 	"io/ioutil"
+	"os"
+	"strings"
 	"testing"
 )
 
@@ -133,6 +136,41 @@ var reqWriteTests = []reqWriteTest{
 			"Transfer-Encoding: chunked\r\n\r\n" +
 			"6\r\nabcdef\r\n0\r\n\r\n",
 	},
+
+	// HTTP/1.1 POST with Content-Length, no chunking
+	{
+		Request{
+			Method: "POST",
+			URL: &URL{
+				Scheme: "http",
+				Host:   "www.google.com",
+				Path:   "/search",
+			},
+			ProtoMajor:    1,
+			ProtoMinor:    1,
+			Header:        Header{},
+			Close:         true,
+			ContentLength: 6,
+		},
+
+		[]byte("abcdef"),
+
+		"POST /search HTTP/1.1\r\n" +
+			"Host: www.google.com\r\n" +
+			"User-Agent: Go http package\r\n" +
+			"Connection: close\r\n" +
+			"Content-Length: 6\r\n" +
+			"\r\n" +
+			"abcdef",
+
+		"POST http://www.google.com/search HTTP/1.1\r\n" +
+			"User-Agent: Go http package\r\n" +
+			"Connection: close\r\n" +
+			"Content-Length: 6\r\n" +
+			"\r\n" +
+			"abcdef",
+	},
+
 	// default to HTTP/1.1
 	{
 		Request{
@@ -189,3 +227,26 @@ func TestRequestWrite(t *testing.T) {
 		}
 	}
 }
+
+type closeChecker struct {
+	io.Reader
+	closed bool
+}
+
+func (rc *closeChecker) Close() os.Error {
+	rc.closed = true
+	return nil
+}
+
+// TestRequestWriteClosesBody tests that Request.Write does close its request.Body.
+// It also indirectly tests NewRequest and that it doesn't wrap an existing Closer
+// inside a NopCloser.
+func TestRequestWriteClosesBody(t *testing.T) {
+	rc := &closeChecker{Reader: strings.NewReader("my body")}
+	req, _ := NewRequest("GET", "http://foo.com/", rc)
+	buf := new(bytes.Buffer)
+	req.Write(buf)
+	if !rc.closed {
+		t.Error("body not closed after write")
+	}
+}
diff --git a/src/pkg/http/response_test.go b/src/pkg/http/response_test.go
index 314f05b..9e77c20 100644
--- a/src/pkg/http/response_test.go
+++ b/src/pkg/http/response_test.go
@@ -7,8 +7,12 @@ package http
 import (
 	"bufio"
 	"bytes"
+	"compress/gzip"
+	"crypto/rand"
 	"fmt"
+	"os"
 	"io"
+	"io/ioutil"
 	"reflect"
 	"testing"
 )
@@ -117,7 +121,9 @@ var respTests = []respTest{
 			"Transfer-Encoding: chunked\r\n" +
 			"\r\n" +
 			"0a\r\n" +
-			"Body here\n" +
+			"Body here\n\r\n" +
+			"09\r\n" +
+			"continued\r\n" +
 			"0\r\n" +
 			"\r\n",
 
@@ -134,7 +140,7 @@ var respTests = []respTest{
 			TransferEncoding: []string{"chunked"},
 		},
 
-		"Body here\n",
+		"Body here\ncontinued",
 	},
 
 	// Chunked response with Content-Length.
@@ -186,6 +192,29 @@ var respTests = []respTest{
 		"",
 	},
 
+	// explicit Content-Length of 0.
+	{
+		"HTTP/1.1 200 OK\r\n" +
+			"Content-Length: 0\r\n" +
+			"\r\n",
+
+		Response{
+			Status:        "200 OK",
+			StatusCode:    200,
+			Proto:         "HTTP/1.1",
+			ProtoMajor:    1,
+			ProtoMinor:    1,
+			RequestMethod: "GET",
+			Header: Header{
+				"Content-Length": {"0"},
+			},
+			Close:         false,
+			ContentLength: 0,
+		},
+
+		"",
+	},
+
 	// Status line without a Reason-Phrase, but trailing space.
 	// (permitted by RFC 2616)
 	{
@@ -250,9 +279,107 @@ func TestReadResponse(t *testing.T) {
 	}
 }
 
+var readResponseCloseInMiddleTests = []struct {
+	chunked, compressed bool
+}{
+	{false, false},
+	{true, false},
+	{true, true},
+}
+
+// TestReadResponseCloseInMiddle tests that closing a body after
+// reading only part of its contents advances the read to the end of
+// the request, right up until the next request.
+func TestReadResponseCloseInMiddle(t *testing.T) {
+	for _, test := range readResponseCloseInMiddleTests {
+		fatalf := func(format string, args ...interface{}) {
+			args = append([]interface{}{test.chunked, test.compressed}, args...)
+			t.Fatalf("on test chunked=%v, compressed=%v: "+format, args...)
+		}
+		checkErr := func(err os.Error, msg string) {
+			if err == nil {
+				return
+			}
+			fatalf(msg+": %v", err)
+		}
+		var buf bytes.Buffer
+		buf.WriteString("HTTP/1.1 200 OK\r\n")
+		if test.chunked {
+			buf.WriteString("Transfer-Encoding: chunked\r\n")
+		} else {
+			buf.WriteString("Content-Length: 1000000\r\n")
+		}
+		var wr io.Writer = &buf
+		if test.chunked {
+			wr = &chunkedWriter{wr}
+		}
+		if test.compressed {
+			buf.WriteString("Content-Encoding: gzip\r\n")
+			var err os.Error
+			wr, err = gzip.NewWriter(wr)
+			checkErr(err, "gzip.NewWriter")
+		}
+		buf.WriteString("\r\n")
+
+		chunk := bytes.Repeat([]byte{'x'}, 1000)
+		for i := 0; i < 1000; i++ {
+			if test.compressed {
+				// Otherwise this compresses too well.
+				_, err := io.ReadFull(rand.Reader, chunk)
+				checkErr(err, "rand.Reader ReadFull")
+			}
+			wr.Write(chunk)
+		}
+		if test.compressed {
+			err := wr.(*gzip.Compressor).Close()
+			checkErr(err, "compressor close")
+		}
+		if test.chunked {
+			buf.WriteString("0\r\n\r\n")
+		}
+		buf.WriteString("Next Request Here")
+
+		bufr := bufio.NewReader(&buf)
+		resp, err := ReadResponse(bufr, "GET")
+		checkErr(err, "ReadResponse")
+		expectedLength := int64(-1)
+		if !test.chunked {
+			expectedLength = 1000000
+		}
+		if resp.ContentLength != expectedLength {
+			fatalf("expected response length %d, got %d", expectedLength, resp.ContentLength)
+		}
+		if resp.Body == nil {
+			fatalf("nil body")
+		}
+		if test.compressed {
+			gzReader, err := gzip.NewReader(resp.Body)
+			checkErr(err, "gzip.NewReader")
+			resp.Body = &readFirstCloseBoth{gzReader, resp.Body}
+		}
+
+		rbuf := make([]byte, 2500)
+		n, err := io.ReadFull(resp.Body, rbuf)
+		checkErr(err, "2500 byte ReadFull")
+		if n != 2500 {
+			fatalf("ReadFull only read %d bytes", n)
+		}
+		if test.compressed == false && !bytes.Equal(bytes.Repeat([]byte{'x'}, 2500), rbuf) {
+			fatalf("ReadFull didn't read 2500 'x'; got %q", string(rbuf))
+		}
+		resp.Body.Close()
+
+		rest, err := ioutil.ReadAll(bufr)
+		checkErr(err, "ReadAll on remainder")
+		if e, g := "Next Request Here", string(rest); e != g {
+			fatalf("for chunked=%v remainder = %q, expected %q", g, e)
+		}
+	}
+}
+
 func diff(t *testing.T, prefix string, have, want interface{}) {
-	hv := reflect.NewValue(have).Elem()
-	wv := reflect.NewValue(want).Elem()
+	hv := reflect.ValueOf(have).Elem()
+	wv := reflect.ValueOf(want).Elem()
 	if hv.Type() != wv.Type() {
 		t.Errorf("%s: type mismatch %v vs %v", prefix, hv.Type(), wv.Type())
 	}
diff --git a/src/pkg/http/reverseproxy.go b/src/pkg/http/reverseproxy.go
new file mode 100644
index 0000000..e4ce1e3
--- /dev/null
+++ b/src/pkg/http/reverseproxy.go
@@ -0,0 +1,100 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// HTTP reverse proxy handler
+
+package http
+
+import (
+	"io"
+	"log"
+	"net"
+	"strings"
+)
+
+// ReverseProxy is an HTTP Handler that takes an incoming request and
+// sends it to another server, proxying the response back to the
+// client.
+type ReverseProxy struct {
+	// Director must be a function which modifies
+	// the request into a new request to be sent
+	// using Transport. Its response is then copied
+	// back to the original client unmodified.
+	Director func(*Request)
+
+	// The Transport used to perform proxy requests.
+	// If nil, DefaultTransport is used.
+	Transport RoundTripper
+}
+
+func singleJoiningSlash(a, b string) string {
+	aslash := strings.HasSuffix(a, "/")
+	bslash := strings.HasPrefix(b, "/")
+	switch {
+	case aslash && bslash:
+		return a + b[1:]
+	case !aslash && !bslash:
+		return a + "/" + b
+	}
+	return a + b
+}
+
+// NewSingleHostReverseProxy returns a new ReverseProxy that rewrites
+// URLs to the scheme, host, and base path provided in target. If the
+// target's path is "/base" and the incoming request was for "/dir",
+// the target request will be for /base/dir.
+func NewSingleHostReverseProxy(target *URL) *ReverseProxy {
+	director := func(req *Request) {
+		req.URL.Scheme = target.Scheme
+		req.URL.Host = target.Host
+		req.URL.Path = singleJoiningSlash(target.Path, req.URL.Path)
+		if q := req.URL.RawQuery; q != "" {
+			req.URL.RawPath = req.URL.Path + "?" + q
+		} else {
+			req.URL.RawPath = req.URL.Path
+		}
+		req.URL.RawQuery = target.RawQuery
+	}
+	return &ReverseProxy{Director: director}
+}
+
+func (p *ReverseProxy) ServeHTTP(rw ResponseWriter, req *Request) {
+	transport := p.Transport
+	if transport == nil {
+		transport = DefaultTransport
+	}
+
+	outreq := new(Request)
+	*outreq = *req // includes shallow copies of maps, but okay
+
+	p.Director(outreq)
+	outreq.Proto = "HTTP/1.1"
+	outreq.ProtoMajor = 1
+	outreq.ProtoMinor = 1
+	outreq.Close = false
+
+	if clientIp, _, err := net.SplitHostPort(req.RemoteAddr); err == nil {
+		outreq.Header.Set("X-Forwarded-For", clientIp)
+	}
+
+	res, err := transport.RoundTrip(outreq)
+	if err != nil {
+		log.Printf("http: proxy error: %v", err)
+		rw.WriteHeader(StatusInternalServerError)
+		return
+	}
+
+	hdr := rw.Header()
+	for k, vv := range res.Header {
+		for _, v := range vv {
+			hdr.Add(k, v)
+		}
+	}
+
+	rw.WriteHeader(res.StatusCode)
+
+	if res.Body != nil {
+		io.Copy(rw, res.Body)
+	}
+}
diff --git a/src/pkg/http/reverseproxy_test.go b/src/pkg/http/reverseproxy_test.go
new file mode 100644
index 0000000..8cf7705
--- /dev/null
+++ b/src/pkg/http/reverseproxy_test.go
@@ -0,0 +1,50 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Reverse proxy tests.
+
+package http_test
+
+import (
+	. "http"
+	"http/httptest"
+	"io/ioutil"
+	"testing"
+)
+
+func TestReverseProxy(t *testing.T) {
+	const backendResponse = "I am the backend"
+	const backendStatus = 404
+	backend := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		if r.Header.Get("X-Forwarded-For") == "" {
+			t.Errorf("didn't get X-Forwarded-For header")
+		}
+		w.Header().Set("X-Foo", "bar")
+		w.WriteHeader(backendStatus)
+		w.Write([]byte(backendResponse))
+	}))
+	defer backend.Close()
+	backendURL, err := ParseURL(backend.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	proxyHandler := NewSingleHostReverseProxy(backendURL)
+	frontend := httptest.NewServer(proxyHandler)
+	defer frontend.Close()
+
+	res, _, err := Get(frontend.URL)
+	if err != nil {
+		t.Fatalf("Get: %v", err)
+	}
+	if g, e := res.StatusCode, backendStatus; g != e {
+		t.Errorf("got res.StatusCode %d; expected %d", g, e)
+	}
+	if g, e := res.Header.Get("X-Foo"), "bar"; g != e {
+		t.Errorf("got X-Foo %q; expected %q", g, e)
+	}
+	bodyBytes, _ := ioutil.ReadAll(res.Body)
+	if g, e := string(bodyBytes), backendResponse; g != e {
+		t.Errorf("got body %q; expected %q", g, e)
+	}
+}
diff --git a/src/pkg/http/serve_test.go b/src/pkg/http/serve_test.go
index 0142dea..c3c7b8d 100644
--- a/src/pkg/http/serve_test.go
+++ b/src/pkg/http/serve_test.go
@@ -247,7 +247,7 @@ func TestServerTimeouts(t *testing.T) {
 	server := &Server{Handler: handler, ReadTimeout: 0.25 * second, WriteTimeout: 0.25 * second}
 	go server.Serve(l)
 
-	url := fmt.Sprintf("http://localhost:%d/", addr.Port)
+	url := fmt.Sprintf("http://%s/", addr)
 
 	// Hit the HTTP server successfully.
 	tr := &Transport{DisableKeepAlives: true} // they interfere with this test
@@ -265,7 +265,7 @@ func TestServerTimeouts(t *testing.T) {
 
 	// Slow client that should timeout.
 	t1 := time.Nanoseconds()
-	conn, err := net.Dial("tcp", fmt.Sprintf("localhost:%d", addr.Port))
+	conn, err := net.Dial("tcp", addr.String())
 	if err != nil {
 		t.Fatalf("Dial: %v", err)
 	}
@@ -588,7 +588,7 @@ func TestServerExpect(t *testing.T) {
 		sendf := func(format string, args ...interface{}) {
 			_, err := fmt.Fprintf(conn, format, args...)
 			if err != nil {
-				t.Fatalf("Error writing %q: %v", format, err)
+				t.Fatalf("On test %#v, error writing %q: %v", test, format, err)
 			}
 		}
 		go func() {
@@ -616,3 +616,100 @@ func TestServerExpect(t *testing.T) {
 		runTest(test)
 	}
 }
+
+func TestServerConsumesRequestBody(t *testing.T) {
+	log := make(chan string, 100)
+
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		log <- "got_request"
+		w.WriteHeader(StatusOK)
+		log <- "wrote_header"
+	}))
+	defer ts.Close()
+
+	conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+	if err != nil {
+		t.Fatalf("Dial: %v", err)
+	}
+	defer conn.Close()
+
+	bufr := bufio.NewReader(conn)
+	gotres := make(chan bool)
+	go func() {
+		line, err := bufr.ReadString('\n')
+		if err != nil {
+			t.Fatal(err)
+		}
+		log <- line
+		gotres <- true
+	}()
+
+	size := 1 << 20
+	log <- "writing_request"
+	fmt.Fprintf(conn, "POST / HTTP/1.0\r\nContent-Length: %d\r\n\r\n", size)
+	time.Sleep(25e6) // give server chance to misbehave & speak out of turn
+	log <- "slept_after_req_headers"
+	conn.Write([]byte(strings.Repeat("a", size)))
+
+	<-gotres
+	expected := []string{
+		"writing_request", "got_request",
+		"slept_after_req_headers", "wrote_header",
+		"HTTP/1.0 200 OK\r\n"}
+	for step, e := range expected {
+		if g := <-log; e != g {
+			t.Errorf("on step %d expected %q, got %q", step, e, g)
+		}
+	}
+}
+
+func TestTimeoutHandler(t *testing.T) {
+	sendHi := make(chan bool, 1)
+	writeErrors := make(chan os.Error, 1)
+	sayHi := HandlerFunc(func(w ResponseWriter, r *Request) {
+		<-sendHi
+		_, werr := w.Write([]byte("hi"))
+		writeErrors <- werr
+	})
+	timeout := make(chan int64, 1) // write to this to force timeouts
+	ts := httptest.NewServer(NewTestTimeoutHandler(sayHi, timeout))
+	defer ts.Close()
+
+	// Succeed without timing out:
+	sendHi <- true
+	res, _, err := Get(ts.URL)
+	if err != nil {
+		t.Error(err)
+	}
+	if g, e := res.StatusCode, StatusOK; g != e {
+		t.Errorf("got res.StatusCode %d; expected %d", g, e)
+	}
+	body, _ := ioutil.ReadAll(res.Body)
+	if g, e := string(body), "hi"; g != e {
+		t.Errorf("got body %q; expected %q", g, e)
+	}
+	if g := <-writeErrors; g != nil {
+		t.Errorf("got unexpected Write error on first request: %v", g)
+	}
+
+	// Times out:
+	timeout <- 1
+	res, _, err = Get(ts.URL)
+	if err != nil {
+		t.Error(err)
+	}
+	if g, e := res.StatusCode, StatusServiceUnavailable; g != e {
+		t.Errorf("got res.StatusCode %d; expected %d", g, e)
+	}
+	body, _ = ioutil.ReadAll(res.Body)
+	if !strings.Contains(string(body), "<title>Timeout</title>") {
+		t.Errorf("expected timeout body; got %q", string(body))
+	}
+
+	// Now make the previously-timed out handler speak again,
+	// which verifies the panic is handled:
+	sendHi <- true
+	if g, e := <-writeErrors, ErrHandlerTimeout; g != e {
+		t.Errorf("expected Write error of %v; got %v", e, g)
+	}
+}
diff --git a/src/pkg/http/server.go b/src/pkg/http/server.go
index 3291de1..96d2cb6 100644
--- a/src/pkg/http/server.go
+++ b/src/pkg/http/server.go
@@ -22,6 +22,7 @@ import (
 	"path"
 	"strconv"
 	"strings"
+	"sync"
 	"time"
 )
 
@@ -141,9 +142,13 @@ func newConn(rwc net.Conn, handler Handler) (c *conn, err os.Error) {
 type expectContinueReader struct {
 	resp       *response
 	readCloser io.ReadCloser
+	closed     bool
 }
 
 func (ecr *expectContinueReader) Read(p []byte) (n int, err os.Error) {
+	if ecr.closed {
+		return 0, os.NewError("http: Read after Close on request Body")
+	}
 	if !ecr.resp.wroteContinue && !ecr.resp.conn.hijacked {
 		ecr.resp.wroteContinue = true
 		io.WriteString(ecr.resp.conn.buf, "HTTP/1.1 100 Continue\r\n\r\n")
@@ -153,6 +158,7 @@ func (ecr *expectContinueReader) Read(p []byte) (n int, err os.Error) {
 }
 
 func (ecr *expectContinueReader) Close() os.Error {
+	ecr.closed = true
 	return ecr.readCloser.Close()
 }
 
@@ -196,6 +202,16 @@ func (w *response) WriteHeader(code int) {
 		log.Print("http: multiple response.WriteHeader calls")
 		return
 	}
+
+	// Per RFC 2616, we should consume the request body before
+	// replying, if the handler hasn't already done so.
+	if w.req.ContentLength != 0 {
+		ecr, isExpecter := w.req.Body.(*expectContinueReader)
+		if !isExpecter || ecr.resp.wroteContinue {
+			w.req.Body.Close()
+		}
+	}
+
 	w.wroteHeader = true
 	w.status = code
 	if code == StatusNotModified {
@@ -407,6 +423,9 @@ func (w *response) finishRequest() {
 	}
 	w.conn.buf.Flush()
 	w.req.Body.Close()
+	if w.req.MultipartForm != nil {
+		w.req.MultipartForm.RemoveAll()
+	}
 
 	if w.contentLength != -1 && w.contentLength != w.written {
 		// Did not write enough. Avoid getting out of sync.
@@ -883,3 +902,89 @@ func ListenAndServeTLS(addr string, certFile string, keyFile string, handler Han
 	tlsListener := tls.NewListener(conn, config)
 	return Serve(tlsListener, handler)
 }
+
+// TimeoutHandler returns a Handler that runs h with the given time limit.
+//
+// The new Handler calls h.ServeHTTP to handle each request, but if a
+// call runs for more than ns nanoseconds, the handler responds with
+// a 503 Service Unavailable error and the given message in its body.
+// (If msg is empty, a suitable default message will be sent.)
+// After such a timeout, writes by h to its ResponseWriter will return
+// ErrHandlerTimeout.
+func TimeoutHandler(h Handler, ns int64, msg string) Handler {
+	f := func() <-chan int64 {
+		return time.After(ns)
+	}
+	return &timeoutHandler{h, f, msg}
+}
+
+// ErrHandlerTimeout is returned on ResponseWriter Write calls
+// in handlers which have timed out.
+var ErrHandlerTimeout = os.NewError("http: Handler timeout")
+
+type timeoutHandler struct {
+	handler Handler
+	timeout func() <-chan int64 // returns channel producing a timeout
+	body    string
+}
+
+func (h *timeoutHandler) errorBody() string {
+	if h.body != "" {
+		return h.body
+	}
+	return "<html><head><title>Timeout</title></head><body><h1>Timeout</h1></body></html>"
+}
+
+func (h *timeoutHandler) ServeHTTP(w ResponseWriter, r *Request) {
+	done := make(chan bool)
+	tw := &timeoutWriter{w: w}
+	go func() {
+		h.handler.ServeHTTP(tw, r)
+		done <- true
+	}()
+	select {
+	case <-done:
+		return
+	case <-h.timeout():
+		tw.mu.Lock()
+		defer tw.mu.Unlock()
+		if !tw.wroteHeader {
+			tw.w.WriteHeader(StatusServiceUnavailable)
+			tw.w.Write([]byte(h.errorBody()))
+		}
+		tw.timedOut = true
+	}
+}
+
+type timeoutWriter struct {
+	w ResponseWriter
+
+	mu          sync.Mutex
+	timedOut    bool
+	wroteHeader bool
+}
+
+func (tw *timeoutWriter) Header() Header {
+	return tw.w.Header()
+}
+
+func (tw *timeoutWriter) Write(p []byte) (int, os.Error) {
+	tw.mu.Lock()
+	timedOut := tw.timedOut
+	tw.mu.Unlock()
+	if timedOut {
+		return 0, ErrHandlerTimeout
+	}
+	return tw.w.Write(p)
+}
+
+func (tw *timeoutWriter) WriteHeader(code int) {
+	tw.mu.Lock()
+	if tw.timedOut || tw.wroteHeader {
+		tw.mu.Unlock()
+		return
+	}
+	tw.wroteHeader = true
+	tw.mu.Unlock()
+	tw.w.WriteHeader(code)
+}
diff --git a/src/pkg/http/transfer.go b/src/pkg/http/transfer.go
index 41614f1..98c32ba 100644
--- a/src/pkg/http/transfer.go
+++ b/src/pkg/http/transfer.go
@@ -7,6 +7,7 @@ package http
 import (
 	"bufio"
 	"io"
+	"io/ioutil"
 	"os"
 	"strconv"
 	"strings"
@@ -447,17 +448,10 @@ func (b *body) Close() os.Error {
 		return nil
 	}
 
-	trashBuf := make([]byte, 1024) // local for thread safety
-	for {
-		_, err := b.Read(trashBuf)
-		if err == nil {
-			continue
-		}
-		if err == os.EOF {
-			break
-		}
+	if _, err := io.Copy(ioutil.Discard, b); err != nil {
 		return err
 	}
+
 	if b.hdr == nil { // not reading trailer
 		return nil
 	}
diff --git a/src/pkg/http/transport.go b/src/pkg/http/transport.go
index 7fa37af..73a2c21 100644
--- a/src/pkg/http/transport.go
+++ b/src/pkg/http/transport.go
@@ -6,6 +6,7 @@ package http
 
 import (
 	"bufio"
+	"bytes"
 	"compress/gzip"
 	"crypto/tls"
 	"encoding/base64"
@@ -217,6 +218,9 @@ func (t *Transport) getConn(cm *connectMethod) (*persistConn, os.Error) {
 
 	conn, err := net.Dial("tcp", cm.addr())
 	if err != nil {
+		if cm.proxyURL != nil {
+			err = fmt.Errorf("http: error connecting to proxy %s: %v", cm.proxyURL, err)
+		}
 		return nil, err
 	}
 
@@ -288,10 +292,28 @@ func (t *Transport) getConn(cm *connectMethod) (*persistConn, os.Error) {
 
 // useProxy returns true if requests to addr should use a proxy,
 // according to the NO_PROXY or no_proxy environment variable.
+// addr is always a canonicalAddr with a host and port.
 func (t *Transport) useProxy(addr string) bool {
 	if len(addr) == 0 {
 		return true
 	}
+	host, _, err := net.SplitHostPort(addr)
+	if err != nil {
+		return false
+	}
+	if host == "localhost" {
+		return false
+	}
+	if ip := net.ParseIP(host); ip != nil {
+		if ip4 := ip.To4(); ip4 != nil && ip4[0] == 127 {
+			// 127.0.0.0/8 loopback isn't proxied.
+			return false
+		}
+		if bytes.Equal(ip, net.IPv6loopback) {
+			return false
+		}
+	}
+
 	no_proxy := t.getenvEitherCase("NO_PROXY")
 	if no_proxy == "*" {
 		return false
@@ -510,12 +532,13 @@ func (pc *persistConn) roundTrip(req *Request) (resp *Response, err os.Error) {
 		re.res.Header.Del("Content-Encoding")
 		re.res.Header.Del("Content-Length")
 		re.res.ContentLength = -1
-		var err os.Error
-		re.res.Body, err = gzip.NewReader(re.res.Body)
+		esb := re.res.Body.(*bodyEOFSignal)
+		gzReader, err := gzip.NewReader(esb.body)
 		if err != nil {
 			pc.close()
 			return nil, err
 		}
+		esb.body = &readFirstCloseBoth{gzReader, esb.body}
 	}
 
 	return re.res, re.err
@@ -554,7 +577,7 @@ func responseIsKeepAlive(res *Response) bool {
 func readResponseWithEOFSignal(r *bufio.Reader, requestMethod string) (resp *Response, err os.Error) {
 	resp, err = ReadResponse(r, requestMethod)
 	if err == nil && resp.ContentLength != 0 {
-		resp.Body = &bodyEOFSignal{resp.Body, nil}
+		resp.Body = &bodyEOFSignal{body: resp.Body}
 	}
 	return
 }
@@ -563,12 +586,16 @@ func readResponseWithEOFSignal(r *bufio.Reader, requestMethod string) (resp *Res
 // once, right before the final Read() or Close() call returns, but after
 // EOF has been seen.
 type bodyEOFSignal struct {
-	body io.ReadCloser
-	fn   func()
+	body     io.ReadCloser
+	fn       func()
+	isClosed bool
 }
 
 func (es *bodyEOFSignal) Read(p []byte) (n int, err os.Error) {
 	n, err = es.body.Read(p)
+	if es.isClosed && n > 0 {
+		panic("http: unexpected bodyEOFSignal Read after Close; see issue 1725")
+	}
 	if err == os.EOF && es.fn != nil {
 		es.fn()
 		es.fn = nil
@@ -577,6 +604,7 @@ func (es *bodyEOFSignal) Read(p []byte) (n int, err os.Error) {
 }
 
 func (es *bodyEOFSignal) Close() (err os.Error) {
+	es.isClosed = true
 	err = es.body.Close()
 	if err == nil && es.fn != nil {
 		es.fn()
@@ -584,3 +612,19 @@ func (es *bodyEOFSignal) Close() (err os.Error) {
 	}
 	return
 }
+
+type readFirstCloseBoth struct {
+	io.ReadCloser
+	io.Closer
+}
+
+func (r *readFirstCloseBoth) Close() os.Error {
+	if err := r.ReadCloser.Close(); err != nil {
+		r.Closer.Close()
+		return err
+	}
+	if err := r.Closer.Close(); err != nil {
+		return err
+	}
+	return nil
+}
diff --git a/src/pkg/http/transport_test.go b/src/pkg/http/transport_test.go
index f83deed..a32ac4c 100644
--- a/src/pkg/http/transport_test.go
+++ b/src/pkg/http/transport_test.go
@@ -9,11 +9,14 @@ package http_test
 import (
 	"bytes"
 	"compress/gzip"
+	"crypto/rand"
 	"fmt"
 	. "http"
 	"http/httptest"
+	"io"
 	"io/ioutil"
 	"os"
+	"strconv"
 	"testing"
 	"time"
 )
@@ -179,35 +182,47 @@ func TestTransportIdleCacheKeys(t *testing.T) {
 }
 
 func TestTransportMaxPerHostIdleConns(t *testing.T) {
-	ch := make(chan string)
+	resch := make(chan string)
+	gotReq := make(chan bool)
 	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		w.Write([]byte(<-ch))
+		gotReq <- true
+		msg := <-resch
+		_, err := w.Write([]byte(msg))
+		if err != nil {
+			t.Fatalf("Write: %v", err)
+		}
 	}))
 	defer ts.Close()
 	maxIdleConns := 2
 	tr := &Transport{DisableKeepAlives: false, MaxIdleConnsPerHost: maxIdleConns}
 	c := &Client{Transport: tr}
 
-	// Start 3 outstanding requests (will hang until we write to
-	// ch)
+	// Start 3 outstanding requests and wait for the server to get them.
+	// Their responses will hang until we we write to resch, though.
 	donech := make(chan bool)
 	doReq := func() {
 		resp, _, err := c.Get(ts.URL)
 		if err != nil {
 			t.Error(err)
 		}
-		ioutil.ReadAll(resp.Body)
+		_, err = ioutil.ReadAll(resp.Body)
+		if err != nil {
+			t.Fatalf("ReadAll: %v", err)
+		}
 		donech <- true
 	}
 	go doReq()
+	<-gotReq
 	go doReq()
+	<-gotReq
 	go doReq()
+	<-gotReq
 
 	if e, g := 0, len(tr.IdleConnKeysForTesting()); e != g {
 		t.Fatalf("Before writes, expected %d idle conn cache keys; got %d", e, g)
 	}
 
-	ch <- "res1"
+	resch <- "res1"
 	<-donech
 	keys := tr.IdleConnKeysForTesting()
 	if e, g := 1, len(keys); e != g {
@@ -221,13 +236,13 @@ func TestTransportMaxPerHostIdleConns(t *testing.T) {
 		t.Errorf("after first response, expected %d idle conns; got %d", e, g)
 	}
 
-	ch <- "res2"
+	resch <- "res2"
 	<-donech
 	if e, g := 2, tr.IdleConnCountForTesting(cacheKey); e != g {
 		t.Errorf("after second response, expected %d idle conns; got %d", e, g)
 	}
 
-	ch <- "res3"
+	resch <- "res3"
 	<-donech
 	if e, g := maxIdleConns, tr.IdleConnCountForTesting(cacheKey); e != g {
 		t.Errorf("after third response, still expected %d idle conns; got %d", e, g)
@@ -355,32 +370,80 @@ func TestTransportNilURL(t *testing.T) {
 
 func TestTransportGzip(t *testing.T) {
 	const testString = "The test string aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		if g, e := r.Header.Get("Accept-Encoding"), "gzip"; g != e {
+	const nRandBytes = 1024 * 1024
+	ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
+		if g, e := req.Header.Get("Accept-Encoding"), "gzip"; g != e {
 			t.Errorf("Accept-Encoding = %q, want %q", g, e)
 		}
-		w.Header().Set("Content-Encoding", "gzip")
+		rw.Header().Set("Content-Encoding", "gzip")
+
+		var w io.Writer = rw
+		var buf bytes.Buffer
+		if req.FormValue("chunked") == "0" {
+			w = &buf
+			defer io.Copy(rw, &buf)
+			defer func() {
+				rw.Header().Set("Content-Length", strconv.Itoa(buf.Len()))
+			}()
+		}
 		gz, _ := gzip.NewWriter(w)
-		defer gz.Close()
 		gz.Write([]byte(testString))
-
+		if req.FormValue("body") == "large" {
+			io.Copyn(gz, rand.Reader, nRandBytes)
+		}
+		gz.Close()
 	}))
 	defer ts.Close()
 
-	c := &Client{Transport: &Transport{}}
-	res, _, err := c.Get(ts.URL)
-	if err != nil {
-		t.Fatal(err)
-	}
-	body, err := ioutil.ReadAll(res.Body)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if g, e := string(body), testString; g != e {
-		t.Fatalf("body = %q; want %q", g, e)
-	}
-	if g, e := res.Header.Get("Content-Encoding"), ""; g != e {
-		t.Fatalf("Content-Encoding = %q; want %q", g, e)
+	for _, chunked := range []string{"1", "0"} {
+		c := &Client{Transport: &Transport{}}
+
+		// First fetch something large, but only read some of it.
+		res, _, err := c.Get(ts.URL + "?body=large&chunked=" + chunked)
+		if err != nil {
+			t.Fatalf("large get: %v", err)
+		}
+		buf := make([]byte, len(testString))
+		n, err := io.ReadFull(res.Body, buf)
+		if err != nil {
+			t.Fatalf("partial read of large response: size=%d, %v", n, err)
+		}
+		if e, g := testString, string(buf); e != g {
+			t.Errorf("partial read got %q, expected %q", g, e)
+		}
+		res.Body.Close()
+		// Read on the body, even though it's closed
+		n, err = res.Body.Read(buf)
+		if n != 0 || err == nil {
+			t.Errorf("expected error post-closed large Read; got = %d, %v", n, err)
+		}
+
+		// Then something small.
+		res, _, err = c.Get(ts.URL + "?chunked=" + chunked)
+		if err != nil {
+			t.Fatal(err)
+		}
+		body, err := ioutil.ReadAll(res.Body)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if g, e := string(body), testString; g != e {
+			t.Fatalf("body = %q; want %q", g, e)
+		}
+		if g, e := res.Header.Get("Content-Encoding"), ""; g != e {
+			t.Fatalf("Content-Encoding = %q; want %q", g, e)
+		}
+
+		// Read on the body after it's been fully read:
+		n, err = res.Body.Read(buf)
+		if n != 0 || err == nil {
+			t.Errorf("expected Read error after exhausted reads; got %d, %v", n, err)
+		}
+		res.Body.Close()
+		n, err = res.Body.Read(buf)
+		if n != 0 || err == nil {
+			t.Errorf("expected Read error after Close; got %d, %v", n, err)
+		}
 	}
 }
 
diff --git a/src/pkg/image/image.go b/src/pkg/image/image.go
index c0e96e1..5f398a3 100644
--- a/src/pkg/image/image.go
+++ b/src/pkg/image/image.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The image package implements a basic 2-D image library.
+// Package image implements a basic 2-D image library.
 package image
 
 // A Config consists of an image's color model and dimensions.
diff --git a/src/pkg/image/jpeg/Makefile b/src/pkg/image/jpeg/Makefile
index 5c5f97e..d9d830f 100644
--- a/src/pkg/image/jpeg/Makefile
+++ b/src/pkg/image/jpeg/Makefile
@@ -6,8 +6,10 @@ include ../../../Make.inc
 
 TARG=image/jpeg
 GOFILES=\
+	fdct.go\
 	huffman.go\
 	idct.go\
 	reader.go\
+	writer.go\
 
 include ../../../Make.pkg
diff --git a/src/pkg/image/jpeg/fdct.go b/src/pkg/image/jpeg/fdct.go
new file mode 100644
index 0000000..3f8be4e
--- /dev/null
+++ b/src/pkg/image/jpeg/fdct.go
@@ -0,0 +1,190 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package jpeg
+
+// This file implements a Forward Discrete Cosine Transformation.
+
+/*
+It is based on the code in jfdctint.c from the Independent JPEG Group,
+found at http://www.ijg.org/files/jpegsrc.v8c.tar.gz.
+
+The "LEGAL ISSUES" section of the README in that archive says:
+
+In plain English:
+
+1. We don't promise that this software works.  (But if you find any bugs,
+   please let us know!)
+2. You can use this software for whatever you want.  You don't have to pay us.
+3. You may not pretend that you wrote this software.  If you use it in a
+   program, you must acknowledge somewhere in your documentation that
+   you've used the IJG code.
+
+In legalese:
+
+The authors make NO WARRANTY or representation, either express or implied,
+with respect to this software, its quality, accuracy, merchantability, or
+fitness for a particular purpose.  This software is provided "AS IS", and you,
+its user, assume the entire risk as to its quality and accuracy.
+
+This software is copyright (C) 1991-2011, Thomas G. Lane, Guido Vollbeding.
+All Rights Reserved except as specified below.
+
+Permission is hereby granted to use, copy, modify, and distribute this
+software (or portions thereof) for any purpose, without fee, subject to these
+conditions:
+(1) If any part of the source code for this software is distributed, then this
+README file must be included, with this copyright and no-warranty notice
+unaltered; and any additions, deletions, or changes to the original files
+must be clearly indicated in accompanying documentation.
+(2) If only executable code is distributed, then the accompanying
+documentation must state that "this software is based in part on the work of
+the Independent JPEG Group".
+(3) Permission for use of this software is granted only if the user accepts
+full responsibility for any undesirable consequences; the authors accept
+NO LIABILITY for damages of any kind.
+
+These conditions apply to any software derived from or based on the IJG code,
+not just to the unmodified library.  If you use our work, you ought to
+acknowledge us.
+
+Permission is NOT granted for the use of any IJG author's name or company name
+in advertising or publicity relating to this software or products derived from
+it.  This software may be referred to only as "the Independent JPEG Group's
+software".
+
+We specifically permit and encourage the use of this software as the basis of
+commercial products, provided that all warranty or liability claims are
+assumed by the product vendor.
+*/
+
+// Trigonometric constants in 13-bit fixed point format.
+const (
+	fix_0_298631336 = 2446
+	fix_0_390180644 = 3196
+	fix_0_541196100 = 4433
+	fix_0_765366865 = 6270
+	fix_0_899976223 = 7373
+	fix_1_175875602 = 9633
+	fix_1_501321110 = 12299
+	fix_1_847759065 = 15137
+	fix_1_961570560 = 16069
+	fix_2_053119869 = 16819
+	fix_2_562915447 = 20995
+	fix_3_072711026 = 25172
+)
+
+const (
+	constBits     = 13
+	pass1Bits     = 2
+	centerJSample = 128
+)
+
+// fdct performs a forward DCT on an 8x8 block of coefficients, including a
+// level shift.
+func fdct(b *block) {
+	// Pass 1: process rows.
+	for y := 0; y < 8; y++ {
+		x0 := b[y*8+0]
+		x1 := b[y*8+1]
+		x2 := b[y*8+2]
+		x3 := b[y*8+3]
+		x4 := b[y*8+4]
+		x5 := b[y*8+5]
+		x6 := b[y*8+6]
+		x7 := b[y*8+7]
+
+		tmp0 := x0 + x7
+		tmp1 := x1 + x6
+		tmp2 := x2 + x5
+		tmp3 := x3 + x4
+
+		tmp10 := tmp0 + tmp3
+		tmp12 := tmp0 - tmp3
+		tmp11 := tmp1 + tmp2
+		tmp13 := tmp1 - tmp2
+
+		tmp0 = x0 - x7
+		tmp1 = x1 - x6
+		tmp2 = x2 - x5
+		tmp3 = x3 - x4
+
+		b[y*8+0] = (tmp10 + tmp11 - 8*centerJSample) << pass1Bits
+		b[y*8+4] = (tmp10 - tmp11) << pass1Bits
+		z1 := (tmp12 + tmp13) * fix_0_541196100
+		z1 += 1 << (constBits - pass1Bits - 1)
+		b[y*8+2] = (z1 + tmp12*fix_0_765366865) >> (constBits - pass1Bits)
+		b[y*8+6] = (z1 - tmp13*fix_1_847759065) >> (constBits - pass1Bits)
+
+		tmp10 = tmp0 + tmp3
+		tmp11 = tmp1 + tmp2
+		tmp12 = tmp0 + tmp2
+		tmp13 = tmp1 + tmp3
+		z1 = (tmp12 + tmp13) * fix_1_175875602
+		z1 += 1 << (constBits - pass1Bits - 1)
+		tmp0 = tmp0 * fix_1_501321110
+		tmp1 = tmp1 * fix_3_072711026
+		tmp2 = tmp2 * fix_2_053119869
+		tmp3 = tmp3 * fix_0_298631336
+		tmp10 = tmp10 * -fix_0_899976223
+		tmp11 = tmp11 * -fix_2_562915447
+		tmp12 = tmp12 * -fix_0_390180644
+		tmp13 = tmp13 * -fix_1_961570560
+
+		tmp12 += z1
+		tmp13 += z1
+		b[y*8+1] = (tmp0 + tmp10 + tmp12) >> (constBits - pass1Bits)
+		b[y*8+3] = (tmp1 + tmp11 + tmp13) >> (constBits - pass1Bits)
+		b[y*8+5] = (tmp2 + tmp11 + tmp12) >> (constBits - pass1Bits)
+		b[y*8+7] = (tmp3 + tmp10 + tmp13) >> (constBits - pass1Bits)
+	}
+	// Pass 2: process columns.
+	// We remove pass1Bits scaling, but leave results scaled up by an overall factor of 8.
+	for x := 0; x < 8; x++ {
+		tmp0 := b[0*8+x] + b[7*8+x]
+		tmp1 := b[1*8+x] + b[6*8+x]
+		tmp2 := b[2*8+x] + b[5*8+x]
+		tmp3 := b[3*8+x] + b[4*8+x]
+
+		tmp10 := tmp0 + tmp3 + 1<<(pass1Bits-1)
+		tmp12 := tmp0 - tmp3
+		tmp11 := tmp1 + tmp2
+		tmp13 := tmp1 - tmp2
+
+		tmp0 = b[0*8+x] - b[7*8+x]
+		tmp1 = b[1*8+x] - b[6*8+x]
+		tmp2 = b[2*8+x] - b[5*8+x]
+		tmp3 = b[3*8+x] - b[4*8+x]
+
+		b[0*8+x] = (tmp10 + tmp11) >> pass1Bits
+		b[4*8+x] = (tmp10 - tmp11) >> pass1Bits
+
+		z1 := (tmp12 + tmp13) * fix_0_541196100
+		z1 += 1 << (constBits + pass1Bits - 1)
+		b[2*8+x] = (z1 + tmp12*fix_0_765366865) >> (constBits + pass1Bits)
+		b[6*8+x] = (z1 - tmp13*fix_1_847759065) >> (constBits + pass1Bits)
+
+		tmp10 = tmp0 + tmp3
+		tmp11 = tmp1 + tmp2
+		tmp12 = tmp0 + tmp2
+		tmp13 = tmp1 + tmp3
+		z1 = (tmp12 + tmp13) * fix_1_175875602
+		z1 += 1 << (constBits + pass1Bits - 1)
+		tmp0 = tmp0 * fix_1_501321110
+		tmp1 = tmp1 * fix_3_072711026
+		tmp2 = tmp2 * fix_2_053119869
+		tmp3 = tmp3 * fix_0_298631336
+		tmp10 = tmp10 * -fix_0_899976223
+		tmp11 = tmp11 * -fix_2_562915447
+		tmp12 = tmp12 * -fix_0_390180644
+		tmp13 = tmp13 * -fix_1_961570560
+
+		tmp12 += z1
+		tmp13 += z1
+		b[1*8+x] = (tmp0 + tmp10 + tmp12) >> (constBits + pass1Bits)
+		b[3*8+x] = (tmp1 + tmp11 + tmp13) >> (constBits + pass1Bits)
+		b[5*8+x] = (tmp2 + tmp11 + tmp12) >> (constBits + pass1Bits)
+		b[7*8+x] = (tmp3 + tmp10 + tmp13) >> (constBits + pass1Bits)
+	}
+}
diff --git a/src/pkg/image/jpeg/idct.go b/src/pkg/image/jpeg/idct.go
index 5189931..e5a2f40 100644
--- a/src/pkg/image/jpeg/idct.go
+++ b/src/pkg/image/jpeg/idct.go
@@ -63,7 +63,7 @@ const (
 //
 // For more on the actual algorithm, see Z. Wang, "Fast algorithms for the discrete W transform and
 // for the discrete Fourier transform", IEEE Trans. on ASSP, Vol. ASSP- 32, pp. 803-816, Aug. 1984.
-func idct(b *[blockSize]int) {
+func idct(b *block) {
 	// Horizontal 1-D IDCT.
 	for y := 0; y < 8; y++ {
 		// If all the AC components are zero, then the IDCT is trivial.
diff --git a/src/pkg/image/jpeg/reader.go b/src/pkg/image/jpeg/reader.go
index fb9cb11..21a6fff 100644
--- a/src/pkg/image/jpeg/reader.go
+++ b/src/pkg/image/jpeg/reader.go
@@ -2,18 +2,22 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The jpeg package implements a decoder for JPEG images, as defined in ITU-T T.81.
+// Package jpeg implements a JPEG image decoder and encoder.
+//
+// JPEG is defined in ITU-T T.81: http://www.w3.org/Graphics/JPEG/itu-t81.pdf.
 package jpeg
 
-// See http://www.w3.org/Graphics/JPEG/itu-t81.pdf
-
 import (
 	"bufio"
 	"image"
+	"image/ycbcr"
 	"io"
 	"os"
 )
 
+// TODO(nigeltao): fix up the doc comment style so that sentences start with
+// the name of the type or function that they annotate.
+
 // A FormatError reports that the input is not a valid JPEG.
 type FormatError string
 
@@ -26,12 +30,14 @@ func (e UnsupportedError) String() string { return "unsupported JPEG feature: "
 
 // Component specification, specified in section B.2.2.
 type component struct {
+	h  int   // Horizontal sampling factor.
+	v  int   // Vertical sampling factor.
 	c  uint8 // Component identifier.
-	h  uint8 // Horizontal sampling factor.
-	v  uint8 // Vertical sampling factor.
 	tq uint8 // Quantization table destination selector.
 }
 
+type block [blockSize]int
+
 const (
 	blockSize = 64 // A DCT block is 8x8.
 
@@ -84,13 +90,13 @@ type Reader interface {
 type decoder struct {
 	r             Reader
 	width, height int
-	image         *image.RGBA
+	img           *ycbcr.YCbCr
 	ri            int // Restart Interval.
 	comps         [nComponent]component
 	huff          [maxTc + 1][maxTh + 1]huffman
-	quant         [maxTq + 1][blockSize]int
+	quant         [maxTq + 1]block
 	b             bits
-	blocks        [nComponent][maxH * maxV][blockSize]int
+	blocks        [nComponent][maxH * maxV]block
 	tmp           [1024]byte
 }
 
@@ -130,9 +136,9 @@ func (d *decoder) processSOF(n int) os.Error {
 	}
 	for i := 0; i < nComponent; i++ {
 		hv := d.tmp[7+3*i]
+		d.comps[i].h = int(hv >> 4)
+		d.comps[i].v = int(hv & 0x0f)
 		d.comps[i].c = d.tmp[6+3*i]
-		d.comps[i].h = hv >> 4
-		d.comps[i].v = hv & 0x0f
 		d.comps[i].tq = d.tmp[8+3*i]
 		// We only support YCbCr images, and 4:4:4, 4:2:2 or 4:2:0 chroma downsampling ratios. This implies that
 		// the (h, v) values for the Y component are either (1, 1), (2, 1) or (2, 2), and the
@@ -176,71 +182,47 @@ func (d *decoder) processDQT(n int) os.Error {
 	return nil
 }
 
-// Set the Pixel (px, py)'s RGB value, based on its YCbCr value.
-func (d *decoder) calcPixel(px, py, lumaBlock, lumaIndex, chromaIndex int) {
-	y, cb, cr := d.blocks[0][lumaBlock][lumaIndex], d.blocks[1][0][chromaIndex], d.blocks[2][0][chromaIndex]
-	// The JFIF specification (http://www.w3.org/Graphics/JPEG/jfif3.pdf, page 3) gives the formula
-	// for translating YCbCr to RGB as:
-	//   R = Y + 1.402 (Cr-128)
-	//   G = Y - 0.34414 (Cb-128) - 0.71414 (Cr-128)
-	//   B = Y + 1.772 (Cb-128)
-	yPlusHalf := 100000*y + 50000
-	cb -= 128
-	cr -= 128
-	r := (yPlusHalf + 140200*cr) / 100000
-	g := (yPlusHalf - 34414*cb - 71414*cr) / 100000
-	b := (yPlusHalf + 177200*cb) / 100000
-	if r < 0 {
-		r = 0
-	} else if r > 255 {
-		r = 255
+// Clip x to the range [0, 255] inclusive.
+func clip(x int) uint8 {
+	if x < 0 {
+		return 0
 	}
-	if g < 0 {
-		g = 0
-	} else if g > 255 {
-		g = 255
+	if x > 255 {
+		return 255
 	}
-	if b < 0 {
-		b = 0
-	} else if b > 255 {
-		b = 255
-	}
-	d.image.Pix[py*d.image.Stride+px] = image.RGBAColor{uint8(r), uint8(g), uint8(b), 0xff}
+	return uint8(x)
 }
 
-// Convert the MCU from YCbCr to RGB.
-func (d *decoder) convertMCU(mx, my, h0, v0 int) {
-	lumaBlock := 0
+// Store the MCU to the image.
+func (d *decoder) storeMCU(mx, my int) {
+	h0, v0 := d.comps[0].h, d.comps[0].v
+	// Store the luma blocks.
 	for v := 0; v < v0; v++ {
 		for h := 0; h < h0; h++ {
-			chromaBase := 8*4*v + 4*h
-			py := 8 * (v0*my + v)
-			for y := 0; y < 8 && py < d.height; y++ {
-				px := 8 * (h0*mx + h)
-				lumaIndex := 8 * y
-				chromaIndex := chromaBase + 8*(y/v0)
-				for x := 0; x < 8 && px < d.width; x++ {
-					d.calcPixel(px, py, lumaBlock, lumaIndex, chromaIndex)
-					if h0 == 1 {
-						chromaIndex += 1
-					} else {
-						chromaIndex += x % 2
-					}
-					lumaIndex++
-					px++
+			p := 8 * ((v0*my+v)*d.img.YStride + (h0*mx + h))
+			for y := 0; y < 8; y++ {
+				for x := 0; x < 8; x++ {
+					d.img.Y[p] = clip(d.blocks[0][h0*v+h][8*y+x])
+					p++
 				}
-				py++
+				p += d.img.YStride - 8
 			}
-			lumaBlock++
 		}
 	}
+	// Store the chroma blocks.
+	p := 8 * (my*d.img.CStride + mx)
+	for y := 0; y < 8; y++ {
+		for x := 0; x < 8; x++ {
+			d.img.Cb[p] = clip(d.blocks[1][0][8*y+x])
+			d.img.Cr[p] = clip(d.blocks[2][0][8*y+x])
+			p++
+		}
+		p += d.img.CStride - 8
+	}
 }
 
 // Specified in section B.2.3.
 func (d *decoder) processSOS(n int) os.Error {
-	if d.image == nil {
-		d.image = image.NewRGBA(d.width, d.height)
-	}
 	if n != 4+2*nComponent {
 		return UnsupportedError("SOS has wrong length")
 	}
@@ -255,7 +237,6 @@ func (d *decoder) processSOS(n int) os.Error {
 		td uint8 // DC table selector.
 		ta uint8 // AC table selector.
 	}
-	h0, v0 := int(d.comps[0].h), int(d.comps[0].v) // The h and v values from the Y components.
 	for i := 0; i < nComponent; i++ {
 		cs := d.tmp[1+2*i] // Component selector.
 		if cs != d.comps[i].c {
@@ -265,17 +246,42 @@ func (d *decoder) processSOS(n int) os.Error {
 		scanComps[i].ta = d.tmp[2+2*i] & 0x0f
 	}
 	// mxx and myy are the number of MCUs (Minimum Coded Units) in the image.
-	mxx := (d.width + 8*int(h0) - 1) / (8 * int(h0))
-	myy := (d.height + 8*int(v0) - 1) / (8 * int(v0))
+	h0, v0 := d.comps[0].h, d.comps[0].v // The h and v values from the Y components.
+	mxx := (d.width + 8*h0 - 1) / (8 * h0)
+	myy := (d.height + 8*v0 - 1) / (8 * v0)
+	if d.img == nil {
+		var subsampleRatio ycbcr.SubsampleRatio
+		n := h0 * v0
+		switch n {
+		case 1:
+			subsampleRatio = ycbcr.SubsampleRatio444
+		case 2:
+			subsampleRatio = ycbcr.SubsampleRatio422
+		case 4:
+			subsampleRatio = ycbcr.SubsampleRatio420
+		default:
+			panic("unreachable")
+		}
+		b := make([]byte, mxx*myy*(1*8*8*n+2*8*8))
+		d.img = &ycbcr.YCbCr{
+			Y:              b[mxx*myy*(0*8*8*n+0*8*8) : mxx*myy*(1*8*8*n+0*8*8)],
+			Cb:             b[mxx*myy*(1*8*8*n+0*8*8) : mxx*myy*(1*8*8*n+1*8*8)],
+			Cr:             b[mxx*myy*(1*8*8*n+1*8*8) : mxx*myy*(1*8*8*n+2*8*8)],
+			SubsampleRatio: subsampleRatio,
+			YStride:        mxx * 8 * h0,
+			CStride:        mxx * 8,
+			Rect:           image.Rect(0, 0, d.width, d.height),
+		}
+	}
 
 	mcu, expectedRST := 0, uint8(rst0Marker)
-	var allZeroes [blockSize]int
+	var allZeroes block
 	var dc [nComponent]int
 	for my := 0; my < myy; my++ {
 		for mx := 0; mx < mxx; mx++ {
 			for i := 0; i < nComponent; i++ {
 				qt := &d.quant[d.comps[i].tq]
-				for j := 0; j < int(d.comps[i].h*d.comps[i].v); j++ {
+				for j := 0; j < d.comps[i].h*d.comps[i].v; j++ {
 					d.blocks[i][j] = allZeroes
 
 					// Decode the DC coefficient, as specified in section F.2.2.1.
@@ -299,20 +305,20 @@ func (d *decoder) processSOS(n int) os.Error {
 						if err != nil {
 							return err
 						}
-						v0 := value >> 4
-						v1 := value & 0x0f
-						if v1 != 0 {
-							k += int(v0)
+						val0 := value >> 4
+						val1 := value & 0x0f
+						if val1 != 0 {
+							k += int(val0)
 							if k > blockSize {
 								return FormatError("bad DCT index")
 							}
-							ac, err := d.receiveExtend(v1)
+							ac, err := d.receiveExtend(val1)
 							if err != nil {
 								return err
 							}
 							d.blocks[i][j][unzig[k]] = ac * qt[k]
 						} else {
-							if v0 != 0x0f {
+							if val0 != 0x0f {
 								break
 							}
 							k += 0x0f
@@ -322,7 +328,7 @@ func (d *decoder) processSOS(n int) os.Error {
 					idct(&d.blocks[i][j])
 				} // for j
 			} // for i
-			d.convertMCU(mx, my, int(d.comps[0].h), int(d.comps[0].v))
+			d.storeMCU(mx, my)
 			mcu++
 			if d.ri > 0 && mcu%d.ri == 0 && mcu < mxx*myy {
 				// A more sophisticated decoder could use RST[0-7] markers to resynchronize from corrupt input,
@@ -431,7 +437,7 @@ func (d *decoder) decode(r io.Reader, configOnly bool) (image.Image, os.Error) {
 			return nil, err
 		}
 	}
-	return d.image, nil
+	return d.img, nil
 }
 
 // Decode reads a JPEG image from r and returns it as an image.Image.
diff --git a/src/pkg/image/jpeg/writer.go b/src/pkg/image/jpeg/writer.go
new file mode 100644
index 0000000..505cce0
--- /dev/null
+++ b/src/pkg/image/jpeg/writer.go
@@ -0,0 +1,523 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package jpeg
+
+import (
+	"bufio"
+	"image"
+	"image/ycbcr"
+	"io"
+	"os"
+)
+
+// min returns the minimum of two integers.
+func min(x, y int) int {
+	if x < y {
+		return x
+	}
+	return y
+}
+
+// div returns a/b rounded to the nearest integer, instead of rounded to zero.
+func div(a int, b int) int {
+	if a >= 0 {
+		return (a + (b >> 1)) / b
+	}
+	return -((-a + (b >> 1)) / b)
+}
+
+// bitCount counts the number of bits needed to hold an integer.
+var bitCount = [256]byte{
+	0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
+	5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+	6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+	6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+}
+
+type quantIndex int
+
+const (
+	quantIndexLuminance quantIndex = iota
+	quantIndexChrominance
+	nQuantIndex
+)
+
+// unscaledQuant are the unscaled quantization tables. Each encoder copies and
+// scales the tables according to its quality parameter.
+var unscaledQuant = [nQuantIndex][blockSize]byte{
+	// Luminance.
+	{
+		16, 11, 10, 16, 24, 40, 51, 61,
+		12, 12, 14, 19, 26, 58, 60, 55,
+		14, 13, 16, 24, 40, 57, 69, 56,
+		14, 17, 22, 29, 51, 87, 80, 62,
+		18, 22, 37, 56, 68, 109, 103, 77,
+		24, 35, 55, 64, 81, 104, 113, 92,
+		49, 64, 78, 87, 103, 121, 120, 101,
+		72, 92, 95, 98, 112, 100, 103, 99,
+	},
+	// Chrominance.
+	{
+		17, 18, 24, 47, 99, 99, 99, 99,
+		18, 21, 26, 66, 99, 99, 99, 99,
+		24, 26, 56, 99, 99, 99, 99, 99,
+		47, 66, 99, 99, 99, 99, 99, 99,
+		99, 99, 99, 99, 99, 99, 99, 99,
+		99, 99, 99, 99, 99, 99, 99, 99,
+		99, 99, 99, 99, 99, 99, 99, 99,
+		99, 99, 99, 99, 99, 99, 99, 99,
+	},
+}
+
+type huffIndex int
+
+const (
+	huffIndexLuminanceDC huffIndex = iota
+	huffIndexLuminanceAC
+	huffIndexChrominanceDC
+	huffIndexChrominanceAC
+	nHuffIndex
+)
+
+// huffmanSpec specifies a Huffman encoding.
+type huffmanSpec struct {
+	// count[i] is the number of codes of length i bits.
+	count [16]byte
+	// value[i] is the decoded value of the i'th codeword.
+	value []byte
+}
+
+// theHuffmanSpec is the Huffman encoding specifications.
+// This encoder uses the same Huffman encoding for all images.
+var theHuffmanSpec = [nHuffIndex]huffmanSpec{
+	// Luminance DC.
+	{
+		[16]byte{0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0},
+		[]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11},
+	},
+	// Luminance AC.
+	{
+		[16]byte{0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 125},
+		[]byte{
+			0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
+			0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
+			0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
+			0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
+			0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
+			0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
+			0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+			0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+			0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+			0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+			0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+			0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+			0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+			0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+			0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+			0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
+			0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
+			0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
+			0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
+			0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+			0xf9, 0xfa,
+		},
+	},
+	// Chrominance DC.
+	{
+		[16]byte{0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0},
+		[]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11},
+	},
+	// Chrominance AC.
+	{
+		[16]byte{0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 119},
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
+			0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
+			0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
+			0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
+			0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
+			0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
+			0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
+			0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+			0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+			0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+			0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+			0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+			0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
+			0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
+			0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
+			0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
+			0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
+			0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
+			0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
+			0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+			0xf9, 0xfa,
+		},
+	},
+}
+
+// huffmanLUT is a compiled look-up table representation of a huffmanSpec.
+// Each value maps to a uint32 of which the 8 most significant bits hold the
+// codeword size in bits and the 24 least significant bits hold the codeword.
+// The maximum codeword size is 16 bits.
+type huffmanLUT []uint32
+
+func (h *huffmanLUT) init(s huffmanSpec) {
+	maxValue := 0
+	for _, v := range s.value {
+		if int(v) > maxValue {
+			maxValue = int(v)
+		}
+	}
+	*h = make([]uint32, maxValue+1)
+	code, k := uint32(0), 0
+	for i := 0; i < len(s.count); i++ {
+		nBits := uint32(i+1) << 24
+		for j := uint8(0); j < s.count[i]; j++ {
+			(*h)[s.value[k]] = nBits | code
+			code++
+			k++
+		}
+		code <<= 1
+	}
+}
+
+// theHuffmanLUT are compiled representations of theHuffmanSpec.
+var theHuffmanLUT [4]huffmanLUT
+
+func init() {
+	for i, s := range theHuffmanSpec {
+		theHuffmanLUT[i].init(s)
+	}
+}
+
+// writer is a buffered writer.
+type writer interface {
+	Flush() os.Error
+	Write([]byte) (int, os.Error)
+	WriteByte(byte) os.Error
+}
+
+// encoder encodes an image to the JPEG format.
+type encoder struct {
+	// w is the writer to write to. err is the first error encountered during
+	// writing. All attempted writes after the first error become no-ops.
+	w   writer
+	err os.Error
+	// buf is a scratch buffer.
+	buf [16]byte
+	// bits and nBits are accumulated bits to write to w.
+	bits  uint32
+	nBits uint8
+	// quant is the scaled quantization tables.
+	quant [nQuantIndex][blockSize]byte
+}
+
+func (e *encoder) flush() {
+	if e.err != nil {
+		return
+	}
+	e.err = e.w.Flush()
+}
+
+func (e *encoder) write(p []byte) {
+	if e.err != nil {
+		return
+	}
+	_, e.err = e.w.Write(p)
+}
+
+func (e *encoder) writeByte(b byte) {
+	if e.err != nil {
+		return
+	}
+	e.err = e.w.WriteByte(b)
+}
+
+// emit emits the least significant nBits bits of bits to the bitstream.
+// The precondition is bits < 1<<nBits && nBits <= 16.
+func (e *encoder) emit(bits uint32, nBits uint8) {
+	nBits += e.nBits
+	bits <<= 32 - nBits
+	bits |= e.bits
+	for nBits >= 8 {
+		b := uint8(bits >> 24)
+		e.writeByte(b)
+		if b == 0xff {
+			e.writeByte(0x00)
+		}
+		bits <<= 8
+		nBits -= 8
+	}
+	e.bits, e.nBits = bits, nBits
+}
+
+// emitHuff emits the given value with the given Huffman encoder.
+func (e *encoder) emitHuff(h huffIndex, value int) {
+	x := theHuffmanLUT[h][value]
+	e.emit(x&(1<<24-1), uint8(x>>24))
+}
+
+// emitHuffRLE emits a run of runLength copies of value encoded with the given
+// Huffman encoder.
+func (e *encoder) emitHuffRLE(h huffIndex, runLength, value int) {
+	a, b := value, value
+	if a < 0 {
+		a, b = -value, value-1
+	}
+	var nBits uint8
+	if a < 0x100 {
+		nBits = bitCount[a]
+	} else {
+		nBits = 8 + bitCount[a>>8]
+	}
+	e.emitHuff(h, runLength<<4|int(nBits))
+	if nBits > 0 {
+		e.emit(uint32(b)&(1<<nBits-1), nBits)
+	}
+}
+
+// writeMarkerHeader writes the header for a marker with the given length.
+func (e *encoder) writeMarkerHeader(marker uint8, markerlen int) {
+	e.buf[0] = 0xff
+	e.buf[1] = marker
+	e.buf[2] = uint8(markerlen >> 8)
+	e.buf[3] = uint8(markerlen & 0xff)
+	e.write(e.buf[:4])
+}
+
+// writeDQT writes the Define Quantization Table marker.
+func (e *encoder) writeDQT() {
+	markerlen := 2
+	for _, q := range e.quant {
+		markerlen += 1 + len(q)
+	}
+	e.writeMarkerHeader(dqtMarker, markerlen)
+	for i, q := range e.quant {
+		e.writeByte(uint8(i))
+		e.write(q[:])
+	}
+}
+
+// writeSOF0 writes the Start Of Frame (Baseline) marker.
+func (e *encoder) writeSOF0(size image.Point) {
+	markerlen := 8 + 3*nComponent
+	e.writeMarkerHeader(sof0Marker, markerlen)
+	e.buf[0] = 8 // 8-bit color.
+	e.buf[1] = uint8(size.Y >> 8)
+	e.buf[2] = uint8(size.Y & 0xff)
+	e.buf[3] = uint8(size.X >> 8)
+	e.buf[4] = uint8(size.X & 0xff)
+	e.buf[5] = nComponent
+	for i := 0; i < nComponent; i++ {
+		e.buf[3*i+6] = uint8(i + 1)
+		// We use 4:2:0 chroma subsampling.
+		e.buf[3*i+7] = "\x22\x11\x11"[i]
+		e.buf[3*i+8] = "\x00\x01\x01"[i]
+	}
+	e.write(e.buf[:3*(nComponent-1)+9])
+}
+
+// writeDHT writes the Define Huffman Table marker.
+func (e *encoder) writeDHT() {
+	markerlen := 2
+	for _, s := range theHuffmanSpec {
+		markerlen += 1 + 16 + len(s.value)
+	}
+	e.writeMarkerHeader(dhtMarker, markerlen)
+	for i, s := range theHuffmanSpec {
+		e.writeByte("\x00\x10\x01\x11"[i])
+		e.write(s.count[:])
+		e.write(s.value)
+	}
+}
+
+// writeBlock writes a block of pixel data using the given quantization table,
+// returning the post-quantized DC value of the DCT-transformed block.
+func (e *encoder) writeBlock(b *block, q quantIndex, prevDC int) int {
+	fdct(b)
+	// Emit the DC delta.
+	dc := div(b[0], (8 * int(e.quant[q][0])))
+	e.emitHuffRLE(huffIndex(2*q+0), 0, dc-prevDC)
+	// Emit the AC components.
+	h, runLength := huffIndex(2*q+1), 0
+	for k := 1; k < blockSize; k++ {
+		ac := div(b[unzig[k]], (8 * int(e.quant[q][k])))
+		if ac == 0 {
+			runLength++
+		} else {
+			for runLength > 15 {
+				e.emitHuff(h, 0xf0)
+				runLength -= 16
+			}
+			e.emitHuffRLE(h, runLength, ac)
+			runLength = 0
+		}
+	}
+	if runLength > 0 {
+		e.emitHuff(h, 0x00)
+	}
+	return dc
+}
+
+// toYCbCr converts the 8x8 region of m whose top-left corner is p to its
+// YCbCr values.
+func toYCbCr(m image.Image, p image.Point, yBlock, cbBlock, crBlock *block) {
+	b := m.Bounds()
+	xmax := b.Max.X - 1
+	ymax := b.Max.Y - 1
+	for j := 0; j < 8; j++ {
+		for i := 0; i < 8; i++ {
+			r, g, b, _ := m.At(min(p.X+i, xmax), min(p.Y+j, ymax)).RGBA()
+			yy, cb, cr := ycbcr.RGBToYCbCr(uint8(r>>8), uint8(g>>8), uint8(b>>8))
+			yBlock[8*j+i] = int(yy)
+			cbBlock[8*j+i] = int(cb)
+			crBlock[8*j+i] = int(cr)
+		}
+	}
+}
+
+// scale scales the 16x16 region represented by the 4 src blocks to the 8x8
+// dst block.
+func scale(dst *block, src *[4]block) {
+	for i := 0; i < 4; i++ {
+		dstOff := (i&2)<<4 | (i&1)<<2
+		for y := 0; y < 4; y++ {
+			for x := 0; x < 4; x++ {
+				j := 16*y + 2*x
+				sum := src[i][j] + src[i][j+1] + src[i][j+8] + src[i][j+9]
+				dst[8*y+x+dstOff] = (sum + 2) >> 2
+			}
+		}
+	}
+}
+
+// sosHeader is the SOS marker "\xff\xda" followed by 12 bytes:
+//	- the marker length "\x00\x0c",
+//	- the number of components "\x03",
+//	- component 1 uses DC table 0 and AC table 0 "\x01\x00",
+//	- component 2 uses DC table 1 and AC table 1 "\x02\x11",
+//	- component 3 uses DC table 1 and AC table 1 "\x03\x11",
+//	- padding "\x00\x00\x00".
+var sosHeader = []byte{
+	0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02,
+	0x11, 0x03, 0x11, 0x00, 0x00, 0x00,
+}
+
+// writeSOS writes the StartOfScan marker.
+func (e *encoder) writeSOS(m image.Image) {
+	e.write(sosHeader)
+	var (
+		// Scratch buffers to hold the YCbCr values.
+		yBlock  block
+		cbBlock [4]block
+		crBlock [4]block
+		cBlock  block
+		// DC components are delta-encoded.
+		prevDCY, prevDCCb, prevDCCr int
+	)
+	bounds := m.Bounds()
+	for y := bounds.Min.Y; y < bounds.Max.Y; y += 16 {
+		for x := bounds.Min.X; x < bounds.Max.X; x += 16 {
+			for i := 0; i < 4; i++ {
+				xOff := (i & 1) * 8
+				yOff := (i & 2) * 4
+				p := image.Point{x + xOff, y + yOff}
+				toYCbCr(m, p, &yBlock, &cbBlock[i], &crBlock[i])
+				prevDCY = e.writeBlock(&yBlock, 0, prevDCY)
+			}
+			scale(&cBlock, &cbBlock)
+			prevDCCb = e.writeBlock(&cBlock, 1, prevDCCb)
+			scale(&cBlock, &crBlock)
+			prevDCCr = e.writeBlock(&cBlock, 1, prevDCCr)
+		}
+	}
+	// Pad the last byte with 1's.
+	e.emit(0x7f, 7)
+}
+
+// DefaultQuality is the default quality encoding parameter.
+const DefaultQuality = 75
+
+// Options are the encoding parameters.
+// Quality ranges from 1 to 100 inclusive, higher is better.
+type Options struct {
+	Quality int
+}
+
+// Encode writes the Image m to w in JPEG 4:2:0 baseline format with the given
+// options. Default parameters are used if a nil *Options is passed.
+func Encode(w io.Writer, m image.Image, o *Options) os.Error {
+	b := m.Bounds()
+	if b.Dx() >= 1<<16 || b.Dy() >= 1<<16 {
+		return os.NewError("jpeg: image is too large to encode")
+	}
+	var e encoder
+	if ww, ok := w.(writer); ok {
+		e.w = ww
+	} else {
+		e.w = bufio.NewWriter(w)
+	}
+	// Clip quality to [1, 100].
+	quality := DefaultQuality
+	if o != nil {
+		quality = o.Quality
+		if quality < 1 {
+			quality = 1
+		} else if quality > 100 {
+			quality = 100
+		}
+	}
+	// Convert from a quality rating to a scaling factor.
+	var scale int
+	if quality < 50 {
+		scale = 5000 / quality
+	} else {
+		scale = 200 - quality*2
+	}
+	// Initialize the quantization tables.
+	for i := range e.quant {
+		for j := range e.quant[i] {
+			x := int(unscaledQuant[i][j])
+			x = (x*scale + 50) / 100
+			if x < 1 {
+				x = 1
+			} else if x > 255 {
+				x = 255
+			}
+			e.quant[i][j] = uint8(x)
+		}
+	}
+	// Write the Start Of Image marker.
+	e.buf[0] = 0xff
+	e.buf[1] = 0xd8
+	e.write(e.buf[:2])
+	// Write the quantization tables.
+	e.writeDQT()
+	// Write the image dimensions.
+	e.writeSOF0(b.Size())
+	// Write the Huffman tables.
+	e.writeDHT()
+	// Write the image data.
+	e.writeSOS(m)
+	// Write the End Of Image marker.
+	e.buf[0] = 0xff
+	e.buf[1] = 0xd9
+	e.write(e.buf[:2])
+	e.flush()
+	return e.err
+}
diff --git a/src/pkg/image/jpeg/writer_test.go b/src/pkg/image/jpeg/writer_test.go
new file mode 100644
index 0000000..00922dd
--- /dev/null
+++ b/src/pkg/image/jpeg/writer_test.go
@@ -0,0 +1,87 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package jpeg
+
+import (
+	"bytes"
+	"image"
+	"image/png"
+	"os"
+	"testing"
+)
+
+var testCase = []struct {
+	filename  string
+	quality   int
+	tolerance int64
+}{
+	{"../testdata/video-001.png", 1, 24 << 8},
+	{"../testdata/video-001.png", 20, 12 << 8},
+	{"../testdata/video-001.png", 60, 8 << 8},
+	{"../testdata/video-001.png", 80, 6 << 8},
+	{"../testdata/video-001.png", 90, 4 << 8},
+	{"../testdata/video-001.png", 100, 2 << 8},
+}
+
+func delta(u0, u1 uint32) int64 {
+	d := int64(u0) - int64(u1)
+	if d < 0 {
+		return -d
+	}
+	return d
+}
+
+func readPng(filename string) (image.Image, os.Error) {
+	f, err := os.Open(filename)
+	if err != nil {
+		return nil, err
+	}
+	defer f.Close()
+	return png.Decode(f)
+}
+
+func TestWriter(t *testing.T) {
+	for _, tc := range testCase {
+		// Read the image.
+		m0, err := readPng(tc.filename)
+		if err != nil {
+			t.Error(tc.filename, err)
+			continue
+		}
+		// Encode that image as JPEG.
+		buf := bytes.NewBuffer(nil)
+		err = Encode(buf, m0, &Options{Quality: tc.quality})
+		if err != nil {
+			t.Error(tc.filename, err)
+			continue
+		}
+		// Decode that JPEG.
+		m1, err := Decode(buf)
+		if err != nil {
+			t.Error(tc.filename, err)
+			continue
+		}
+		// Compute the average delta in RGB space.
+		b := m0.Bounds()
+		var sum, n int64
+		for y := b.Min.Y; y < b.Max.Y; y++ {
+			for x := b.Min.X; x < b.Max.X; x++ {
+				c0 := m0.At(x, y)
+				c1 := m1.At(x, y)
+				r0, g0, b0, _ := c0.RGBA()
+				r1, g1, b1, _ := c1.RGBA()
+				sum += delta(r0, r1)
+				sum += delta(g0, g1)
+				sum += delta(b0, b1)
+				n += 3
+			}
+		}
+		// Compare the average delta to the tolerance level.
+		if sum/n > tc.tolerance {
+			t.Errorf("%s, quality=%d: average delta is too high", tc.filename, tc.quality)
+			continue
+		}
+	}
+}
diff --git a/src/pkg/image/png/reader.go b/src/pkg/image/png/reader.go
index eee4eac..b30a951 100644
--- a/src/pkg/image/png/reader.go
+++ b/src/pkg/image/png/reader.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The png package implements a PNG image decoder and encoder.
+// Package png implements a PNG image decoder and encoder.
 //
 // The PNG specification is at http://www.libpng.org/pub/png/spec/1.2/PNG-Contents.html
 package png
diff --git a/src/pkg/image/ycbcr/ycbcr.go b/src/pkg/image/ycbcr/ycbcr.go
index b2e033b..cda4599 100644
--- a/src/pkg/image/ycbcr/ycbcr.go
+++ b/src/pkg/image/ycbcr/ycbcr.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The ycbcr package provides images from the Y'CbCr color model.
+// Package ycbcr provides images from the Y'CbCr color model.
 //
 // JPEG, VP8, the MPEG family and other codecs use this color model. Such
 // codecs often use the terms YUV and Y'CbCr interchangeably, but strictly
diff --git a/src/pkg/index/suffixarray/suffixarray.go b/src/pkg/index/suffixarray/suffixarray.go
index d8c6fc9..079b7d8 100644
--- a/src/pkg/index/suffixarray/suffixarray.go
+++ b/src/pkg/index/suffixarray/suffixarray.go
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The suffixarray package implements substring search in logarithmic time
-// using an in-memory suffix array.
+// Package suffixarray implements substring search in logarithmic time using
+// an in-memory suffix array.
 //
 // Example use:
 //
diff --git a/src/pkg/io/io.go b/src/pkg/io/io.go
index d3707eb..0bc73d6 100644
--- a/src/pkg/io/io.go
+++ b/src/pkg/io/io.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package provides basic interfaces to I/O primitives.
+// Package io provides basic interfaces to I/O primitives.
 // Its primary job is to wrap existing implementations of such primitives,
 // such as those in package os, into shared public interfaces that
 // abstract the functionality, plus some other related primitives.
diff --git a/src/pkg/io/ioutil/ioutil.go b/src/pkg/io/ioutil/ioutil.go
index 57d797e..5f1eeca 100644
--- a/src/pkg/io/ioutil/ioutil.go
+++ b/src/pkg/io/ioutil/ioutil.go
@@ -2,8 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Utility functions.
-
+// Package ioutil implements some I/O utility functions.
 package ioutil
 
 import (
@@ -102,3 +101,13 @@ func (nopCloser) Close() os.Error { return nil }
 func NopCloser(r io.Reader) io.ReadCloser {
 	return nopCloser{r}
 }
+
+type devNull int
+
+func (devNull) Write(p []byte) (int, os.Error) {
+	return len(p), nil
+}
+
+// Discard is an io.Writer on which all Write calls succeed
+// without doing anything.
+var Discard io.Writer = devNull(0)
diff --git a/src/pkg/json/decode.go b/src/pkg/json/decode.go
index a5fd339..e78b60c 100644
--- a/src/pkg/json/decode.go
+++ b/src/pkg/json/decode.go
@@ -122,11 +122,10 @@ func (d *decodeState) unmarshal(v interface{}) (err os.Error) {
 		}
 	}()
 
-	rv := reflect.NewValue(v)
+	rv := reflect.ValueOf(v)
 	pv := rv
-	if pv.Kind() != reflect.Ptr ||
-		pv.IsNil() {
-		return &InvalidUnmarshalError{reflect.Typeof(v)}
+	if pv.Kind() != reflect.Ptr || pv.IsNil() {
+		return &InvalidUnmarshalError{reflect.TypeOf(v)}
 	}
 
 	d.scan.reset()
@@ -267,17 +266,17 @@ func (d *decodeState) indirect(v reflect.Value, wantptr bool) (Unmarshaler, refl
 			v = iv.Elem()
 			continue
 		}
+
 		pv := v
 		if pv.Kind() != reflect.Ptr {
 			break
 		}
 
-		if pv.Elem().Kind() != reflect.Ptr &&
-			wantptr && !isUnmarshaler {
+		if pv.Elem().Kind() != reflect.Ptr && wantptr && pv.CanSet() && !isUnmarshaler {
 			return nil, pv
 		}
 		if pv.IsNil() {
-			pv.Set(reflect.Zero(pv.Type().Elem()).Addr())
+			pv.Set(reflect.New(pv.Type().Elem()))
 		}
 		if isUnmarshaler {
 			// Using v.Interface().(Unmarshaler)
@@ -314,7 +313,7 @@ func (d *decodeState) array(v reflect.Value) {
 	iv := v
 	ok := iv.Kind() == reflect.Interface
 	if ok {
-		iv.Set(reflect.NewValue(d.arrayInterface()))
+		iv.Set(reflect.ValueOf(d.arrayInterface()))
 		return
 	}
 
@@ -410,7 +409,7 @@ func (d *decodeState) object(v reflect.Value) {
 	// Decoding into nil interface?  Switch to non-reflect code.
 	iv := v
 	if iv.Kind() == reflect.Interface {
-		iv.Set(reflect.NewValue(d.objectInterface()))
+		iv.Set(reflect.ValueOf(d.objectInterface()))
 		return
 	}
 
@@ -423,7 +422,7 @@ func (d *decodeState) object(v reflect.Value) {
 	case reflect.Map:
 		// map must have string type
 		t := v.Type()
-		if t.Key() != reflect.Typeof("") {
+		if t.Key() != reflect.TypeOf("") {
 			d.saveError(&UnmarshalTypeError{"object", v.Type()})
 			break
 		}
@@ -443,6 +442,8 @@ func (d *decodeState) object(v reflect.Value) {
 		return
 	}
 
+	var mapElem reflect.Value
+
 	for {
 		// Read opening " of string key or closing }.
 		op := d.scanWhile(scanSkipSpace)
@@ -466,7 +467,13 @@ func (d *decodeState) object(v reflect.Value) {
 		// Figure out field corresponding to key.
 		var subv reflect.Value
 		if mv.IsValid() {
-			subv = reflect.Zero(mv.Type().Elem())
+			elemType := mv.Type().Elem()
+			if !mapElem.IsValid() {
+				mapElem = reflect.New(elemType).Elem()
+			} else {
+				mapElem.Set(reflect.Zero(elemType))
+			}
+			subv = mapElem
 		} else {
 			var f reflect.StructField
 			var ok bool
@@ -514,7 +521,7 @@ func (d *decodeState) object(v reflect.Value) {
 		// Write value back to map;
 		// if using struct, subv points into struct already.
 		if mv.IsValid() {
-			mv.SetMapIndex(reflect.NewValue(key), subv)
+			mv.SetMapIndex(reflect.ValueOf(key), subv)
 		}
 
 		// Next token must be , or }.
@@ -570,7 +577,7 @@ func (d *decodeState) literal(v reflect.Value) {
 		case reflect.Bool:
 			v.SetBool(value)
 		case reflect.Interface:
-			v.Set(reflect.NewValue(value))
+			v.Set(reflect.ValueOf(value))
 		}
 
 	case '"': // string
@@ -592,11 +599,11 @@ func (d *decodeState) literal(v reflect.Value) {
 				d.saveError(err)
 				break
 			}
-			v.Set(reflect.NewValue(b[0:n]))
+			v.Set(reflect.ValueOf(b[0:n]))
 		case reflect.String:
 			v.SetString(string(s))
 		case reflect.Interface:
-			v.Set(reflect.NewValue(string(s)))
+			v.Set(reflect.ValueOf(string(s)))
 		}
 
 	default: // number
@@ -613,7 +620,7 @@ func (d *decodeState) literal(v reflect.Value) {
 				d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
 				break
 			}
-			v.Set(reflect.NewValue(n))
+			v.Set(reflect.ValueOf(n))
 
 		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
 			n, err := strconv.Atoi64(s)
@@ -767,7 +774,7 @@ func (d *decodeState) literalInterface() interface{} {
 		}
 		n, err := strconv.Atof64(string(item))
 		if err != nil {
-			d.saveError(&UnmarshalTypeError{"number " + string(item), reflect.Typeof(0.0)})
+			d.saveError(&UnmarshalTypeError{"number " + string(item), reflect.TypeOf(0.0)})
 		}
 		return n
 	}
diff --git a/src/pkg/json/decode_test.go b/src/pkg/json/decode_test.go
index 49135c4..bf8bf10 100644
--- a/src/pkg/json/decode_test.go
+++ b/src/pkg/json/decode_test.go
@@ -21,7 +21,7 @@ type tx struct {
 	x int
 }
 
-var txType = reflect.Typeof((*tx)(nil)).Elem()
+var txType = reflect.TypeOf((*tx)(nil)).Elem()
 
 // A type that can unmarshal itself.
 
@@ -64,14 +64,14 @@ var unmarshalTests = []unmarshalTest{
 	{`"g-clef: \uD834\uDD1E"`, new(string), "g-clef: \U0001D11E", nil},
 	{`"invalid: \uD834x\uDD1E"`, new(string), "invalid: \uFFFDx\uFFFD", nil},
 	{"null", new(interface{}), nil, nil},
-	{`{"X": [1,2,3], "Y": 4}`, new(T), T{Y: 4}, &UnmarshalTypeError{"array", reflect.Typeof("")}},
+	{`{"X": [1,2,3], "Y": 4}`, new(T), T{Y: 4}, &UnmarshalTypeError{"array", reflect.TypeOf("")}},
 	{`{"x": 1}`, new(tx), tx{}, &UnmarshalFieldError{"x", txType, txType.Field(0)}},
 
 	// skip invalid tags
 	{`{"X":"a", "y":"b", "Z":"c"}`, new(badTag), badTag{"a", "b", "c"}, nil},
 
 	// syntax errors
-	{`{"X": "foo", "Y"}`, nil, nil, SyntaxError("invalid character '}' after object key")},
+	{`{"X": "foo", "Y"}`, nil, nil, &SyntaxError{"invalid character '}' after object key", 17}},
 
 	// composite tests
 	{allValueIndent, new(All), allValue, nil},
@@ -125,12 +125,12 @@ func TestMarshalBadUTF8(t *testing.T) {
 }
 
 func TestUnmarshal(t *testing.T) {
-	var scan scanner
 	for i, tt := range unmarshalTests {
+		var scan scanner
 		in := []byte(tt.in)
 		if err := checkValid(in, &scan); err != nil {
 			if !reflect.DeepEqual(err, tt.err) {
-				t.Errorf("#%d: checkValid: %v", i, err)
+				t.Errorf("#%d: checkValid: %#v", i, err)
 				continue
 			}
 		}
@@ -138,8 +138,7 @@ func TestUnmarshal(t *testing.T) {
 			continue
 		}
 		// v = new(right-type)
-		v := reflect.NewValue(tt.ptr)
-		v.Set(reflect.Zero(v.Type().Elem()).Addr())
+		v := reflect.New(reflect.TypeOf(tt.ptr).Elem())
 		if err := Unmarshal([]byte(in), v.Interface()); !reflect.DeepEqual(err, tt.err) {
 			t.Errorf("#%d: %v want %v", i, err, tt.err)
 			continue
diff --git a/src/pkg/json/encode.go b/src/pkg/json/encode.go
index dfa3c59..ec0a14a 100644
--- a/src/pkg/json/encode.go
+++ b/src/pkg/json/encode.go
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The json package implements encoding and decoding of JSON objects as
-// defined in RFC 4627.
+// Package json implements encoding and decoding of JSON objects as defined in
+// RFC 4627.
 package json
 
 import (
@@ -172,7 +172,7 @@ func (e *encodeState) marshal(v interface{}) (err os.Error) {
 			err = r.(os.Error)
 		}
 	}()
-	e.reflectValue(reflect.NewValue(v))
+	e.reflectValue(reflect.ValueOf(v))
 	return nil
 }
 
@@ -180,7 +180,7 @@ func (e *encodeState) error(err os.Error) {
 	panic(err)
 }
 
-var byteSliceType = reflect.Typeof([]byte(nil))
+var byteSliceType = reflect.TypeOf([]byte(nil))
 
 func (e *encodeState) reflectValue(v reflect.Value) {
 	if !v.IsValid() {
diff --git a/src/pkg/json/scanner.go b/src/pkg/json/scanner.go
index e98ddef..49c2edd 100644
--- a/src/pkg/json/scanner.go
+++ b/src/pkg/json/scanner.go
@@ -23,6 +23,7 @@ import (
 func checkValid(data []byte, scan *scanner) os.Error {
 	scan.reset()
 	for _, c := range data {
+		scan.bytes++
 		if scan.step(scan, int(c)) == scanError {
 			return scan.err
 		}
@@ -56,10 +57,12 @@ func nextValue(data []byte, scan *scanner) (value, rest []byte, err os.Error) {
 }
 
 // A SyntaxError is a description of a JSON syntax error.
-type SyntaxError string
-
-func (e SyntaxError) String() string { return string(e) }
+type SyntaxError struct {
+	msg    string // description of error
+	Offset int64  // error occurred after reading Offset bytes
+}
 
+func (e *SyntaxError) String() string { return e.msg }
 
 // A scanner is a JSON scanning state machine.
 // Callers call scan.reset() and then pass bytes in one at a time
@@ -89,6 +92,9 @@ type scanner struct {
 	// 1-byte redo (see undo method)
 	redoCode  int
 	redoState func(*scanner, int) int
+
+	// total bytes consumed, updated by decoder.Decode
+	bytes int64
 }
 
 // These values are returned by the state transition functions
@@ -148,7 +154,7 @@ func (s *scanner) eof() int {
 		return scanEnd
 	}
 	if s.err == nil {
-		s.err = SyntaxError("unexpected end of JSON input")
+		s.err = &SyntaxError{"unexpected end of JSON input", s.bytes}
 	}
 	return scanError
 }
@@ -581,7 +587,7 @@ func stateError(s *scanner, c int) int {
 // error records an error and switches to the error state.
 func (s *scanner) error(c int, context string) int {
 	s.step = stateError
-	s.err = SyntaxError("invalid character " + quoteChar(c) + " " + context)
+	s.err = &SyntaxError{"invalid character " + quoteChar(c) + " " + context, s.bytes}
 	return scanError
 }
 
diff --git a/src/pkg/json/stream.go b/src/pkg/json/stream.go
index cb9b165..f143b3f 100644
--- a/src/pkg/json/stream.go
+++ b/src/pkg/json/stream.go
@@ -23,8 +23,8 @@ func NewDecoder(r io.Reader) *Decoder {
 	return &Decoder{r: r}
 }
 
-// Decode reads the next JSON-encoded value from the
-// connection and stores it in the value pointed to by v.
+// Decode reads the next JSON-encoded value from its
+// input and stores it in the value pointed to by v.
 //
 // See the documentation for Unmarshal for details about
 // the conversion of JSON into a Go value.
@@ -62,6 +62,7 @@ Input:
 	for {
 		// Look in the buffer for a new value.
 		for i, c := range dec.buf[scanp:] {
+			dec.scan.bytes++
 			v := dec.scan.step(&dec.scan, int(c))
 			if v == scanEnd {
 				scanp += i
diff --git a/src/pkg/log/log.go b/src/pkg/log/log.go
index 33140ee..00bce6a 100644
--- a/src/pkg/log/log.go
+++ b/src/pkg/log/log.go
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Simple logging package. It defines a type, Logger, with methods
-// for formatting output. It also has a predefined 'standard' Logger
-// accessible through helper functions Print[f|ln], Fatal[f|ln], and
+// Package log implements a simple logging package. It defines a type, Logger,
+// with methods for formatting output. It also has a predefined 'standard'
+// Logger accessible through helper functions Print[f|ln], Fatal[f|ln], and
 // Panic[f|ln], which are easier to use than creating a Logger manually.
 // That logger writes to standard error and prints the date and time
 // of each logged message.
diff --git a/src/pkg/math/const.go b/src/pkg/math/const.go
index b53527a..a108d3e 100644
--- a/src/pkg/math/const.go
+++ b/src/pkg/math/const.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The math package provides basic constants and mathematical functions.
+// Package math provides basic constants and mathematical functions.
 package math
 
 // Mathematical constants.
diff --git a/src/pkg/mime/mediatype.go b/src/pkg/mime/mediatype.go
index eb629aa..f28ff3e 100644
--- a/src/pkg/mime/mediatype.go
+++ b/src/pkg/mime/mediatype.go
@@ -6,10 +6,30 @@ package mime
 
 import (
 	"bytes"
+	"fmt"
+	"os"
 	"strings"
 	"unicode"
 )
 
+func validMediaTypeOrDisposition(s string) bool {
+	typ, rest := consumeToken(s)
+	if typ == "" {
+		return false
+	}
+	if rest == "" {
+		return true
+	}
+	if !strings.HasPrefix(rest, "/") {
+		return false
+	}
+	subtype, rest := consumeToken(rest[1:])
+	if subtype == "" {
+		return false
+	}
+	return rest == ""
+}
+
 // ParseMediaType parses a media type value and any optional
 // parameters, per RFC 1531.  Media types are the values in
 // Content-Type and Content-Disposition headers (RFC 2183).  On
@@ -22,25 +42,112 @@ func ParseMediaType(v string) (mediatype string, params map[string]string) {
 		i = len(v)
 	}
 	mediatype = strings.TrimSpace(strings.ToLower(v[0:i]))
+	if !validMediaTypeOrDisposition(mediatype) {
+		return "", nil
+	}
+
 	params = make(map[string]string)
 
+	// Map of base parameter name -> parameter name -> value
+	// for parameters containing a '*' character.
+	// Lazily initialized.
+	var continuation map[string]map[string]string
+
 	v = v[i:]
 	for len(v) > 0 {
 		v = strings.TrimLeftFunc(v, unicode.IsSpace)
 		if len(v) == 0 {
-			return
+			break
 		}
 		key, value, rest := consumeMediaParam(v)
 		if key == "" {
+			if strings.TrimSpace(rest) == ";" {
+				// Ignore trailing semicolons.
+				// Not an error.
+				return
+			}
 			// Parse error.
 			return "", nil
 		}
-		params[key] = value
+
+		pmap := params
+		if idx := strings.Index(key, "*"); idx != -1 {
+			baseName := key[:idx]
+			if continuation == nil {
+				continuation = make(map[string]map[string]string)
+			}
+			var ok bool
+			if pmap, ok = continuation[baseName]; !ok {
+				continuation[baseName] = make(map[string]string)
+				pmap = continuation[baseName]
+			}
+		}
+		if _, exists := pmap[key]; exists {
+			// Duplicate parameter name is bogus.
+			return "", nil
+		}
+		pmap[key] = value
 		v = rest
 	}
+
+	// Stitch together any continuations or things with stars
+	// (i.e. RFC 2231 things with stars: "foo*0" or "foo*")
+	var buf bytes.Buffer
+	for key, pieceMap := range continuation {
+		singlePartKey := key + "*"
+		if v, ok := pieceMap[singlePartKey]; ok {
+			decv := decode2231Enc(v)
+			params[key] = decv
+			continue
+		}
+
+		buf.Reset()
+		valid := false
+		for n := 0; ; n++ {
+			simplePart := fmt.Sprintf("%s*%d", key, n)
+			if v, ok := pieceMap[simplePart]; ok {
+				valid = true
+				buf.WriteString(v)
+				continue
+			}
+			encodedPart := simplePart + "*"
+			if v, ok := pieceMap[encodedPart]; ok {
+				valid = true
+				if n == 0 {
+					buf.WriteString(decode2231Enc(v))
+				} else {
+					decv, _ := percentHexUnescape(v)
+					buf.WriteString(decv)
+				}
+			} else {
+				break
+			}
+		}
+		if valid {
+			params[key] = buf.String()
+		}
+	}
+
 	return
 }
 
+func decode2231Enc(v string) string {
+	sv := strings.Split(v, "'", 3)
+	if len(sv) != 3 {
+		return ""
+	}
+	// TODO: ignoring lang in sv[1] for now. If anybody needs it we'll
+	// need to decide how to expose it in the API. But I'm not sure
+	// anybody uses it in practice.
+	charset := strings.ToLower(sv[0])
+	if charset != "us-ascii" && charset != "utf-8" {
+		// TODO: unsupported encoding
+		return ""
+	}
+	encv, _ := percentHexUnescape(sv[2])
+	return encv
+}
+
 func isNotTokenChar(rune int) bool {
 	return !IsTokenChar(rune)
 }
@@ -66,10 +173,12 @@ func consumeToken(v string) (token, rest string) {
 // quoted-string) and the rest of the string.  On failure, returns
 // ("", v).
 func consumeValue(v string) (value, rest string) {
-	if !strings.HasPrefix(v, `"`) {
+	if !strings.HasPrefix(v, `"`) && !strings.HasPrefix(v, `'`) {
 		return consumeToken(v)
 	}
 
+	leadQuote := int(v[0])
+
 	// parse a quoted-string
 	rest = v[1:] // consume the leading quote
 	buffer := new(bytes.Buffer)
@@ -78,17 +187,14 @@ func consumeValue(v string) (value, rest string) {
 	for idx, rune = range rest {
 		switch {
 		case nextIsLiteral:
-			if rune >= 0x80 {
-				return "", v
-			}
 			buffer.WriteRune(rune)
 			nextIsLiteral = false
-		case rune == '"':
+		case rune == leadQuote:
 			return buffer.String(), rest[idx+1:]
-		case IsQText(rune):
-			buffer.WriteRune(rune)
 		case rune == '\\':
 			nextIsLiteral = true
+		case rune != '\r' && rune != '\n':
+			buffer.WriteRune(rune)
 		default:
 			return "", v
 		}
@@ -108,13 +214,79 @@ func consumeMediaParam(v string) (param, value, rest string) {
 	if param == "" {
 		return "", "", v
 	}
+
+	rest = strings.TrimLeftFunc(rest, unicode.IsSpace)
 	if !strings.HasPrefix(rest, "=") {
 		return "", "", v
 	}
 	rest = rest[1:] // consume equals sign
+	rest = strings.TrimLeftFunc(rest, unicode.IsSpace)
 	value, rest = consumeValue(rest)
 	if value == "" {
 		return "", "", v
 	}
 	return param, value, rest
 }
+
+func percentHexUnescape(s string) (string, os.Error) {
+	// Count %, check that they're well-formed.
+	percents := 0
+	for i := 0; i < len(s); {
+		if s[i] != '%' {
+			i++
+			continue
+		}
+		percents++
+		if i+2 >= len(s) || !ishex(s[i+1]) || !ishex(s[i+2]) {
+			s = s[i:]
+			if len(s) > 3 {
+				s = s[0:3]
+			}
+			return "", fmt.Errorf("mime: bogus characters after %%: %q", s)
+		}
+		i += 3
+	}
+	if percents == 0 {
+		return s, nil
+	}
+
+	t := make([]byte, len(s)-2*percents)
+	j := 0
+	for i := 0; i < len(s); {
+		switch s[i] {
+		case '%':
+			t[j] = unhex(s[i+1])<<4 | unhex(s[i+2])
+			j++
+			i += 3
+		default:
+			t[j] = s[i]
+			j++
+			i++
+		}
+	}
+	return string(t), nil
+}
+
+func ishex(c byte) bool {
+	switch {
+	case '0' <= c && c <= '9':
+		return true
+	case 'a' <= c && c <= 'f':
+		return true
+	case 'A' <= c && c <= 'F':
+		return true
+	}
+	return false
+}
+
+func unhex(c byte) byte {
+	switch {
+	case '0' <= c && c <= '9':
+		return c - '0'
+	case 'a' <= c && c <= 'f':
+		return c - 'a' + 10
+	case 'A' <= c && c <= 'F':
+		return c - 'A' + 10
+	}
+	return 0
+}
diff --git a/src/pkg/mime/mediatype_test.go b/src/pkg/mime/mediatype_test.go
index 4891e89..454ddd0 100644
--- a/src/pkg/mime/mediatype_test.go
+++ b/src/pkg/mime/mediatype_test.go
@@ -5,6 +5,7 @@
 package mime
 
 import (
+	"reflect"
 	"testing"
 )
 
@@ -85,23 +86,152 @@ func TestConsumeMediaParam(t *testing.T) {
 	}
 }
 
+type mediaTypeTest struct {
+	in string
+	t  string
+	p  map[string]string
+}
+
 func TestParseMediaType(t *testing.T) {
-	tests := [...]string{
-		`form-data; name="foo"`,
-		` form-data ; name=foo`,
-		`FORM-DATA;name="foo"`,
-		` FORM-DATA ; name="foo"`,
-		` FORM-DATA ; name="foo"`,
-		`form-data; key=value;  blah="value";name="foo" `,
+	// Convenience map initializer
+	m := func(s ...string) map[string]string {
+		sm := make(map[string]string)
+		for i := 0; i < len(s); i += 2 {
+			sm[s[i]] = s[i+1]
+		}
+		return sm
+	}
+
+	nameFoo := map[string]string{"name": "foo"}
+	tests := []mediaTypeTest{
+		{`form-data; name="foo"`, "form-data", nameFoo},
+		{` form-data ; name=foo`, "form-data", nameFoo},
+		{`FORM-DATA;name="foo"`, "form-data", nameFoo},
+		{` FORM-DATA ; name="foo"`, "form-data", nameFoo},
+		{` FORM-DATA ; name="foo"`, "form-data", nameFoo},
+
+		{`form-data; key=value;  blah="value";name="foo" `,
+			"form-data",
+			m("key", "value", "blah", "value", "name", "foo")},
+
+		{`foo; key=val1; key=the-key-appears-again-which-is-bogus`,
+			"", m()},
+
+		// From RFC 2231:
+		{`application/x-stuff; title*=us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A`,
+			"application/x-stuff",
+			m("title", "This is ***fun***")},
+
+		{`message/external-body; access-type=URL; ` +
+			`URL*0="ftp://";` +
+			`URL*1="cs.utk.edu/pub/moore/bulk-mailer/bulk-mailer.tar"`,
+			"message/external-body",
+			m("access-type", "URL",
+				"URL", "ftp://cs.utk.edu/pub/moore/bulk-mailer/bulk-mailer.tar")},
+
+		{`application/x-stuff; ` +
+			`title*0*=us-ascii'en'This%20is%20even%20more%20; ` +
+			`title*1*=%2A%2A%2Afun%2A%2A%2A%20; ` +
+			`title*2="isn't it!"`,
+			"application/x-stuff",
+			m("title", "This is even more ***fun*** isn't it!")},
+
+		// Tests from http://greenbytes.de/tech/tc2231/
+		// TODO(bradfitz): add the rest of the tests from that site.
+		{`attachment; filename="f\oo.html"`,
+			"attachment",
+			m("filename", "foo.html")},
+		{`attachment; filename="\"quoting\" tested.html"`,
+			"attachment",
+			m("filename", `"quoting" tested.html`)},
+		{`attachment; filename="Here's a semicolon;.html"`,
+			"attachment",
+			m("filename", "Here's a semicolon;.html")},
+		{`attachment; foo="\"\\";filename="foo.html"`,
+			"attachment",
+			m("foo", "\"\\", "filename", "foo.html")},
+		{`attachment; filename=foo.html`,
+			"attachment",
+			m("filename", "foo.html")},
+		{`attachment; filename=foo.html ;`,
+			"attachment",
+			m("filename", "foo.html")},
+		{`attachment; filename='foo.html'`,
+			"attachment",
+			m("filename", "foo.html")},
+		{`attachment; filename="foo-%41.html"`,
+			"attachment",
+			m("filename", "foo-%41.html")},
+		{`attachment; filename="foo-%\41.html"`,
+			"attachment",
+			m("filename", "foo-%41.html")},
+		{`filename=foo.html`,
+			"", m()},
+		{`x=y; filename=foo.html`,
+			"", m()},
+		{`"foo; filename=bar;baz"; filename=qux`,
+			"", m()},
+		{`inline; attachment; filename=foo.html`,
+			"", m()},
+		{`attachment; filename="foo.html".txt`,
+			"", m()},
+		{`attachment; filename="bar`,
+			"", m()},
+		{`attachment; creation-date="Wed, 12 Feb 1997 16:29:51 -0500"`,
+			"attachment",
+			m("creation-date", "Wed, 12 Feb 1997 16:29:51 -0500")},
+		{`foobar`, "foobar", m()},
+		{`attachment; filename* =UTF-8''foo-%c3%a4.html`,
+			"attachment",
+			m("filename", "foo-ä.html")},
+		{`attachment; filename*=UTF-8''A-%2541.html`,
+			"attachment",
+			m("filename", "A-%41.html")},
+		{`attachment; filename*0="foo."; filename*1="html"`,
+			"attachment",
+			m("filename", "foo.html")},
+		{`attachment; filename*0*=UTF-8''foo-%c3%a4; filename*1=".html"`,
+			"attachment",
+			m("filename", "foo-ä.html")},
+		{`attachment; filename*0="foo"; filename*01="bar"`,
+			"attachment",
+			m("filename", "foo")},
+		{`attachment; filename*0="foo"; filename*2="bar"`,
+			"attachment",
+			m("filename", "foo")},
+		{`attachment; filename*1="foo"; filename*2="bar"`,
+			"attachment", m()},
+		{`attachment; filename*1="bar"; filename*0="foo"`,
+			"attachment",
+			m("filename", "foobar")},
+		{`attachment; filename="foo-ae.html"; filename*=UTF-8''foo-%c3%a4.html`,
+			"attachment",
+			m("filename", "foo-ä.html")},
+		{`attachment; filename*=UTF-8''foo-%c3%a4.html; filename="foo-ae.html"`,
+			"attachment",
+			m("filename", "foo-ä.html")},
+
+		// Browsers also just send UTF-8 directly without RFC 2231,
+		// at least when the source page is served with UTF-8.
+		{`form-data; firstname="Брэд"; lastname="Фицпатрик"`,
+			"form-data",
+			m("firstname", "Брэд", "lastname", "Фицпатрик")},
 	}
 	for _, test := range tests {
-		mt, params := ParseMediaType(test)
-		if mt != "form-data" {
-			t.Errorf("expected type form-data for %s, got [%s]", test, mt)
+		mt, params := ParseMediaType(test.in)
+		if g, e := mt, test.t; g != e {
+			t.Errorf("for input %q, expected type %q, got %q",
+				test.in, e, g)
+			continue
+		}
+		if len(params) == 0 && len(test.p) == 0 {
 			continue
 		}
-		if params["name"] != "foo" {
-			t.Errorf("expected name=foo for %s", test)
+		if !reflect.DeepEqual(params, test.p) {
+			t.Errorf("for input %q, wrong params.\n"+
+				"expected: %#v\n"+
+				"     got: %#v",
+				test.in, test.p, params)
 		}
 	}
 }
diff --git a/src/pkg/mime/multipart/Makefile b/src/pkg/mime/multipart/Makefile
index 5a7b98d..5051f0d 100644
--- a/src/pkg/mime/multipart/Makefile
+++ b/src/pkg/mime/multipart/Makefile
@@ -6,6 +6,7 @@ include ../../../Make.inc
 
 TARG=mime/multipart
 GOFILES=\
+	formdata.go\
 	multipart.go\
 
 include ../../../Make.pkg
diff --git a/src/pkg/mime/multipart/formdata.go b/src/pkg/mime/multipart/formdata.go
new file mode 100644
index 0000000..2879385
--- /dev/null
+++ b/src/pkg/mime/multipart/formdata.go
@@ -0,0 +1,169 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package multipart
+
+import (
+	"bytes"
+	"io"
+	"io/ioutil"
+	"net/textproto"
+	"os"
+)
+
+// TODO(adg,bradfitz): find a way to unify the DoS-prevention strategy here
+// with that of the http package's ParseForm.
+
+// ReadForm parses an entire multipart message whose parts have
+// a Content-Disposition of "form-data".
+// It stores up to maxMemory bytes of the file parts in memory
+// and the remainder on disk in temporary files.
+func (r *multiReader) ReadForm(maxMemory int64) (f *Form, err os.Error) {
+	form := &Form{make(map[string][]string), make(map[string][]*FileHeader)}
+	defer func() {
+		if err != nil {
+			form.RemoveAll()
+		}
+	}()
+
+	maxValueBytes := int64(10 << 20) // 10 MB is a lot of text.
+	for {
+		p, err := r.NextPart()
+		if err != nil {
+			return nil, err
+		}
+		if p == nil {
+			break
+		}
+
+		name := p.FormName()
+		if name == "" {
+			continue
+		}
+		var filename string
+		if p.dispositionParams != nil {
+			filename = p.dispositionParams["filename"]
+		}
+
+		var b bytes.Buffer
+
+		if filename == "" {
+			// value, store as string in memory
+			n, err := io.Copyn(&b, p, maxValueBytes)
+			if err != nil && err != os.EOF {
+				return nil, err
+			}
+			maxValueBytes -= n
+			if maxValueBytes == 0 {
+				return nil, os.NewError("multipart: message too large")
+			}
+			form.Value[name] = append(form.Value[name], b.String())
+			continue
+		}
+
+		// file, store in memory or on disk
+		fh := &FileHeader{
+			Filename: filename,
+			Header:   p.Header,
+		}
+		n, err := io.Copyn(&b, p, maxMemory+1)
+		if err != nil && err != os.EOF {
+			return nil, err
+		}
+		if n > maxMemory {
+			// too big, write to disk and flush buffer
+			file, err := ioutil.TempFile("", "multipart-")
+			if err != nil {
+				return nil, err
+			}
+			defer file.Close()
+			_, err = io.Copy(file, io.MultiReader(&b, p))
+			if err != nil {
+				os.Remove(file.Name())
+				return nil, err
+			}
+			fh.tmpfile = file.Name()
+		} else {
+			fh.content = b.Bytes()
+			maxMemory -= n
+		}
+		form.File[name] = append(form.File[name], fh)
+	}
+
+	return form, nil
+}
+
+// Form is a parsed multipart form.
+// Its File parts are stored either in memory or on disk,
+// and are accessible via the *FileHeader's Open method.
+// Its Value parts are stored as strings.
+// Both are keyed by field name.
+type Form struct {
+	Value map[string][]string
+	File  map[string][]*FileHeader
+}
+
+// RemoveAll removes any temporary files associated with a Form.
+func (f *Form) RemoveAll() os.Error {
+	var err os.Error
+	for _, fhs := range f.File {
+		for _, fh := range fhs {
+			if fh.tmpfile != "" {
+				e := os.Remove(fh.tmpfile)
+				if e != nil && err == nil {
+					err = e
+				}
+			}
+		}
+	}
+	return err
+}
+
+// A FileHeader describes a file part of a multipart request.
+type FileHeader struct {
+	Filename string
+	Header   textproto.MIMEHeader
+
+	content []byte
+	tmpfile string
+}
+
+// Open opens and returns the FileHeader's associated File.
+func (fh *FileHeader) Open() (File, os.Error) {
+	if b := fh.content; b != nil {
+		r := io.NewSectionReader(sliceReaderAt(b), 0, int64(len(b)))
+		return sectionReadCloser{r}, nil
+	}
+	return os.Open(fh.tmpfile)
+}
+
+// File is an interface to access the file part of a multipart message.
+// Its contents may be either stored in memory or on disk.
+// If stored on disk, the File's underlying concrete type will be an *os.File.
+type File interface {
+	io.Reader
+	io.ReaderAt
+	io.Seeker
+	io.Closer
+}
+
+// helper types to turn a []byte into a File
+
+type sectionReadCloser struct {
+	*io.SectionReader
+}
+
+func (rc sectionReadCloser) Close() os.Error {
+	return nil
+}
+
+type sliceReaderAt []byte
+
+func (r sliceReaderAt) ReadAt(b []byte, off int64) (int, os.Error) {
+	if int(off) >= len(r) || off < 0 {
+		return 0, os.EINVAL
+	}
+	n := copy(b, r[int(off):])
+	return n, nil
+}
diff --git a/src/pkg/mime/multipart/formdata_test.go b/src/pkg/mime/multipart/formdata_test.go
new file mode 100644
index 0000000..b56e2a4
--- /dev/null
+++ b/src/pkg/mime/multipart/formdata_test.go
@@ -0,0 +1,87 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package multipart
+
+import (
+	"bytes"
+	"io"
+	"os"
+	"regexp"
+	"testing"
+)
+
+func TestReadForm(t *testing.T) {
+	testBody := regexp.MustCompile("\n").ReplaceAllString(message, "\r\n")
+	b := bytes.NewBufferString(testBody)
+	r := NewReader(b, boundary)
+	f, err := r.ReadForm(25)
+	if err != nil {
+		t.Fatal("ReadForm:", err)
+	}
+	defer f.RemoveAll()
+	if g, e := f.Value["texta"][0], textaValue; g != e {
+		t.Errorf("texta value = %q, want %q", g, e)
+	}
+	if g, e := f.Value["textb"][0], textbValue; g != e {
+		t.Errorf("texta value = %q, want %q", g, e)
+	}
+	fd := testFile(t, f.File["filea"][0], "filea.txt", fileaContents)
+	if _, ok := fd.(*os.File); ok {
+		t.Error("file is *os.File, should not be")
+	}
+	fd = testFile(t, f.File["fileb"][0], "fileb.txt", filebContents)
+	if _, ok := fd.(*os.File); !ok {
+		t.Error("file has unexpected underlying type %T", fd)
+	}
+}
+
+func testFile(t *testing.T, fh *FileHeader, efn, econtent string) File {
+	if fh.Filename != efn {
+		t.Errorf("filename = %q, want %q", fh.Filename, efn)
+	}
+	f, err := fh.Open()
+	if err != nil {
+		t.Fatal("opening file:", err)
+	}
+	b := new(bytes.Buffer)
+	_, err = io.Copy(b, f)
+	if err != nil {
+		t.Fatal("copying contents:", err)
+	}
+	if g := b.String(); g != econtent {
+		t.Errorf("contents = %q, want %q", g, econtent)
+	}
+	return f
+}
+
+const (
+	fileaContents = "This is a test file."
+	filebContents = "Another test file."
+	textaValue    = "foo"
+	textbValue    = "bar"
+	boundary      = `MyBoundary`
+)
+
+const message = `
+--MyBoundary
+Content-Disposition: form-data; name="filea"; filename="filea.txt"
+Content-Type: text/plain
+
+` + fileaContents + `
+--MyBoundary
+Content-Disposition: form-data; name="fileb"; filename="fileb.txt"
+Content-Type: text/plain
+
+` + filebContents + `
+--MyBoundary
+Content-Disposition: form-data; name="texta"
+
+` + textaValue + `
+--MyBoundary
+Content-Disposition: form-data; name="textb"
+
+` + textbValue + `
+--MyBoundary--
+`
diff --git a/src/pkg/mime/multipart/multipart.go b/src/pkg/mime/multipart/multipart.go
index 0a65a44..e0b747c 100644
--- a/src/pkg/mime/multipart/multipart.go
+++ b/src/pkg/mime/multipart/multipart.go
@@ -16,6 +16,7 @@ import (
 	"bufio"
 	"bytes"
 	"io"
+	"io/ioutil"
 	"mime"
 	"net/textproto"
 	"os"
@@ -34,6 +35,12 @@ type Reader interface {
 	// reports errors, or on truncated or otherwise malformed
 	// input.
 	NextPart() (*Part, os.Error)
+
+	// ReadForm parses an entire multipart message whose parts have
+	// a Content-Disposition of "form-data".
+	// It stores up to maxMemory bytes of the file parts in memory
+	// and the remainder on disk in temporary files.
+	ReadForm(maxMemory int64) (*Form, os.Error)
 }
 
 // A Part represents a single part in a multipart body.
@@ -45,6 +52,8 @@ type Part struct {
 
 	buffer *bytes.Buffer
 	mr     *multiReader
+
+	dispositionParams map[string]string
 }
 
 // FormName returns the name parameter if p has a Content-Disposition
@@ -52,15 +61,19 @@ type Part struct {
 func (p *Part) FormName() string {
 	// See http://tools.ietf.org/html/rfc2183 section 2 for EBNF
 	// of Content-Disposition value format.
+	if p.dispositionParams != nil {
+		return p.dispositionParams["name"]
+	}
 	v := p.Header.Get("Content-Disposition")
 	if v == "" {
 		return ""
 	}
-	d, params := mime.ParseMediaType(v)
-	if d != "form-data" {
+	if d, params := mime.ParseMediaType(v); d != "form-data" {
 		return ""
+	} else {
+		p.dispositionParams = params
 	}
-	return params["name"]
+	return p.dispositionParams["name"]
 }
 
 // NewReader creates a new multipart Reader reading from r using the
@@ -76,14 +89,6 @@ func NewReader(reader io.Reader, boundary string) Reader {
 
 // Implementation ....
 
-type devNullWriter bool
-
-func (*devNullWriter) Write(p []byte) (n int, err os.Error) {
-	return len(p), nil
-}
-
-var devNull = devNullWriter(false)
-
 func newPart(mr *multiReader) (bp *Part, err os.Error) {
 	bp = new(Part)
 	bp.Header = make(map[string][]string)
@@ -97,10 +102,11 @@ func newPart(mr *multiReader) (bp *Part, err os.Error) {
 
 func (bp *Part) populateHeaders() os.Error {
 	for {
-		line, err := bp.mr.bufReader.ReadString('\n')
+		lineBytes, err := bp.mr.bufReader.ReadSlice('\n')
 		if err != nil {
 			return err
 		}
+		line := string(lineBytes)
 		if line == "\n" || line == "\r\n" {
 			return nil
 		}
@@ -157,7 +163,7 @@ func (bp *Part) Read(p []byte) (n int, err os.Error) {
 }
 
 func (bp *Part) Close() os.Error {
-	io.Copy(&devNull, bp)
+	io.Copy(ioutil.Discard, bp)
 	return nil
 }
 
@@ -179,11 +185,12 @@ func (mr *multiReader) eof() bool {
 }
 
 func (mr *multiReader) readLine() bool {
-	line, err := mr.bufReader.ReadString('\n')
+	lineBytes, err := mr.bufReader.ReadSlice('\n')
 	if err != nil {
 		// TODO: care about err being EOF or not?
 		return false
 	}
+	line := string(lineBytes)
 	mr.bufferedLine = &line
 	return true
 }
diff --git a/src/pkg/mime/multipart/multipart_test.go b/src/pkg/mime/multipart/multipart_test.go
index 1f3d32d..f8f10f3 100644
--- a/src/pkg/mime/multipart/multipart_test.go
+++ b/src/pkg/mime/multipart/multipart_test.go
@@ -9,6 +9,7 @@ import (
 	"fmt"
 	"io"
 	"json"
+	"os"
 	"regexp"
 	"strings"
 	"testing"
@@ -205,3 +206,34 @@ func TestVariousTextLineEndings(t *testing.T) {
 
 	}
 }
+
+type maliciousReader struct {
+	t *testing.T
+	n int
+}
+
+const maxReadThreshold = 1 << 20
+
+func (mr *maliciousReader) Read(b []byte) (n int, err os.Error) {
+	mr.n += len(b)
+	if mr.n >= maxReadThreshold {
+		mr.t.Fatal("too much was read")
+		return 0, os.EOF
+	}
+	return len(b), nil
+}
+
+func TestLineLimit(t *testing.T) {
+	mr := &maliciousReader{t: t}
+	r := NewReader(mr, "fooBoundary")
+	part, err := r.NextPart()
+	if part != nil {
+		t.Errorf("unexpected part read")
+	}
+	if err == nil {
+		t.Errorf("expected an error")
+	}
+	if mr.n >= maxReadThreshold {
+		t.Errorf("expected to read < %d bytes; read %d", maxReadThreshold, mr.n)
+	}
+}
diff --git a/src/pkg/mime/type.go b/src/pkg/mime/type.go
index 6fe0ed5..8c43b81 100644
--- a/src/pkg/mime/type.go
+++ b/src/pkg/mime/type.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The mime package implements parts of the MIME spec.
+// Package mime implements parts of the MIME spec.
 package mime
 
 import (
diff --git a/src/pkg/net/Makefile b/src/pkg/net/Makefile
index 7ce6502..221871c 100644
--- a/src/pkg/net/Makefile
+++ b/src/pkg/net/Makefile
@@ -6,7 +6,6 @@ include ../../Make.inc
 
 TARG=net
 GOFILES=\
-	cgo_stub.go\
 	dial.go\
 	dnsmsg.go\
 	fd_$(GOOS).go\
@@ -31,6 +30,10 @@ GOFILES_freebsd=\
 	dnsclient.go\
 	port.go\
 
+CGOFILES_freebsd=\
+	cgo_bsd.go\
+	cgo_unix.go\
+
 GOFILES_darwin=\
 	newpollserver.go\
 	fd.go\
@@ -38,6 +41,10 @@ GOFILES_darwin=\
 	dnsconfig.go\
 	dnsclient.go\
 	port.go\
+
+CGOFILES_darwin=\
+	cgo_bsd.go\
+	cgo_unix.go\
 	
 GOFILES_linux=\
 	newpollserver.go\
@@ -47,10 +54,23 @@ GOFILES_linux=\
 	dnsclient.go\
 	port.go\
 
+ifeq ($(GOARCH),arm)
+# ARM has no cgo, so use the stubs.
+GOFILES_linux+=cgo_stub.go
+else
+CGOFILES_linux=\
+	cgo_linux.go\
+	cgo_unix.go
+endif
+
 GOFILES_windows=\
+	cgo_stub.go\
 	resolv_windows.go\
 	file_windows.go\
 
 GOFILES+=$(GOFILES_$(GOOS))
+ifneq ($(CGOFILES_$(GOOS)),)
+CGOFILES+=$(CGOFILES_$(GOOS))
+endif
 
 include ../../Make.pkg
diff --git a/src/pkg/net/cgo_bsd.go b/src/pkg/net/cgo_bsd.go
new file mode 100644
index 0000000..4984df4
--- /dev/null
+++ b/src/pkg/net/cgo_bsd.go
@@ -0,0 +1,14 @@
+// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+/*
+#include <netdb.h>
+*/
+import "C"
+
+func cgoAddrInfoMask() C.int {
+	return C.AI_MASK
+}
diff --git a/src/pkg/net/cgo_linux.go b/src/pkg/net/cgo_linux.go
new file mode 100644
index 0000000..8d4413d
--- /dev/null
+++ b/src/pkg/net/cgo_linux.go
@@ -0,0 +1,14 @@
+// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+/*
+#include <netdb.h>
+*/
+import "C"
+
+func cgoAddrInfoMask() C.int {
+	return C.AI_CANONNAME | C.AI_V4MAPPED | C.AI_ALL
+}
diff --git a/src/pkg/net/cgo_stub.go b/src/pkg/net/cgo_stub.go
index e28f662..c6277cb 100644
--- a/src/pkg/net/cgo_stub.go
+++ b/src/pkg/net/cgo_stub.go
@@ -19,3 +19,7 @@ func cgoLookupPort(network, service string) (port int, err os.Error, completed b
 func cgoLookupIP(name string) (addrs []IP, err os.Error, completed bool) {
 	return nil, nil, false
 }
+
+func cgoLookupCNAME(name string) (cname string, err os.Error, completed bool) {
+	return "", nil, false
+}
diff --git a/src/pkg/net/cgo_unix.go b/src/pkg/net/cgo_unix.go
new file mode 100644
index 0000000..a3711d6
--- /dev/null
+++ b/src/pkg/net/cgo_unix.go
@@ -0,0 +1,148 @@
+// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+/*
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+*/
+import "C"
+
+import (
+	"os"
+	"syscall"
+	"unsafe"
+)
+
+func cgoLookupHost(name string) (addrs []string, err os.Error, completed bool) {
+	ip, err, completed := cgoLookupIP(name)
+	for _, p := range ip {
+		addrs = append(addrs, p.String())
+	}
+	return
+}
+
+func cgoLookupPort(net, service string) (port int, err os.Error, completed bool) {
+	var res *C.struct_addrinfo
+	var hints C.struct_addrinfo
+
+	switch net {
+	case "":
+		// no hints
+	case "tcp", "tcp4", "tcp6":
+		hints.ai_socktype = C.SOCK_STREAM
+		hints.ai_protocol = C.IPPROTO_TCP
+	case "udp", "udp4", "udp6":
+		hints.ai_socktype = C.SOCK_DGRAM
+		hints.ai_protocol = C.IPPROTO_UDP
+	default:
+		return 0, UnknownNetworkError(net), true
+	}
+	if len(net) >= 4 {
+		switch net[3] {
+		case '4':
+			hints.ai_family = C.AF_INET
+		case '6':
+			hints.ai_family = C.AF_INET6
+		}
+	}
+
+	s := C.CString(service)
+	defer C.free(unsafe.Pointer(s))
+	if C.getaddrinfo(nil, s, &hints, &res) == 0 {
+		defer C.freeaddrinfo(res)
+		for r := res; r != nil; r = r.ai_next {
+			switch r.ai_family {
+			default:
+				continue
+			case C.AF_INET:
+				sa := (*syscall.RawSockaddrInet4)(unsafe.Pointer(r.ai_addr))
+				p := (*[2]byte)(unsafe.Pointer(&sa.Port))
+				return int(p[0])<<8 | int(p[1]), nil, true
+			case C.AF_INET6:
+				sa := (*syscall.RawSockaddrInet6)(unsafe.Pointer(r.ai_addr))
+				p := (*[2]byte)(unsafe.Pointer(&sa.Port))
+				return int(p[0])<<8 | int(p[1]), nil, true
+			}
+		}
+	}
+	return 0, &AddrError{"unknown port", net + "/" + service}, true
+}
+
+func cgoLookupIPCNAME(name string) (addrs []IP, cname string, err os.Error, completed bool) {
+	var res *C.struct_addrinfo
+	var hints C.struct_addrinfo
+
+	// NOTE(rsc): In theory there are approximately balanced
+	// arguments for and against including AI_ADDRCONFIG
+	// in the flags (it includes IPv4 results only on IPv4 systems,
+	// and similarly for IPv6), but in practice setting it causes
+	// getaddrinfo to return the wrong canonical name on Linux.
+	// So definitely leave it out.
+	hints.ai_flags = (C.AI_ALL | C.AI_V4MAPPED | C.AI_CANONNAME) & cgoAddrInfoMask()
+
+	h := C.CString(name)
+	defer C.free(unsafe.Pointer(h))
+	gerrno, err := C.getaddrinfo(h, nil, &hints, &res)
+	if gerrno != 0 {
+		var str string
+		if gerrno == C.EAI_NONAME {
+			str = noSuchHost
+		} else if gerrno == C.EAI_SYSTEM {
+			str = err.String()
+		} else {
+			str = C.GoString(C.gai_strerror(gerrno))
+		}
+		return nil, "", &DNSError{Error: str, Name: name}, true
+	}
+	defer C.freeaddrinfo(res)
+	if res != nil {
+		cname = C.GoString(res.ai_canonname)
+		if cname == "" {
+			cname = name
+		}
+		if len(cname) > 0 && cname[len(cname)-1] != '.' {
+			cname += "."
+		}
+	}
+	for r := res; r != nil; r = r.ai_next {
+		// Everything comes back twice, once for UDP and once for TCP.
+		if r.ai_socktype != C.SOCK_STREAM {
+			continue
+		}
+		switch r.ai_family {
+		default:
+			continue
+		case C.AF_INET:
+			sa := (*syscall.RawSockaddrInet4)(unsafe.Pointer(r.ai_addr))
+			addrs = append(addrs, copyIP(sa.Addr[:]))
+		case C.AF_INET6:
+			sa := (*syscall.RawSockaddrInet6)(unsafe.Pointer(r.ai_addr))
+			addrs = append(addrs, copyIP(sa.Addr[:]))
+		}
+	}
+	return addrs, cname, nil, true
+}
+
+func cgoLookupIP(name string) (addrs []IP, err os.Error, completed bool) {
+	addrs, _, err, completed = cgoLookupIPCNAME(name)
+	return
+}
+
+func cgoLookupCNAME(name string) (cname string, err os.Error, completed bool) {
+	_, cname, err, completed = cgoLookupIPCNAME(name)
+	return
+}
+
+func copyIP(x IP) IP {
+	y := make(IP, len(x))
+	copy(y, x)
+	return y
+}
diff --git a/src/pkg/net/dial.go b/src/pkg/net/dial.go
index 66cb09b..16896b4 100644
--- a/src/pkg/net/dial.go
+++ b/src/pkg/net/dial.go
@@ -30,7 +30,7 @@ func Dial(net, addr string) (c Conn, err os.Error) {
 	switch net {
 	case "tcp", "tcp4", "tcp6":
 		var ra *TCPAddr
-		if ra, err = ResolveTCPAddr(raddr); err != nil {
+		if ra, err = ResolveTCPAddr(net, raddr); err != nil {
 			goto Error
 		}
 		c, err := DialTCP(net, nil, ra)
@@ -40,7 +40,7 @@ func Dial(net, addr string) (c Conn, err os.Error) {
 		return c, nil
 	case "udp", "udp4", "udp6":
 		var ra *UDPAddr
-		if ra, err = ResolveUDPAddr(raddr); err != nil {
+		if ra, err = ResolveUDPAddr(net, raddr); err != nil {
 			goto Error
 		}
 		c, err := DialUDP(net, nil, ra)
@@ -83,7 +83,7 @@ func Listen(net, laddr string) (l Listener, err os.Error) {
 	case "tcp", "tcp4", "tcp6":
 		var la *TCPAddr
 		if laddr != "" {
-			if la, err = ResolveTCPAddr(laddr); err != nil {
+			if la, err = ResolveTCPAddr(net, laddr); err != nil {
 				return nil, err
 			}
 		}
@@ -116,7 +116,7 @@ func ListenPacket(net, laddr string) (c PacketConn, err os.Error) {
 	case "udp", "udp4", "udp6":
 		var la *UDPAddr
 		if laddr != "" {
-			if la, err = ResolveUDPAddr(laddr); err != nil {
+			if la, err = ResolveUDPAddr(net, laddr); err != nil {
 				return nil, err
 			}
 		}
diff --git a/src/pkg/net/dialgoogle_test.go b/src/pkg/net/dialgoogle_test.go
index 9a9c02e..c25089b 100644
--- a/src/pkg/net/dialgoogle_test.go
+++ b/src/pkg/net/dialgoogle_test.go
@@ -56,29 +56,44 @@ var googleaddrs = []string{
 }
 
 func TestLookupCNAME(t *testing.T) {
+	if testing.Short() {
+		// Don't use external network.
+		t.Logf("skipping external network test during -short")
+		return
+	}
 	cname, err := LookupCNAME("www.google.com")
-	if cname != "www.l.google.com." || err != nil {
-		t.Errorf(`LookupCNAME("www.google.com.") = %q, %v, want "www.l.google.com.", nil`, cname, err)
+	if !strings.HasSuffix(cname, ".l.google.com.") || err != nil {
+		t.Errorf(`LookupCNAME("www.google.com.") = %q, %v, want "*.l.google.com.", nil`, cname, err)
 	}
 }
 
 func TestDialGoogle(t *testing.T) {
+	if testing.Short() {
+		// Don't use external network.
+		t.Logf("skipping external network test during -short")
+		return
+	}
 	// If no ipv6 tunnel, don't try the last address.
 	if !*ipv6 {
 		googleaddrs[len(googleaddrs)-1] = ""
 	}
 
-	// Insert an actual IP address for google.com
+	// Insert an actual IPv4 address for google.com
 	// into the table.
-
 	addrs, err := LookupIP("www.google.com")
 	if err != nil {
 		t.Fatalf("lookup www.google.com: %v", err)
 	}
-	if len(addrs) == 0 {
-		t.Fatalf("no addresses for www.google.com")
+	var ip IP
+	for _, addr := range addrs {
+		if x := addr.To4(); x != nil {
+			ip = x
+			break
+		}
+	}
+	if ip == nil {
+		t.Fatalf("no IPv4 addresses for www.google.com")
 	}
-	ip := addrs[0].To4()
 
 	for i, s := range googleaddrs {
 		if strings.Contains(s, "%") {
diff --git a/src/pkg/net/dnsclient.go b/src/pkg/net/dnsclient.go
index c3e727b..89f2409 100644
--- a/src/pkg/net/dnsclient.go
+++ b/src/pkg/net/dnsclient.go
@@ -307,17 +307,22 @@ func lookup(name string, qtype uint16) (cname string, addrs []dnsRR, err os.Erro
 }
 
 // goLookupHost is the native Go implementation of LookupHost.
+// Used only if cgoLookupHost refuses to handle the request
+// (that is, only if cgoLookupHost is the stub in cgo_stub.go).
+// Normally we let cgo use the C library resolver instead of
+// depending on our lookup code, so that Go and C get the same
+// answers.
 func goLookupHost(name string) (addrs []string, err os.Error) {
-	onceLoadConfig.Do(loadConfig)
-	if dnserr != nil || cfg == nil {
-		err = dnserr
-		return
-	}
 	// Use entries from /etc/hosts if they match.
 	addrs = lookupStaticHost(name)
 	if len(addrs) > 0 {
 		return
 	}
+	onceLoadConfig.Do(loadConfig)
+	if dnserr != nil || cfg == nil {
+		err = dnserr
+		return
+	}
 	ips, err := goLookupIP(name)
 	if err != nil {
 		return
@@ -330,6 +335,11 @@ func goLookupHost(name string) (addrs []string, err os.Error) {
 }
 
 // goLookupIP is the native Go implementation of LookupIP.
+// Used only if cgoLookupIP refuses to handle the request
+// (that is, only if cgoLookupIP is the stub in cgo_stub.go).
+// Normally we let cgo use the C library resolver instead of
+// depending on our lookup code, so that Go and C get the same
+// answers.
 func goLookupIP(name string) (addrs []IP, err os.Error) {
 	onceLoadConfig.Do(loadConfig)
 	if dnserr != nil || cfg == nil {
@@ -358,11 +368,13 @@ func goLookupIP(name string) (addrs []IP, err os.Error) {
 	return
 }
 
-// LookupCNAME returns the canonical DNS host for the given name.
-// Callers that do not care about the canonical name can call
-// LookupHost or LookupIP directly; both take care of resolving
-// the canonical name as part of the lookup.
-func LookupCNAME(name string) (cname string, err os.Error) {
+// goLookupCNAME is the native Go implementation of LookupCNAME.
+// Used only if cgoLookupCNAME refuses to handle the request
+// (that is, only if cgoLookupCNAME is the stub in cgo_stub.go).
+// Normally we let cgo use the C library resolver instead of
+// depending on our lookup code, so that Go and C get the same
+// answers.
+func goLookupCNAME(name string) (cname string, err os.Error) {
 	onceLoadConfig.Do(loadConfig)
 	if dnserr != nil || cfg == nil {
 		err = dnserr
diff --git a/src/pkg/net/dnsmsg.go b/src/pkg/net/dnsmsg.go
index e8eb8d9..7b8e5c6 100644
--- a/src/pkg/net/dnsmsg.go
+++ b/src/pkg/net/dnsmsg.go
@@ -426,7 +426,7 @@ func packStructValue(val reflect.Value, msg []byte, off int) (off1 int, ok bool)
 			if off+n > len(msg) {
 				return len(msg), false
 			}
-			reflect.Copy(reflect.NewValue(msg[off:off+n]), fv)
+			reflect.Copy(reflect.ValueOf(msg[off:off+n]), fv)
 			off += n
 		case reflect.String:
 			// There are multiple string encodings.
@@ -456,7 +456,7 @@ func packStructValue(val reflect.Value, msg []byte, off int) (off1 int, ok bool)
 }
 
 func structValue(any interface{}) reflect.Value {
-	return reflect.NewValue(any).Elem()
+	return reflect.ValueOf(any).Elem()
 }
 
 func packStruct(any interface{}, msg []byte, off int) (off1 int, ok bool) {
@@ -499,7 +499,7 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, ok boo
 			if off+n > len(msg) {
 				return len(msg), false
 			}
-			reflect.Copy(fv, reflect.NewValue(msg[off:off+n]))
+			reflect.Copy(fv, reflect.ValueOf(msg[off:off+n]))
 			off += n
 		case reflect.String:
 			var s string
diff --git a/src/pkg/net/hosts_test.go b/src/pkg/net/hosts_test.go
index 470e35f..e5793ee 100644
--- a/src/pkg/net/hosts_test.go
+++ b/src/pkg/net/hosts_test.go
@@ -5,6 +5,7 @@
 package net
 
 import (
+	"sort"
 	"testing"
 )
 
@@ -51,3 +52,17 @@ func TestLookupStaticHost(t *testing.T) {
 	}
 	hostsPath = p
 }
+
+func TestLookupHost(t *testing.T) {
+	// Can't depend on this to return anything in particular,
+	// but if it does return something, make sure it doesn't
+	// duplicate addresses (a common bug due to the way
+	// getaddrinfo works).
+	addrs, _ := LookupHost("localhost")
+	sort.SortStrings(addrs)
+	for i := 0; i+1 < len(addrs); i++ {
+		if addrs[i] == addrs[i+1] {
+			t.Fatalf("LookupHost(\"localhost\") = %v, has duplicate addresses", addrs)
+		}
+	}
+}
diff --git a/src/pkg/net/ip.go b/src/pkg/net/ip.go
index 12bb6f3..61b2c68 100644
--- a/src/pkg/net/ip.go
+++ b/src/pkg/net/ip.go
@@ -75,7 +75,8 @@ var (
 
 // Well-known IPv6 addresses
 var (
-	IPzero = make(IP, IPv6len) // all zeros
+	IPzero       = make(IP, IPv6len) // all zeros
+	IPv6loopback = IP([]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1})
 )
 
 // Is p all zeros?
@@ -436,7 +437,7 @@ func parseIPv6(s string) IP {
 		}
 
 		// Otherwise must be followed by colon and more.
-		if s[i] != ':' && i+1 == len(s) {
+		if s[i] != ':' || i+1 == len(s) {
 			return nil
 		}
 		i++
diff --git a/src/pkg/net/ip_test.go b/src/pkg/net/ip_test.go
index f1a4716..2008953 100644
--- a/src/pkg/net/ip_test.go
+++ b/src/pkg/net/ip_test.go
@@ -29,6 +29,7 @@ var parseiptests = []struct {
 	{"127.0.0.1", IPv4(127, 0, 0, 1)},
 	{"127.0.0.256", nil},
 	{"abc", nil},
+	{"123:", nil},
 	{"::ffff:127.0.0.1", IPv4(127, 0, 0, 1)},
 	{"2001:4860:0:2001::68",
 		IP{0x20, 0x01, 0x48, 0x60, 0, 0, 0x20, 0x01,
diff --git a/src/pkg/net/iprawsock.go b/src/pkg/net/iprawsock.go
index 6043330..5be6fe4 100644
--- a/src/pkg/net/iprawsock.go
+++ b/src/pkg/net/iprawsock.go
@@ -245,7 +245,7 @@ func hostToIP(host string) (ip IP, err os.Error) {
 			err = err1
 			goto Error
 		}
-		addr = firstSupportedAddr(addrs)
+		addr = firstSupportedAddr(anyaddr, addrs)
 		if addr == nil {
 			// should not happen
 			err = &AddrError{"LookupHost returned invalid address", addrs[0]}
diff --git a/src/pkg/net/ipsock.go b/src/pkg/net/ipsock.go
index 80bc3ee..e8bcac6 100644
--- a/src/pkg/net/ipsock.go
+++ b/src/pkg/net/ipsock.go
@@ -35,15 +35,28 @@ func kernelSupportsIPv6() bool {
 
 var preferIPv4 = !kernelSupportsIPv6()
 
-func firstSupportedAddr(addrs []string) (addr IP) {
+func firstSupportedAddr(filter func(IP) IP, addrs []string) IP {
 	for _, s := range addrs {
-		addr = ParseIP(s)
-		if !preferIPv4 || addr.To4() != nil {
-			break
+		if addr := filter(ParseIP(s)); addr != nil {
+			return addr
 		}
-		addr = nil
 	}
-	return addr
+	return nil
+}
+
+func anyaddr(x IP) IP  { return x }
+func ipv4only(x IP) IP { return x.To4() }
+
+func ipv6only(x IP) IP {
+	// Only return addresses that we can use
+	// with the kernel's IPv6 addressing modes.
+	// If preferIPv4 is set, it means the IPv6 stack
+	// cannot take IPv4 addresses directly (we prefer
+	// to use the IPv4 stack) so reject IPv4 addresses.
+	if x.To4() != nil && preferIPv4 {
+		return nil
+	}
+	return x
 }
 
 // TODO(rsc): if syscall.OS == "linux", we're supposd to read
@@ -131,7 +144,6 @@ func (e InvalidAddrError) String() string  { return string(e) }
 func (e InvalidAddrError) Timeout() bool   { return false }
 func (e InvalidAddrError) Temporary() bool { return false }
 
-
 func ipToSockaddr(family int, ip IP, port int) (syscall.Sockaddr, os.Error) {
 	switch family {
 	case syscall.AF_INET:
@@ -218,13 +230,31 @@ func hostPortToIP(net, hostport string) (ip IP, iport int, err os.Error) {
 		// Try as an IP address.
 		addr = ParseIP(host)
 		if addr == nil {
+			filter := anyaddr
+			if len(net) >= 4 && net[3] == '4' {
+				filter = ipv4only
+			} else if len(net) >= 4 && net[3] == '6' {
+				filter = ipv6only
+			}
 			// Not an IP address.  Try as a DNS name.
 			addrs, err1 := LookupHost(host)
 			if err1 != nil {
 				err = err1
 				goto Error
 			}
-			addr = firstSupportedAddr(addrs)
+			if filter == anyaddr {
+				// We'll take any IP address, but since the dialing code
+				// does not yet try multiple addresses, prefer to use
+				// an IPv4 address if possible.  This is especially relevant
+				// if localhost resolves to [ipv6-localhost, ipv4-localhost].
+				// Too much code assumes localhost == ipv4-localhost.
+				addr = firstSupportedAddr(ipv4only, addrs)
+				if addr == nil {
+					addr = firstSupportedAddr(anyaddr, addrs)
+				}
+			} else {
+				addr = firstSupportedAddr(filter, addrs)
+			}
 			if addr == nil {
 				// should not happen
 				err = &AddrError{"LookupHost returned invalid address", addrs[0]}
diff --git a/src/pkg/net/lookup.go b/src/pkg/net/lookup.go
index 7b2185e..eeb22a8 100644
--- a/src/pkg/net/lookup.go
+++ b/src/pkg/net/lookup.go
@@ -36,3 +36,15 @@ func LookupPort(network, service string) (port int, err os.Error) {
 	}
 	return
 }
+
+// LookupCNAME returns the canonical DNS host for the given name.
+// Callers that do not care about the canonical name can call
+// LookupHost or LookupIP directly; both take care of resolving
+// the canonical name as part of the lookup.
+func LookupCNAME(name string) (cname string, err os.Error) {
+	cname, err, ok := cgoLookupCNAME(name)
+	if !ok {
+		cname, err = goLookupCNAME(name)
+	}
+	return
+}
diff --git a/src/pkg/net/net.go b/src/pkg/net/net.go
index 04a898a..51db107 100644
--- a/src/pkg/net/net.go
+++ b/src/pkg/net/net.go
@@ -2,9 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The net package provides a portable interface to Unix
-// networks sockets, including TCP/IP, UDP, domain name
-// resolution, and Unix domain sockets.
+// Package net provides a portable interface to Unix networks sockets,
+// including TCP/IP, UDP, domain name resolution, and Unix domain sockets.
 package net
 
 // TODO(rsc):
diff --git a/src/pkg/net/resolv_windows.go b/src/pkg/net/resolv_windows.go
index 000c306..3506ea1 100644
--- a/src/pkg/net/resolv_windows.go
+++ b/src/pkg/net/resolv_windows.go
@@ -47,7 +47,7 @@ func goLookupIP(name string) (addrs []IP, err os.Error) {
 	return addrs, nil
 }
 
-func LookupCNAME(name string) (cname string, err os.Error) {
+func goLookupCNAME(name string) (cname string, err os.Error) {
 	var r *syscall.DNSRecord
 	e := syscall.DnsQuery(name, syscall.DNS_TYPE_CNAME, 0, nil, &r, nil)
 	if int(e) != 0 {
diff --git a/src/pkg/net/server_test.go b/src/pkg/net/server_test.go
index 37695a0..075748b 100644
--- a/src/pkg/net/server_test.go
+++ b/src/pkg/net/server_test.go
@@ -108,12 +108,10 @@ func doTest(t *testing.T, network, listenaddr, dialaddr string) {
 }
 
 func TestTCPServer(t *testing.T) {
-	doTest(t, "tcp", "0.0.0.0", "127.0.0.1")
-	doTest(t, "tcp", "", "127.0.0.1")
+	doTest(t, "tcp", "127.0.0.1", "127.0.0.1")
 	if kernelSupportsIPv6() {
-		doTest(t, "tcp", "[::]", "[::ffff:127.0.0.1]")
-		doTest(t, "tcp", "[::]", "127.0.0.1")
-		doTest(t, "tcp", "0.0.0.0", "[::ffff:127.0.0.1]")
+		doTest(t, "tcp", "[::1]", "[::1]")
+		doTest(t, "tcp", "127.0.0.1", "[::ffff:127.0.0.1]")
 	}
 }
 
diff --git a/src/pkg/net/sock.go b/src/pkg/net/sock.go
index 933700a..bd88f7e 100644
--- a/src/pkg/net/sock.go
+++ b/src/pkg/net/sock.go
@@ -161,7 +161,7 @@ type UnknownSocketError struct {
 }
 
 func (e *UnknownSocketError) String() string {
-	return "unknown socket address type " + reflect.Typeof(e.sa).String()
+	return "unknown socket address type " + reflect.TypeOf(e.sa).String()
 }
 
 func sockaddrToString(sa syscall.Sockaddr) (name string, err os.Error) {
diff --git a/src/pkg/net/srv_test.go b/src/pkg/net/srv_test.go
index 4dd6089..f1c7a0a 100644
--- a/src/pkg/net/srv_test.go
+++ b/src/pkg/net/srv_test.go
@@ -8,10 +8,17 @@
 package net
 
 import (
+	"runtime"
 	"testing"
 )
 
+var avoidMacFirewall = runtime.GOOS == "darwin"
+
 func TestGoogleSRV(t *testing.T) {
+	if testing.Short() || avoidMacFirewall {
+		t.Logf("skipping test to avoid external network")
+		return
+	}
 	_, addrs, err := LookupSRV("xmpp-server", "tcp", "google.com")
 	if err != nil {
 		t.Errorf("failed: %s", err)
diff --git a/src/pkg/net/tcpsock.go b/src/pkg/net/tcpsock.go
index b484be2..d9aa7cf 100644
--- a/src/pkg/net/tcpsock.go
+++ b/src/pkg/net/tcpsock.go
@@ -62,8 +62,8 @@ func (a *TCPAddr) toAddr() sockaddr {
 // host:port and resolves domain names or port names to
 // numeric addresses.  A literal IPv6 host address must be
 // enclosed in square brackets, as in "[::]:80".
-func ResolveTCPAddr(addr string) (*TCPAddr, os.Error) {
-	ip, port, err := hostPortToIP("tcp", addr)
+func ResolveTCPAddr(network, addr string) (*TCPAddr, os.Error) {
+	ip, port, err := hostPortToIP(network, addr)
 	if err != nil {
 		return nil, err
 	}
diff --git a/src/pkg/net/textproto/textproto.go b/src/pkg/net/textproto/textproto.go
index fbfad9d..9f19b54 100644
--- a/src/pkg/net/textproto/textproto.go
+++ b/src/pkg/net/textproto/textproto.go
@@ -2,9 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The textproto package implements generic support for
-// text-based request/response protocols in the style of
-// HTTP, NNTP, and SMTP.
+// Package textproto implements generic support for text-based request/response
+// protocols in the style of HTTP, NNTP, and SMTP.
 //
 // The package provides:
 //
diff --git a/src/pkg/net/udpsock.go b/src/pkg/net/udpsock.go
index 44d618d..6768447 100644
--- a/src/pkg/net/udpsock.go
+++ b/src/pkg/net/udpsock.go
@@ -62,8 +62,8 @@ func (a *UDPAddr) toAddr() sockaddr {
 // host:port and resolves domain names or port names to
 // numeric addresses.  A literal IPv6 host address must be
 // enclosed in square brackets, as in "[::]:80".
-func ResolveUDPAddr(addr string) (*UDPAddr, os.Error) {
-	ip, port, err := hostPortToIP("udp", addr)
+func ResolveUDPAddr(network, addr string) (*UDPAddr, os.Error) {
+	ip, port, err := hostPortToIP(network, addr)
 	if err != nil {
 		return nil, err
 	}
diff --git a/src/pkg/netchan/export.go b/src/pkg/netchan/export.go
index 2209f04..1e5ccdb 100644
--- a/src/pkg/netchan/export.go
+++ b/src/pkg/netchan/export.go
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 /*
-	The netchan package implements type-safe networked channels:
+	Package netchan implements type-safe networked channels:
 	it allows the two ends of a channel to appear on different
 	computers connected by a network.  It does this by transporting
 	data sent to a channel on one machine so it can be recovered
@@ -111,9 +111,9 @@ func (client *expClient) getChan(hdr *header, dir Dir) *netChan {
 // data arrives from the client.
 func (client *expClient) run() {
 	hdr := new(header)
-	hdrValue := reflect.NewValue(hdr)
+	hdrValue := reflect.ValueOf(hdr)
 	req := new(request)
-	reqValue := reflect.NewValue(req)
+	reqValue := reflect.ValueOf(req)
 	error := new(error)
 	for {
 		*hdr = header{}
@@ -221,7 +221,7 @@ func (client *expClient) serveSend(hdr header) {
 		return
 	}
 	// Create a new value for each received item.
-	val := reflect.Zero(nch.ch.Type().Elem())
+	val := reflect.New(nch.ch.Type().Elem()).Elem()
 	if err := client.decode(val); err != nil {
 		expLog("value decode:", err, "; type ", nch.ch.Type())
 		return
@@ -341,7 +341,7 @@ func (exp *Exporter) Sync(timeout int64) os.Error {
 }
 
 func checkChan(chT interface{}, dir Dir) (reflect.Value, os.Error) {
-	chanType := reflect.Typeof(chT)
+	chanType := reflect.TypeOf(chT)
 	if chanType.Kind() != reflect.Chan {
 		return reflect.Value{}, os.ErrorString("not a channel")
 	}
@@ -359,7 +359,7 @@ func checkChan(chT interface{}, dir Dir) (reflect.Value, os.Error) {
 			return reflect.Value{}, os.ErrorString("to import/export with Recv, must provide chan<-")
 		}
 	}
-	return reflect.NewValue(chT), nil
+	return reflect.ValueOf(chT), nil
 }
 
 // Export exports a channel of a given type and specified direction.  The
diff --git a/src/pkg/netchan/import.go b/src/pkg/netchan/import.go
index 9921486..0a700ca 100644
--- a/src/pkg/netchan/import.go
+++ b/src/pkg/netchan/import.go
@@ -73,10 +73,10 @@ func (imp *Importer) shutdown() {
 func (imp *Importer) run() {
 	// Loop on responses; requests are sent by ImportNValues()
 	hdr := new(header)
-	hdrValue := reflect.NewValue(hdr)
+	hdrValue := reflect.ValueOf(hdr)
 	ackHdr := new(header)
 	err := new(error)
-	errValue := reflect.NewValue(err)
+	errValue := reflect.ValueOf(err)
 	for {
 		*hdr = header{}
 		if e := imp.decode(hdrValue); e != nil {
@@ -133,7 +133,7 @@ func (imp *Importer) run() {
 		ackHdr.SeqNum = hdr.SeqNum
 		imp.encode(ackHdr, payAck, nil)
 		// Create a new value for each received item.
-		value := reflect.Zero(nch.ch.Type().Elem())
+		value := reflect.New(nch.ch.Type().Elem()).Elem()
 		if e := imp.decode(value); e != nil {
 			impLog("importer value decode:", e)
 			return
diff --git a/src/pkg/os/file.go b/src/pkg/os/file.go
index 3aad802..dff8fa8 100644
--- a/src/pkg/os/file.go
+++ b/src/pkg/os/file.go
@@ -2,12 +2,13 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The os package provides a platform-independent interface to operating
-// system functionality.  The design is Unix-like.
+// Package os provides a platform-independent interface to operating system
+// functionality.  The design is Unix-like.
 package os
 
 import (
 	"runtime"
+	"sync"
 	"syscall"
 )
 
@@ -15,8 +16,9 @@ import (
 type File struct {
 	fd      int
 	name    string
-	dirinfo *dirInfo // nil unless directory being read
-	nepipe  int      // number of consecutive EPIPE in Write
+	dirinfo *dirInfo   // nil unless directory being read
+	nepipe  int        // number of consecutive EPIPE in Write
+	l       sync.Mutex // used to implement windows pread/pwrite
 }
 
 // Fd returns the integer Unix file descriptor referencing the open file.
@@ -30,7 +32,7 @@ func NewFile(fd int, name string) *File {
 	if fd < 0 {
 		return nil
 	}
-	f := &File{fd, name, nil, 0}
+	f := &File{fd: fd, name: name}
 	runtime.SetFinalizer(f, (*File).Close)
 	return f
 }
@@ -85,7 +87,7 @@ func (file *File) Read(b []byte) (n int, err Error) {
 	if file == nil {
 		return 0, EINVAL
 	}
-	n, e := syscall.Read(file.fd, b)
+	n, e := file.read(b)
 	if n < 0 {
 		n = 0
 	}
@@ -107,7 +109,7 @@ func (file *File) ReadAt(b []byte, off int64) (n int, err Error) {
 		return 0, EINVAL
 	}
 	for len(b) > 0 {
-		m, e := syscall.Pread(file.fd, b, off)
+		m, e := file.pread(b, off)
 		if m == 0 && !iserror(e) {
 			return n, EOF
 		}
@@ -129,7 +131,7 @@ func (file *File) Write(b []byte) (n int, err Error) {
 	if file == nil {
 		return 0, EINVAL
 	}
-	n, e := syscall.Write(file.fd, b)
+	n, e := file.write(b)
 	if n < 0 {
 		n = 0
 	}
@@ -150,7 +152,7 @@ func (file *File) WriteAt(b []byte, off int64) (n int, err Error) {
 		return 0, EINVAL
 	}
 	for len(b) > 0 {
-		m, e := syscall.Pwrite(file.fd, b, off)
+		m, e := file.pwrite(b, off)
 		if iserror(e) {
 			err = &PathError{"write", file.name, Errno(e)}
 			break
@@ -167,7 +169,7 @@ func (file *File) WriteAt(b []byte, off int64) (n int, err Error) {
 // relative to the current offset, and 2 means relative to the end.
 // It returns the new offset and an Error, if any.
 func (file *File) Seek(offset int64, whence int) (ret int64, err Error) {
-	r, e := syscall.Seek(file.fd, offset, whence)
+	r, e := file.seek(offset, whence)
 	if !iserror(e) && file.dirinfo != nil && r != 0 {
 		e = syscall.EISDIR
 	}
diff --git a/src/pkg/os/file_plan9.go b/src/pkg/os/file_plan9.go
index c8d0efb..7b473f8 100644
--- a/src/pkg/os/file_plan9.go
+++ b/src/pkg/os/file_plan9.go
@@ -117,6 +117,39 @@ func (f *File) Sync() (err Error) {
 	return nil
 }
 
+// read reads up to len(b) bytes from the File.
+// It returns the number of bytes read and an error, if any.
+func (f *File) read(b []byte) (n int, err syscall.Error) {
+	return syscall.Read(f.fd, b)
+}
+
+// pread reads len(b) bytes from the File starting at byte offset off.
+// It returns the number of bytes read and the error, if any.
+// EOF is signaled by a zero count with err set to nil.
+func (f *File) pread(b []byte, off int64) (n int, err syscall.Error) {
+	return syscall.Pread(f.fd, b, off)
+}
+
+// write writes len(b) bytes to the File.
+// It returns the number of bytes written and an error, if any.
+func (f *File) write(b []byte) (n int, err syscall.Error) {
+	return syscall.Write(f.fd, b)
+}
+
+// pwrite writes len(b) bytes to the File starting at byte offset off.
+// It returns the number of bytes written and an error, if any.
+func (f *File) pwrite(b []byte, off int64) (n int, err syscall.Error) {
+	return syscall.Pwrite(f.fd, b, off)
+}
+
+// seek sets the offset for the next Read or Write on file to offset, interpreted
+// according to whence: 0 means relative to the origin of the file, 1 means
+// relative to the current offset, and 2 means relative to the end.
+// It returns the new offset and an error, if any.
+func (f *File) seek(offset int64, whence int) (ret int64, err syscall.Error) {
+	return syscall.Seek(f.fd, offset, whence)
+}
+
 // Truncate changes the size of the named file.
 // If the file is a symbolic link, it changes the size of the link's target.
 func Truncate(name string, size int64) Error {
diff --git a/src/pkg/os/file_posix.go b/src/pkg/os/file_posix.go
index 5151df4..f1191d6 100644
--- a/src/pkg/os/file_posix.go
+++ b/src/pkg/os/file_posix.go
@@ -10,11 +10,13 @@ import (
 	"syscall"
 )
 
+func sigpipe() // implemented in package runtime
+
 func epipecheck(file *File, e int) {
 	if e == syscall.EPIPE {
 		file.nepipe++
 		if file.nepipe >= 10 {
-			Exit(syscall.EPIPE)
+			sigpipe()
 		}
 	} else {
 		file.nepipe = 0
diff --git a/src/pkg/os/file_unix.go b/src/pkg/os/file_unix.go
index f2b94f4..2fb28df 100644
--- a/src/pkg/os/file_unix.go
+++ b/src/pkg/os/file_unix.go
@@ -96,6 +96,39 @@ func (file *File) Readdir(count int) (fi []FileInfo, err Error) {
 	return
 }
 
+// read reads up to len(b) bytes from the File.
+// It returns the number of bytes read and an error, if any.
+func (f *File) read(b []byte) (n int, err int) {
+	return syscall.Read(f.fd, b)
+}
+
+// pread reads len(b) bytes from the File starting at byte offset off.
+// It returns the number of bytes read and the error, if any.
+// EOF is signaled by a zero count with err set to 0.
+func (f *File) pread(b []byte, off int64) (n int, err int) {
+	return syscall.Pread(f.fd, b, off)
+}
+
+// write writes len(b) bytes to the File.
+// It returns the number of bytes written and an error, if any.
+func (f *File) write(b []byte) (n int, err int) {
+	return syscall.Write(f.fd, b)
+}
+
+// pwrite writes len(b) bytes to the File starting at byte offset off.
+// It returns the number of bytes written and an error, if any.
+func (f *File) pwrite(b []byte, off int64) (n int, err int) {
+	return syscall.Pwrite(f.fd, b, off)
+}
+
+// seek sets the offset for the next Read or Write on file to offset, interpreted
+// according to whence: 0 means relative to the origin of the file, 1 means
+// relative to the current offset, and 2 means relative to the end.
+// It returns the new offset and an error, if any.
+func (f *File) seek(offset int64, whence int) (ret int64, err int) {
+	return syscall.Seek(f.fd, offset, whence)
+}
+
 // Truncate changes the size of the named file.
 // If the file is a symbolic link, it changes the size of the link's target.
 func Truncate(name string, size int64) Error {
diff --git a/src/pkg/os/file_windows.go b/src/pkg/os/file_windows.go
index 862baf6..95f60b7 100644
--- a/src/pkg/os/file_windows.go
+++ b/src/pkg/os/file_windows.go
@@ -165,6 +165,77 @@ func (file *File) Readdir(count int) (fi []FileInfo, err Error) {
 	return fi, nil
 }
 
+// read reads up to len(b) bytes from the File.
+// It returns the number of bytes read and an error, if any.
+func (f *File) read(b []byte) (n int, err int) {
+	f.l.Lock()
+	defer f.l.Unlock()
+	return syscall.Read(f.fd, b)
+}
+
+// pread reads len(b) bytes from the File starting at byte offset off.
+// It returns the number of bytes read and the error, if any.
+// EOF is signaled by a zero count with err set to 0.
+func (f *File) pread(b []byte, off int64) (n int, err int) {
+	f.l.Lock()
+	defer f.l.Unlock()
+	curoffset, e := syscall.Seek(f.fd, 0, 1)
+	if e != 0 {
+		return 0, e
+	}
+	defer syscall.Seek(f.fd, curoffset, 0)
+	o := syscall.Overlapped{
+		OffsetHigh: uint32(off >> 32),
+		Offset:     uint32(off),
+	}
+	var done uint32
+	e = syscall.ReadFile(int32(f.fd), b, &done, &o)
+	if e != 0 {
+		return 0, e
+	}
+	return int(done), 0
+}
+
+// write writes len(b) bytes to the File.
+// It returns the number of bytes written and an error, if any.
+func (f *File) write(b []byte) (n int, err int) {
+	f.l.Lock()
+	defer f.l.Unlock()
+	return syscall.Write(f.fd, b)
+}
+
+// pwrite writes len(b) bytes to the File starting at byte offset off.
+// It returns the number of bytes written and an error, if any.
+func (f *File) pwrite(b []byte, off int64) (n int, err int) {
+	f.l.Lock()
+	defer f.l.Unlock()
+	curoffset, e := syscall.Seek(f.fd, 0, 1)
+	if e != 0 {
+		return 0, e
+	}
+	defer syscall.Seek(f.fd, curoffset, 0)
+	o := syscall.Overlapped{
+		OffsetHigh: uint32(off >> 32),
+		Offset:     uint32(off),
+	}
+	var done uint32
+	e = syscall.WriteFile(int32(f.fd), b, &done, &o)
+	if e != 0 {
+		return 0, e
+	}
+	return int(done), 0
+}
+
+// seek sets the offset for the next Read or Write on file to offset, interpreted
+// according to whence: 0 means relative to the origin of the file, 1 means
+// relative to the current offset, and 2 means relative to the end.
+// It returns the new offset and an error, if any.
+func (f *File) seek(offset int64, whence int) (ret int64, err int) {
+	f.l.Lock()
+	defer f.l.Unlock()
+	return syscall.Seek(f.fd, offset, whence)
+}
+
 // Truncate changes the size of the named file.
 // If the file is a symbolic link, it changes the size of the link's target.
 func Truncate(name string, size int64) Error {
diff --git a/src/pkg/os/inotify/inotify_linux.go b/src/pkg/os/inotify/inotify_linux.go
index 8b5c30e..7c7b769 100644
--- a/src/pkg/os/inotify/inotify_linux.go
+++ b/src/pkg/os/inotify/inotify_linux.go
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 /*
-This package implements a wrapper for the Linux inotify system.
+Package inotify implements a wrapper for the Linux inotify system.
 
 Example:
     watcher, err := inotify.NewWatcher()
diff --git a/src/pkg/os/os_test.go b/src/pkg/os/os_test.go
index 551b865..65475c1 100644
--- a/src/pkg/os/os_test.go
+++ b/src/pkg/os/os_test.go
@@ -567,8 +567,8 @@ func checkSize(t *testing.T, f *File, size int64) {
 	}
 }
 
-func TestTruncate(t *testing.T) {
-	f := newFile("TestTruncate", t)
+func TestFTruncate(t *testing.T) {
+	f := newFile("TestFTruncate", t)
 	defer Remove(f.Name())
 	defer f.Close()
 
@@ -585,6 +585,24 @@ func TestTruncate(t *testing.T) {
 	checkSize(t, f, 13+9) // wrote at offset past where hello, world was.
 }
 
+func TestTruncate(t *testing.T) {
+	f := newFile("TestTruncate", t)
+	defer Remove(f.Name())
+	defer f.Close()
+
+	checkSize(t, f, 0)
+	f.Write([]byte("hello, world\n"))
+	checkSize(t, f, 13)
+	Truncate(f.Name(), 10)
+	checkSize(t, f, 10)
+	Truncate(f.Name(), 1024)
+	checkSize(t, f, 1024)
+	Truncate(f.Name(), 0)
+	checkSize(t, f, 0)
+	f.Write([]byte("surprise!"))
+	checkSize(t, f, 13+9) // wrote at offset past where hello, world was.
+}
+
 // Use TempDir() to make sure we're on a local file system,
 // so that timings are not distorted by latency and caching.
 // On NFS, timings can be off due to caching of meta-data on
@@ -886,6 +904,18 @@ func TestAppend(t *testing.T) {
 	if s != "new|append" {
 		t.Fatalf("writeFile: have %q want %q", s, "new|append")
 	}
+	s = writeFile(t, f, O_CREATE|O_APPEND|O_RDWR, "|append")
+	if s != "new|append|append" {
+		t.Fatalf("writeFile: have %q want %q", s, "new|append|append")
+	}
+	err := Remove(f)
+	if err != nil {
+		t.Fatalf("Remove: %v", err)
+	}
+	s = writeFile(t, f, O_CREATE|O_APPEND|O_RDWR, "new&append")
+	if s != "new&append" {
+		t.Fatalf("writeFile: have %q want %q", s, "new&append")
+	}
 }
 
 func TestStatDirWithTrailingSlash(t *testing.T) {
diff --git a/src/pkg/os/user/Makefile b/src/pkg/os/user/Makefile
new file mode 100644
index 0000000..731f799
--- /dev/null
+++ b/src/pkg/os/user/Makefile
@@ -0,0 +1,26 @@
+# Copyright 2011 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=os/user
+GOFILES=\
+	user.go\
+
+ifneq ($(GOARCH),arm)
+CGOFILES_linux=\
+	lookup_unix.go
+CGOFILES_freebsd=\
+	lookup_unix.go
+CGOFILES_darwin=\
+	lookup_unix.go
+endif
+
+ifneq ($(CGOFILES_$(GOOS)),)
+CGOFILES+=$(CGOFILES_$(GOOS))
+else
+GOFILES+=lookup_stubs.go
+endif
+
+include ../../../Make.pkg
diff --git a/src/pkg/os/user/lookup_stubs.go b/src/pkg/os/user/lookup_stubs.go
new file mode 100644
index 0000000..2f08f70
--- /dev/null
+++ b/src/pkg/os/user/lookup_stubs.go
@@ -0,0 +1,19 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package user
+
+import (
+	"fmt"
+	"os"
+	"runtime"
+)
+
+func Lookup(username string) (*User, os.Error) {
+	return nil, fmt.Errorf("user: Lookup not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
+}
+
+func LookupId(int) (*User, os.Error) {
+	return nil, fmt.Errorf("user: LookupId not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
+}
diff --git a/src/pkg/os/user/lookup_unix.go b/src/pkg/os/user/lookup_unix.go
new file mode 100644
index 0000000..678de80
--- /dev/null
+++ b/src/pkg/os/user/lookup_unix.go
@@ -0,0 +1,104 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package user
+
+import (
+	"fmt"
+	"os"
+	"runtime"
+	"strings"
+	"unsafe"
+)
+
+/*
+#include <unistd.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <stdlib.h>
+
+static int mygetpwuid_r(int uid, struct passwd *pwd,
+	char *buf, size_t buflen, struct passwd **result) {
+ return getpwuid_r(uid, pwd, buf, buflen, result);
+}
+*/
+import "C"
+
+// Lookup looks up a user by username. If the user cannot be found,
+// the returned error is of type UnknownUserError.
+func Lookup(username string) (*User, os.Error) {
+	return lookup(-1, username, true)
+}
+
+// LookupId looks up a user by userid. If the user cannot be found,
+// the returned error is of type UnknownUserIdError.
+func LookupId(uid int) (*User, os.Error) {
+	return lookup(uid, "", false)
+}
+
+func lookup(uid int, username string, lookupByName bool) (*User, os.Error) {
+	var pwd C.struct_passwd
+	var result *C.struct_passwd
+
+	var bufSize C.long
+	if runtime.GOOS == "freebsd" {
+		// FreeBSD doesn't have _SC_GETPW_R_SIZE_MAX
+		// and just returns -1.  So just use the same
+		// size that Linux returns
+		bufSize = 1024
+	} else {
+		bufSize = C.sysconf(C._SC_GETPW_R_SIZE_MAX)
+		if bufSize <= 0 || bufSize > 1<<20 {
+			return nil, fmt.Errorf("user: unreasonable _SC_GETPW_R_SIZE_MAX of %d", bufSize)
+		}
+	}
+	buf := C.malloc(C.size_t(bufSize))
+	defer C.free(buf)
+	var rv C.int
+	if lookupByName {
+		nameC := C.CString(username)
+		defer C.free(unsafe.Pointer(nameC))
+		rv = C.getpwnam_r(nameC,
+			&pwd,
+			(*C.char)(buf),
+			C.size_t(bufSize),
+			&result)
+		if rv != 0 {
+			return nil, fmt.Errorf("user: lookup username %s: %s", username, os.Errno(rv))
+		}
+		if result == nil {
+			return nil, UnknownUserError(username)
+		}
+	} else {
+		// mygetpwuid_r is a wrapper around getpwuid_r to
+		// to avoid using uid_t because C.uid_t(uid) for
+		// unknown reasons doesn't work on linux.
+		rv = C.mygetpwuid_r(C.int(uid),
+			&pwd,
+			(*C.char)(buf),
+			C.size_t(bufSize),
+			&result)
+		if rv != 0 {
+			return nil, fmt.Errorf("user: lookup userid %d: %s", uid, os.Errno(rv))
+		}
+		if result == nil {
+			return nil, UnknownUserIdError(uid)
+		}
+	}
+	u := &User{
+		Uid:      int(pwd.pw_uid),
+		Gid:      int(pwd.pw_gid),
+		Username: C.GoString(pwd.pw_name),
+		Name:     C.GoString(pwd.pw_gecos),
+		HomeDir:  C.GoString(pwd.pw_dir),
+	}
+	// The pw_gecos field isn't quite standardized.  Some docs
+	// say: "It is expected to be a comma separated list of
+	// personal data where the first item is the full name of the
+	// user."
+	if i := strings.Index(u.Name, ","); i >= 0 {
+		u.Name = u.Name[:i]
+	}
+	return u, nil
+}
diff --git a/src/pkg/os/user/user.go b/src/pkg/os/user/user.go
new file mode 100644
index 0000000..dd00921
--- /dev/null
+++ b/src/pkg/os/user/user.go
@@ -0,0 +1,35 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package user allows user account lookups by name or id.
+package user
+
+import (
+	"strconv"
+)
+
+// User represents a user account.
+type User struct {
+	Uid      int // user id
+	Gid      int // primary group id
+	Username string
+	Name     string
+	HomeDir  string
+}
+
+// UnknownUserIdError is returned by LookupId when
+// a user cannot be found.
+type UnknownUserIdError int
+
+func (e UnknownUserIdError) String() string {
+	return "user: unknown userid " + strconv.Itoa(int(e))
+}
+
+// UnknownUserError is returned by Lookup when
+// a user cannot be found.
+type UnknownUserError string
+
+func (e UnknownUserError) String() string {
+	return "user: unknown user " + string(e)
+}
diff --git a/src/pkg/os/user/user_test.go b/src/pkg/os/user/user_test.go
new file mode 100644
index 0000000..2c142bf
--- /dev/null
+++ b/src/pkg/os/user/user_test.go
@@ -0,0 +1,61 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package user
+
+import (
+	"os"
+	"reflect"
+	"runtime"
+	"syscall"
+	"testing"
+)
+
+func skip(t *testing.T) bool {
+	if runtime.GOARCH == "arm" {
+		t.Logf("user: cgo not implemented on arm; skipping tests")
+		return true
+	}
+
+	if runtime.GOOS == "linux" || runtime.GOOS == "freebsd" || runtime.GOOS == "darwin" {
+		return false
+	}
+
+	t.Logf("user: Lookup not implemented on %s; skipping test", runtime.GOOS)
+	return true
+}
+
+func TestLookup(t *testing.T) {
+	if skip(t) {
+		return
+	}
+
+	// Test LookupId on the current user
+	uid := syscall.Getuid()
+	u, err := LookupId(uid)
+	if err != nil {
+		t.Fatalf("LookupId: %v", err)
+	}
+	if e, g := uid, u.Uid; e != g {
+		t.Errorf("expected Uid of %d; got %d", e, g)
+	}
+	fi, err := os.Stat(u.HomeDir)
+	if err != nil || !fi.IsDirectory() {
+		t.Errorf("expected a valid HomeDir; stat(%q): err=%v, IsDirectory=%v", err, fi.IsDirectory())
+	}
+	if u.Username == "" {
+		t.Fatalf("didn't get a username")
+	}
+
+	// Test Lookup by username, using the username from LookupId
+	un, err := Lookup(u.Username)
+	if err != nil {
+		t.Fatalf("Lookup: %v", err)
+	}
+	if !reflect.DeepEqual(u, un) {
+		t.Errorf("Lookup by userid vs. name didn't match\n"+
+			"LookupId(%d): %#v\n"+
+			"Lookup(%q): %#v\n",uid, u, u.Username, un)
+	}
+}
diff --git a/src/pkg/path/filepath/path.go b/src/pkg/path/filepath/path.go
index de673a7..541a233 100644
--- a/src/pkg/path/filepath/path.go
+++ b/src/pkg/path/filepath/path.go
@@ -2,9 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The filepath package implements utility routines for manipulating
-// filename paths in a way compatible with the target operating
-// system-defined file paths.
+// Package filepath implements utility routines for manipulating filename paths
+// in a way compatible with the target operating system-defined file paths.
 package filepath
 
 import (
diff --git a/src/pkg/path/path.go b/src/pkg/path/path.go
index 658eec0..2353846 100644
--- a/src/pkg/path/path.go
+++ b/src/pkg/path/path.go
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The path package implements utility routines for manipulating
-// slash-separated filename paths.
+// Package path implements utility routines for manipulating slash-separated
+// filename paths.
 package path
 
 import (
diff --git a/src/pkg/reflect/all_test.go b/src/pkg/reflect/all_test.go
index bc91576..5bf6533 100644
--- a/src/pkg/reflect/all_test.go
+++ b/src/pkg/reflect/all_test.go
@@ -5,11 +5,13 @@
 package reflect_test
 
 import (
+	"bytes"
 	"container/vector"
 	"fmt"
 	"io"
 	"os"
 	. "reflect"
+	"runtime"
 	"testing"
 	"unsafe"
 )
@@ -35,7 +37,7 @@ func assert(t *testing.T, s, want string) {
 	}
 }
 
-func typestring(i interface{}) string { return Typeof(i).String() }
+func typestring(i interface{}) string { return TypeOf(i).String() }
 
 var typeTests = []pair{
 	{struct{ x int }{}, "int"},
@@ -150,50 +152,50 @@ var typeTests = []pair{
 			b()
 		})
 	}{},
-		"interface { a(func(func(int) int) func(func(int)) int); b() }",
+		"interface { reflect_test.a(func(func(int) int) func(func(int)) int); reflect_test.b() }",
 	},
 }
 
 var valueTests = []pair{
-	{(int8)(0), "8"},
-	{(int16)(0), "16"},
-	{(int32)(0), "32"},
-	{(int64)(0), "64"},
-	{(uint8)(0), "8"},
-	{(uint16)(0), "16"},
-	{(uint32)(0), "32"},
-	{(uint64)(0), "64"},
-	{(float32)(0), "256.25"},
-	{(float64)(0), "512.125"},
-	{(string)(""), "stringy cheese"},
-	{(bool)(false), "true"},
-	{(*int8)(nil), "*int8(0)"},
-	{(**int8)(nil), "**int8(0)"},
-	{[5]int32{}, "[5]int32{0, 0, 0, 0, 0}"},
-	{(**integer)(nil), "**reflect_test.integer(0)"},
-	{(map[string]int32)(nil), "map[string] int32{<can't iterate on maps>}"},
-	{(chan<- string)(nil), "chan<- string"},
-	{struct {
+	{new(int8), "8"},
+	{new(int16), "16"},
+	{new(int32), "32"},
+	{new(int64), "64"},
+	{new(uint8), "8"},
+	{new(uint16), "16"},
+	{new(uint32), "32"},
+	{new(uint64), "64"},
+	{new(float32), "256.25"},
+	{new(float64), "512.125"},
+	{new(string), "stringy cheese"},
+	{new(bool), "true"},
+	{new(*int8), "*int8(0)"},
+	{new(**int8), "**int8(0)"},
+	{new([5]int32), "[5]int32{0, 0, 0, 0, 0}"},
+	{new(**integer), "**reflect_test.integer(0)"},
+	{new(map[string]int32), "map[string] int32{<can't iterate on maps>}"},
+	{new(chan<- string), "chan<- string"},
+	{new(func(a int8, b int32)), "func(int8, int32)(0)"},
+	{new(struct {
 		c chan *int32
 		d float32
-	}{},
+	}),
 		"struct { c chan *int32; d float32 }{chan *int32, 0}",
 	},
-	{(func(a int8, b int32))(nil), "func(int8, int32)(0)"},
-	{struct{ c func(chan *integer, *int8) }{},
+	{new(struct{ c func(chan *integer, *int8) }),
 		"struct { c func(chan *reflect_test.integer, *int8) }{func(chan *reflect_test.integer, *int8)(0)}",
 	},
-	{struct {
+	{new(struct {
 		a int8
 		b int32
-	}{},
+	}),
 		"struct { a int8; b int32 }{0, 0}",
 	},
-	{struct {
+	{new(struct {
 		a int8
 		b int8
 		c int32
-	}{},
+	}),
 		"struct { a int8; b int8; c int32 }{0, 0, 0}",
 	},
 }
@@ -207,13 +209,13 @@ func testType(t *testing.T, i int, typ Type, want string) {
 
 func TestTypes(t *testing.T) {
 	for i, tt := range typeTests {
-		testType(t, i, NewValue(tt.i).Field(0).Type(), tt.s)
+		testType(t, i, ValueOf(tt.i).Field(0).Type(), tt.s)
 	}
 }
 
 func TestSet(t *testing.T) {
 	for i, tt := range valueTests {
-		v := NewValue(tt.i)
+		v := ValueOf(tt.i).Elem()
 		switch v.Kind() {
 		case Int:
 			v.SetInt(132)
@@ -257,40 +259,40 @@ func TestSet(t *testing.T) {
 
 func TestSetValue(t *testing.T) {
 	for i, tt := range valueTests {
-		v := NewValue(tt.i)
+		v := ValueOf(tt.i).Elem()
 		switch v.Kind() {
 		case Int:
-			v.Set(NewValue(int(132)))
+			v.Set(ValueOf(int(132)))
 		case Int8:
-			v.Set(NewValue(int8(8)))
+			v.Set(ValueOf(int8(8)))
 		case Int16:
-			v.Set(NewValue(int16(16)))
+			v.Set(ValueOf(int16(16)))
 		case Int32:
-			v.Set(NewValue(int32(32)))
+			v.Set(ValueOf(int32(32)))
 		case Int64:
-			v.Set(NewValue(int64(64)))
+			v.Set(ValueOf(int64(64)))
 		case Uint:
-			v.Set(NewValue(uint(132)))
+			v.Set(ValueOf(uint(132)))
 		case Uint8:
-			v.Set(NewValue(uint8(8)))
+			v.Set(ValueOf(uint8(8)))
 		case Uint16:
-			v.Set(NewValue(uint16(16)))
+			v.Set(ValueOf(uint16(16)))
 		case Uint32:
-			v.Set(NewValue(uint32(32)))
+			v.Set(ValueOf(uint32(32)))
 		case Uint64:
-			v.Set(NewValue(uint64(64)))
+			v.Set(ValueOf(uint64(64)))
 		case Float32:
-			v.Set(NewValue(float32(256.25)))
+			v.Set(ValueOf(float32(256.25)))
 		case Float64:
-			v.Set(NewValue(512.125))
+			v.Set(ValueOf(512.125))
 		case Complex64:
-			v.Set(NewValue(complex64(532.125 + 10i)))
+			v.Set(ValueOf(complex64(532.125 + 10i)))
 		case Complex128:
-			v.Set(NewValue(complex128(564.25 + 1i)))
+			v.Set(ValueOf(complex128(564.25 + 1i)))
 		case String:
-			v.Set(NewValue("stringy cheese"))
+			v.Set(ValueOf("stringy cheese"))
 		case Bool:
-			v.Set(NewValue(true))
+			v.Set(ValueOf(true))
 		}
 		s := valueToString(v)
 		if s != tt.s {
@@ -316,7 +318,7 @@ var valueToStringTests = []pair{
 
 func TestValueToString(t *testing.T) {
 	for i, test := range valueToStringTests {
-		s := valueToString(NewValue(test.i))
+		s := valueToString(ValueOf(test.i))
 		if s != test.s {
 			t.Errorf("#%d: have %#q, want %#q", i, s, test.s)
 		}
@@ -324,7 +326,7 @@ func TestValueToString(t *testing.T) {
 }
 
 func TestArrayElemSet(t *testing.T) {
-	v := NewValue([10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
+	v := ValueOf(&[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}).Elem()
 	v.Index(4).SetInt(123)
 	s := valueToString(v)
 	const want = "[10]int{1, 2, 3, 4, 123, 6, 7, 8, 9, 10}"
@@ -332,7 +334,7 @@ func TestArrayElemSet(t *testing.T) {
 		t.Errorf("[10]int: have %#q want %#q", s, want)
 	}
 
-	v = NewValue([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
+	v = ValueOf([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
 	v.Index(4).SetInt(123)
 	s = valueToString(v)
 	const want1 = "[]int{1, 2, 3, 4, 123, 6, 7, 8, 9, 10}"
@@ -344,15 +346,15 @@ func TestArrayElemSet(t *testing.T) {
 func TestPtrPointTo(t *testing.T) {
 	var ip *int32
 	var i int32 = 1234
-	vip := NewValue(&ip)
-	vi := NewValue(i)
+	vip := ValueOf(&ip)
+	vi := ValueOf(&i).Elem()
 	vip.Elem().Set(vi.Addr())
 	if *ip != 1234 {
 		t.Errorf("got %d, want 1234", *ip)
 	}
 
 	ip = nil
-	vp := NewValue(ip)
+	vp := ValueOf(&ip).Elem()
 	vp.Set(Zero(vp.Type()))
 	if ip != nil {
 		t.Errorf("got non-nil (%p), want nil", ip)
@@ -362,7 +364,7 @@ func TestPtrPointTo(t *testing.T) {
 func TestPtrSetNil(t *testing.T) {
 	var i int32 = 1234
 	ip := &i
-	vip := NewValue(&ip)
+	vip := ValueOf(&ip)
 	vip.Elem().Set(Zero(vip.Elem().Type()))
 	if ip != nil {
 		t.Errorf("got non-nil (%d), want nil", *ip)
@@ -371,7 +373,7 @@ func TestPtrSetNil(t *testing.T) {
 
 func TestMapSetNil(t *testing.T) {
 	m := make(map[string]int)
-	vm := NewValue(&m)
+	vm := ValueOf(&m)
 	vm.Elem().Set(Zero(vm.Elem().Type()))
 	if m != nil {
 		t.Errorf("got non-nil (%p), want nil", m)
@@ -380,10 +382,10 @@ func TestMapSetNil(t *testing.T) {
 
 
 func TestAll(t *testing.T) {
-	testType(t, 1, Typeof((int8)(0)), "int8")
-	testType(t, 2, Typeof((*int8)(nil)).Elem(), "int8")
+	testType(t, 1, TypeOf((int8)(0)), "int8")
+	testType(t, 2, TypeOf((*int8)(nil)).Elem(), "int8")
 
-	typ := Typeof((*struct {
+	typ := TypeOf((*struct {
 		c chan *int32
 		d float32
 	})(nil))
@@ -405,22 +407,22 @@ func TestAll(t *testing.T) {
 		t.Errorf("FieldByName says absent field is present")
 	}
 
-	typ = Typeof([32]int32{})
+	typ = TypeOf([32]int32{})
 	testType(t, 7, typ, "[32]int32")
 	testType(t, 8, typ.Elem(), "int32")
 
-	typ = Typeof((map[string]*int32)(nil))
+	typ = TypeOf((map[string]*int32)(nil))
 	testType(t, 9, typ, "map[string] *int32")
 	mtyp := typ
 	testType(t, 10, mtyp.Key(), "string")
 	testType(t, 11, mtyp.Elem(), "*int32")
 
-	typ = Typeof((chan<- string)(nil))
+	typ = TypeOf((chan<- string)(nil))
 	testType(t, 12, typ, "chan<- string")
 	testType(t, 13, typ.Elem(), "string")
 
 	// make sure tag strings are not part of element type
-	typ = Typeof(struct {
+	typ = TypeOf(struct {
 		d []uint32 "TAG"
 	}{}).Field(0).Type
 	testType(t, 14, typ, "[]uint32")
@@ -428,23 +430,23 @@ func TestAll(t *testing.T) {
 
 func TestInterfaceGet(t *testing.T) {
 	var inter struct {
-		e interface{}
+		E interface{}
 	}
-	inter.e = 123.456
-	v1 := NewValue(&inter)
+	inter.E = 123.456
+	v1 := ValueOf(&inter)
 	v2 := v1.Elem().Field(0)
 	assert(t, v2.Type().String(), "interface { }")
 	i2 := v2.Interface()
-	v3 := NewValue(i2)
+	v3 := ValueOf(i2)
 	assert(t, v3.Type().String(), "float64")
 }
 
 func TestInterfaceValue(t *testing.T) {
 	var inter struct {
-		e interface{}
+		E interface{}
 	}
-	inter.e = 123.456
-	v1 := NewValue(&inter)
+	inter.E = 123.456
+	v1 := ValueOf(&inter)
 	v2 := v1.Elem().Field(0)
 	assert(t, v2.Type().String(), "interface { }")
 	v3 := v2.Elem()
@@ -452,13 +454,14 @@ func TestInterfaceValue(t *testing.T) {
 
 	i3 := v2.Interface()
 	if _, ok := i3.(float64); !ok {
-		t.Error("v2.Interface() did not return float64, got ", Typeof(i3))
+		t.Error("v2.Interface() did not return float64, got ", TypeOf(i3))
 	}
 }
 
 func TestFunctionValue(t *testing.T) {
-	v := NewValue(func() {})
-	if v.Interface() != v.Interface() {
+	var x interface{} = func() {}
+	v := ValueOf(x)
+	if v.Interface() != v.Interface() || v.Interface() != x {
 		t.Fatalf("TestFunction != itself")
 	}
 	assert(t, v.Type().String(), "func()")
@@ -471,6 +474,18 @@ var appendTests = []struct {
 	{make([]int, 2, 4), []int{22, 33, 44}},
 }
 
+func sameInts(x, y []int) bool {
+	if len(x) != len(y) {
+		return false
+	}
+	for i, xx := range x {
+		if xx != y[i] {
+			return false
+		}
+	}
+	return true
+}
+
 func TestAppend(t *testing.T) {
 	for i, test := range appendTests {
 		origLen, extraLen := len(test.orig), len(test.extra)
@@ -478,15 +493,15 @@ func TestAppend(t *testing.T) {
 		// Convert extra from []int to []Value.
 		e0 := make([]Value, len(test.extra))
 		for j, e := range test.extra {
-			e0[j] = NewValue(e)
+			e0[j] = ValueOf(e)
 		}
 		// Convert extra from []int to *SliceValue.
-		e1 := NewValue(test.extra)
+		e1 := ValueOf(test.extra)
 		// Test Append.
-		a0 := NewValue(test.orig)
+		a0 := ValueOf(test.orig)
 		have0 := Append(a0, e0...).Interface().([]int)
-		if !DeepEqual(have0, want) {
-			t.Errorf("Append #%d: have %v, want %v", i, have0, want)
+		if !sameInts(have0, want) {
+			t.Errorf("Append #%d: have %v, want %v (%p %p)", i, have0, want, test.orig, have0)
 		}
 		// Check that the orig and extra slices were not modified.
 		if len(test.orig) != origLen {
@@ -496,9 +511,9 @@ func TestAppend(t *testing.T) {
 			t.Errorf("Append #%d extraLen: have %v, want %v", i, len(test.extra), extraLen)
 		}
 		// Test AppendSlice.
-		a1 := NewValue(test.orig)
+		a1 := ValueOf(test.orig)
 		have1 := AppendSlice(a1, e1).Interface().([]int)
-		if !DeepEqual(have1, want) {
+		if !sameInts(have1, want) {
 			t.Errorf("AppendSlice #%d: have %v, want %v", i, have1, want)
 		}
 		// Check that the orig and extra slices were not modified.
@@ -520,8 +535,10 @@ func TestCopy(t *testing.T) {
 			t.Fatalf("b != c before test")
 		}
 	}
-	aa := NewValue(a)
-	ab := NewValue(b)
+	a1 := a
+	b1 := b
+	aa := ValueOf(&a1).Elem()
+	ab := ValueOf(&b1).Elem()
 	for tocopy := 1; tocopy <= 7; tocopy++ {
 		aa.SetLen(tocopy)
 		Copy(ab, aa)
@@ -548,14 +565,41 @@ func TestCopy(t *testing.T) {
 	}
 }
 
+func TestCopyArray(t *testing.T) {
+	a := [8]int{1, 2, 3, 4, 10, 9, 8, 7}
+	b := [11]int{11, 22, 33, 44, 1010, 99, 88, 77, 66, 55, 44}
+	c := b
+	aa := ValueOf(&a).Elem()
+	ab := ValueOf(&b).Elem()
+	Copy(ab, aa)
+	for i := 0; i < len(a); i++ {
+		if a[i] != b[i] {
+			t.Errorf("(i) a[%d]=%d, b[%d]=%d", i, a[i], i, b[i])
+		}
+	}
+	for i := len(a); i < len(b); i++ {
+		if b[i] != c[i] {
+			if i < len(a) {
+				t.Errorf("(ii) a[%d]=%d, b[%d]=%d, c[%d]=%d",
+					i, a[i], i, b[i], i, c[i])
+			} else {
+				t.Errorf("(iii) b[%d]=%d, c[%d]=%d",
+					i, b[i], i, c[i])
+			}
+		} else {
+			t.Logf("elem %d is okay\n", i)
+		}
+	}
+}
+
 func TestBigUnnamedStruct(t *testing.T) {
 	b := struct{ a, b, c, d int64 }{1, 2, 3, 4}
-	v := NewValue(b)
+	v := ValueOf(b)
 	b1 := v.Interface().(struct {
 		a, b, c, d int64
 	})
 	if b1.a != b.a || b1.b != b.b || b1.c != b.c || b1.d != b.d {
-		t.Errorf("NewValue(%v).Interface().(*Big) = %v", b, b1)
+		t.Errorf("ValueOf(%v).Interface().(*Big) = %v", b, b1)
 	}
 }
 
@@ -565,10 +609,10 @@ type big struct {
 
 func TestBigStruct(t *testing.T) {
 	b := big{1, 2, 3, 4, 5}
-	v := NewValue(b)
+	v := ValueOf(b)
 	b1 := v.Interface().(big)
 	if b1.a != b.a || b1.b != b.b || b1.c != b.c || b1.d != b.d || b1.e != b.e {
-		t.Errorf("NewValue(%v).Interface().(big) = %v", b, b1)
+		t.Errorf("ValueOf(%v).Interface().(big) = %v", b, b1)
 	}
 }
 
@@ -632,15 +676,15 @@ func TestDeepEqual(t *testing.T) {
 	}
 }
 
-func TestTypeof(t *testing.T) {
+func TestTypeOf(t *testing.T) {
 	for _, test := range deepEqualTests {
-		v := NewValue(test.a)
+		v := ValueOf(test.a)
 		if !v.IsValid() {
 			continue
 		}
-		typ := Typeof(test.a)
+		typ := TypeOf(test.a)
 		if typ != v.Type() {
-			t.Errorf("Typeof(%v) = %v, but NewValue(%v).Type() = %v", test.a, typ, test.a, v.Type())
+			t.Errorf("TypeOf(%v) = %v, but ValueOf(%v).Type() = %v", test.a, typ, test.a, v.Type())
 		}
 	}
 }
@@ -690,7 +734,7 @@ func TestDeepEqualComplexStructInequality(t *testing.T) {
 
 
 func check2ndField(x interface{}, offs uintptr, t *testing.T) {
-	s := NewValue(x)
+	s := ValueOf(x)
 	f := s.Type().Field(1)
 	if f.Offset != offs {
 		t.Error("mismatched offsets in structure alignment:", f.Offset, offs)
@@ -723,16 +767,16 @@ func TestAlignment(t *testing.T) {
 }
 
 func Nil(a interface{}, t *testing.T) {
-	n := NewValue(a).Field(0)
+	n := ValueOf(a).Field(0)
 	if !n.IsNil() {
 		t.Errorf("%v should be nil", a)
 	}
 }
 
 func NotNil(a interface{}, t *testing.T) {
-	n := NewValue(a).Field(0)
+	n := ValueOf(a).Field(0)
 	if n.IsNil() {
-		t.Errorf("value of type %v should not be nil", NewValue(a).Type().String())
+		t.Errorf("value of type %v should not be nil", ValueOf(a).Type().String())
 	}
 }
 
@@ -748,7 +792,7 @@ func TestIsNil(t *testing.T) {
 		struct{ x []string }{},
 	}
 	for _, ts := range doNil {
-		ty := Typeof(ts).Field(0).Type
+		ty := TypeOf(ts).Field(0).Type
 		v := Zero(ty)
 		v.IsNil() // panics if not okay to call
 	}
@@ -803,50 +847,22 @@ func TestInterfaceExtraction(t *testing.T) {
 	}
 
 	s.w = os.Stdout
-	v := Indirect(NewValue(&s)).Field(0).Interface()
+	v := Indirect(ValueOf(&s)).Field(0).Interface()
 	if v != s.w.(interface{}) {
 		t.Error("Interface() on interface: ", v, s.w)
 	}
 }
 
-func TestInterfaceEditing(t *testing.T) {
-	// strings are bigger than one word,
-	// so the interface conversion allocates
-	// memory to hold a string and puts that
-	// pointer in the interface.
-	var i interface{} = "hello"
-
-	// if i pass the interface value by value
-	// to NewValue, i should get a fresh copy
-	// of the value.
-	v := NewValue(i)
-
-	// and setting that copy to "bye" should
-	// not change the value stored in i.
-	v.SetString("bye")
-	if i.(string) != "hello" {
-		t.Errorf(`Set("bye") changed i to %s`, i.(string))
-	}
-
-	// the same should be true of smaller items.
-	i = 123
-	v = NewValue(i)
-	v.SetInt(234)
-	if i.(int) != 123 {
-		t.Errorf("Set(234) changed i to %d", i.(int))
-	}
-}
-
 func TestNilPtrValueSub(t *testing.T) {
 	var pi *int
-	if pv := NewValue(pi); pv.Elem().IsValid() {
-		t.Error("NewValue((*int)(nil)).Elem().IsValid()")
+	if pv := ValueOf(pi); pv.Elem().IsValid() {
+		t.Error("ValueOf((*int)(nil)).Elem().IsValid()")
 	}
 }
 
 func TestMap(t *testing.T) {
 	m := map[string]int{"a": 1, "b": 2}
-	mv := NewValue(m)
+	mv := ValueOf(m)
 	if n := mv.Len(); n != len(m) {
 		t.Errorf("Len = %d, want %d", n, len(m))
 	}
@@ -866,15 +882,15 @@ func TestMap(t *testing.T) {
 		i++
 
 		// Check that value lookup is correct.
-		vv := mv.MapIndex(NewValue(k))
+		vv := mv.MapIndex(ValueOf(k))
 		if vi := vv.Int(); vi != int64(v) {
 			t.Errorf("Key %q: have value %d, want %d", k, vi, v)
 		}
 
 		// Copy into new map.
-		newmap.SetMapIndex(NewValue(k), NewValue(v))
+		newmap.SetMapIndex(ValueOf(k), ValueOf(v))
 	}
-	vv := mv.MapIndex(NewValue("not-present"))
+	vv := mv.MapIndex(ValueOf("not-present"))
 	if vv.IsValid() {
 		t.Errorf("Invalid key: got non-nil value %s", valueToString(vv))
 	}
@@ -891,13 +907,13 @@ func TestMap(t *testing.T) {
 		}
 	}
 
-	newmap.SetMapIndex(NewValue("a"), Value{})
+	newmap.SetMapIndex(ValueOf("a"), Value{})
 	v, ok := newm["a"]
 	if ok {
 		t.Errorf("newm[\"a\"] = %d after delete", v)
 	}
 
-	mv = NewValue(&m).Elem()
+	mv = ValueOf(&m).Elem()
 	mv.Set(Zero(mv.Type()))
 	if m != nil {
 		t.Errorf("mv.Set(nil) failed")
@@ -913,14 +929,14 @@ func TestChan(t *testing.T) {
 		switch loop {
 		case 1:
 			c = make(chan int, 1)
-			cv = NewValue(c)
+			cv = ValueOf(c)
 		case 0:
-			cv = MakeChan(Typeof(c), 1)
+			cv = MakeChan(TypeOf(c), 1)
 			c = cv.Interface().(chan int)
 		}
 
 		// Send
-		cv.Send(NewValue(2))
+		cv.Send(ValueOf(2))
 		if i := <-c; i != 2 {
 			t.Errorf("reflect Send 2, native recv %d", i)
 		}
@@ -948,14 +964,14 @@ func TestChan(t *testing.T) {
 
 		// TrySend fail
 		c <- 100
-		ok = cv.TrySend(NewValue(5))
+		ok = cv.TrySend(ValueOf(5))
 		i := <-c
 		if ok {
 			t.Errorf("TrySend on full chan succeeded: value %d", i)
 		}
 
 		// TrySend success
-		ok = cv.TrySend(NewValue(6))
+		ok = cv.TrySend(ValueOf(6))
 		if !ok {
 			t.Errorf("TrySend on empty chan failed")
 		} else {
@@ -977,17 +993,17 @@ func TestChan(t *testing.T) {
 
 	// check creation of unbuffered channel
 	var c chan int
-	cv := MakeChan(Typeof(c), 0)
+	cv := MakeChan(TypeOf(c), 0)
 	c = cv.Interface().(chan int)
-	if cv.TrySend(NewValue(7)) {
+	if cv.TrySend(ValueOf(7)) {
 		t.Errorf("TrySend on sync chan succeeded")
 	}
 	if v, ok := cv.TryRecv(); v.IsValid() || ok {
-		t.Errorf("TryRecv on sync chan succeeded")
+		t.Errorf("TryRecv on sync chan succeeded: isvalid=%v ok=%v", v.IsValid(), ok)
 	}
 
 	// len/cap
-	cv = MakeChan(Typeof(c), 10)
+	cv = MakeChan(TypeOf(c), 10)
 	c = cv.Interface().(chan int)
 	for i := 0; i < 3; i++ {
 		c <- i
@@ -1005,7 +1021,7 @@ func dummy(b byte, c int, d byte) (i byte, j int, k byte) {
 }
 
 func TestFunc(t *testing.T) {
-	ret := NewValue(dummy).Call([]Value{NewValue(byte(10)), NewValue(20), NewValue(byte(30))})
+	ret := ValueOf(dummy).Call([]Value{ValueOf(byte(10)), ValueOf(20), ValueOf(byte(30))})
 	if len(ret) != 3 {
 		t.Fatalf("Call returned %d values, want 3", len(ret))
 	}
@@ -1022,50 +1038,47 @@ type Point struct {
 	x, y int
 }
 
-func (p Point) Dist(scale int) int { return p.x*p.x*scale + p.y*p.y*scale }
+func (p Point) Dist(scale int) int {
+	//	println("Point.Dist", p.x, p.y, scale)
+	return p.x*p.x*scale + p.y*p.y*scale
+}
 
 func TestMethod(t *testing.T) {
 	// Non-curried method of type.
 	p := Point{3, 4}
-	i := Typeof(p).Method(0).Func.Call([]Value{NewValue(p), NewValue(10)})[0].Int()
+	i := TypeOf(p).Method(0).Func.Call([]Value{ValueOf(p), ValueOf(10)})[0].Int()
 	if i != 250 {
 		t.Errorf("Type Method returned %d; want 250", i)
 	}
 
-	i = Typeof(&p).Method(0).Func.Call([]Value{NewValue(&p), NewValue(10)})[0].Int()
+	i = TypeOf(&p).Method(0).Func.Call([]Value{ValueOf(&p), ValueOf(10)})[0].Int()
 	if i != 250 {
 		t.Errorf("Pointer Type Method returned %d; want 250", i)
 	}
 
 	// Curried method of value.
-	i = NewValue(p).Method(0).Call([]Value{NewValue(10)})[0].Int()
+	i = ValueOf(p).Method(0).Call([]Value{ValueOf(10)})[0].Int()
 	if i != 250 {
 		t.Errorf("Value Method returned %d; want 250", i)
 	}
 
 	// Curried method of pointer.
-	i = NewValue(&p).Method(0).Call([]Value{NewValue(10)})[0].Int()
-	if i != 250 {
-		t.Errorf("Value Method returned %d; want 250", i)
-	}
-
-	// Curried method of pointer to value.
-	i = NewValue(p).Addr().Method(0).Call([]Value{NewValue(10)})[0].Int()
+	i = ValueOf(&p).Method(0).Call([]Value{ValueOf(10)})[0].Int()
 	if i != 250 {
 		t.Errorf("Value Method returned %d; want 250", i)
 	}
 
 	// Curried method of interface value.
 	// Have to wrap interface value in a struct to get at it.
-	// Passing it to NewValue directly would
+	// Passing it to ValueOf directly would
 	// access the underlying Point, not the interface.
 	var s = struct {
-		x interface {
+		X interface {
 			Dist(int) int
 		}
 	}{p}
-	pv := NewValue(s).Field(0)
-	i = pv.Method(0).Call([]Value{NewValue(10)})[0].Int()
+	pv := ValueOf(s).Field(0)
+	i = pv.Method(0).Call([]Value{ValueOf(10)})[0].Int()
 	if i != 250 {
 		t.Errorf("Interface Method returned %d; want 250", i)
 	}
@@ -1080,19 +1093,19 @@ func TestInterfaceSet(t *testing.T) {
 			Dist(int) int
 		}
 	}
-	sv := NewValue(&s).Elem()
-	sv.Field(0).Set(NewValue(p))
+	sv := ValueOf(&s).Elem()
+	sv.Field(0).Set(ValueOf(p))
 	if q := s.I.(*Point); q != p {
 		t.Errorf("i: have %p want %p", q, p)
 	}
 
 	pv := sv.Field(1)
-	pv.Set(NewValue(p))
+	pv.Set(ValueOf(p))
 	if q := s.P.(*Point); q != p {
 		t.Errorf("i: have %p want %p", q, p)
 	}
 
-	i := pv.Method(0).Call([]Value{NewValue(10)})[0].Int()
+	i := pv.Method(0).Call([]Value{ValueOf(10)})[0].Int()
 	if i != 250 {
 		t.Errorf("Interface Method returned %d; want 250", i)
 	}
@@ -1107,7 +1120,7 @@ func TestAnonymousFields(t *testing.T) {
 	var field StructField
 	var ok bool
 	var t1 T1
-	type1 := Typeof(t1)
+	type1 := TypeOf(t1)
 	if field, ok = type1.FieldByName("int"); !ok {
 		t.Error("no field 'int'")
 	}
@@ -1191,7 +1204,7 @@ var fieldTests = []FTest{
 
 func TestFieldByIndex(t *testing.T) {
 	for _, test := range fieldTests {
-		s := Typeof(test.s)
+		s := TypeOf(test.s)
 		f := s.FieldByIndex(test.index)
 		if f.Name != "" {
 			if test.index != nil {
@@ -1206,7 +1219,7 @@ func TestFieldByIndex(t *testing.T) {
 		}
 
 		if test.value != 0 {
-			v := NewValue(test.s).FieldByIndex(test.index)
+			v := ValueOf(test.s).FieldByIndex(test.index)
 			if v.IsValid() {
 				if x, ok := v.Interface().(int); ok {
 					if x != test.value {
@@ -1224,7 +1237,7 @@ func TestFieldByIndex(t *testing.T) {
 
 func TestFieldByName(t *testing.T) {
 	for _, test := range fieldTests {
-		s := Typeof(test.s)
+		s := TypeOf(test.s)
 		f, found := s.FieldByName(test.name)
 		if found {
 			if test.index != nil {
@@ -1246,7 +1259,7 @@ func TestFieldByName(t *testing.T) {
 		}
 
 		if test.value != 0 {
-			v := NewValue(test.s).FieldByName(test.name)
+			v := ValueOf(test.s).FieldByName(test.name)
 			if v.IsValid() {
 				if x, ok := v.Interface().(int); ok {
 					if x != test.value {
@@ -1263,19 +1276,19 @@ func TestFieldByName(t *testing.T) {
 }
 
 func TestImportPath(t *testing.T) {
-	if path := Typeof(vector.Vector{}).PkgPath(); path != "container/vector" {
-		t.Errorf("Typeof(vector.Vector{}).PkgPath() = %q, want \"container/vector\"", path)
+	if path := TypeOf(vector.Vector{}).PkgPath(); path != "container/vector" {
+		t.Errorf("TypeOf(vector.Vector{}).PkgPath() = %q, want \"container/vector\"", path)
 	}
 }
 
 func TestDotDotDot(t *testing.T) {
 	// Test example from FuncType.DotDotDot documentation.
 	var f func(x int, y ...float64)
-	typ := Typeof(f)
-	if typ.NumIn() == 2 && typ.In(0) == Typeof(int(0)) {
+	typ := TypeOf(f)
+	if typ.NumIn() == 2 && typ.In(0) == TypeOf(int(0)) {
 		sl := typ.In(1)
 		if sl.Kind() == Slice {
-			if sl.Elem() == Typeof(0.0) {
+			if sl.Elem() == TypeOf(0.0) {
 				// ok
 				return
 			}
@@ -1304,8 +1317,8 @@ func (*inner) m() {}
 func (*outer) m() {}
 
 func TestNestedMethods(t *testing.T) {
-	typ := Typeof((*outer)(nil))
-	if typ.NumMethod() != 1 || typ.Method(0).Func.Pointer() != NewValue((*outer).m).Pointer() {
+	typ := TypeOf((*outer)(nil))
+	if typ.NumMethod() != 1 || typ.Method(0).Func.Pointer() != ValueOf((*outer).m).Pointer() {
 		t.Errorf("Wrong method table for outer: (m=%p)", (*outer).m)
 		for i := 0; i < typ.NumMethod(); i++ {
 			m := typ.Method(i)
@@ -1314,40 +1327,40 @@ func TestNestedMethods(t *testing.T) {
 	}
 }
 
-type innerInt struct {
-	x int
+type InnerInt struct {
+	X int
 }
 
-type outerInt struct {
-	y int
-	innerInt
+type OuterInt struct {
+	Y int
+	InnerInt
 }
 
-func (i *innerInt) m() int {
-	return i.x
+func (i *InnerInt) M() int {
+	return i.X
 }
 
 func TestEmbeddedMethods(t *testing.T) {
-	typ := Typeof((*outerInt)(nil))
-	if typ.NumMethod() != 1 || typ.Method(0).Func.Pointer() != NewValue((*outerInt).m).Pointer() {
-		t.Errorf("Wrong method table for outerInt: (m=%p)", (*outerInt).m)
+	typ := TypeOf((*OuterInt)(nil))
+	if typ.NumMethod() != 1 || typ.Method(0).Func.Pointer() != ValueOf((*OuterInt).M).Pointer() {
+		t.Errorf("Wrong method table for OuterInt: (m=%p)", (*OuterInt).M)
 		for i := 0; i < typ.NumMethod(); i++ {
 			m := typ.Method(i)
 			t.Errorf("\t%d: %s %#x\n", i, m.Name, m.Func.Pointer())
 		}
 	}
 
-	i := &innerInt{3}
-	if v := NewValue(i).Method(0).Call(nil)[0].Int(); v != 3 {
-		t.Errorf("i.m() = %d, want 3", v)
+	i := &InnerInt{3}
+	if v := ValueOf(i).Method(0).Call(nil)[0].Int(); v != 3 {
+		t.Errorf("i.M() = %d, want 3", v)
 	}
 
-	o := &outerInt{1, innerInt{2}}
-	if v := NewValue(o).Method(0).Call(nil)[0].Int(); v != 2 {
-		t.Errorf("i.m() = %d, want 2", v)
+	o := &OuterInt{1, InnerInt{2}}
+	if v := ValueOf(o).Method(0).Call(nil)[0].Int(); v != 2 {
+		t.Errorf("i.M() = %d, want 2", v)
 	}
 
-	f := (*outerInt).m
+	f := (*OuterInt).M
 	if v := f(o); v != 2 {
 		t.Errorf("f(o) = %d, want 2", v)
 	}
@@ -1356,15 +1369,15 @@ func TestEmbeddedMethods(t *testing.T) {
 func TestPtrTo(t *testing.T) {
 	var i int
 
-	typ := Typeof(i)
+	typ := TypeOf(i)
 	for i = 0; i < 100; i++ {
 		typ = PtrTo(typ)
 	}
 	for i = 0; i < 100; i++ {
 		typ = typ.Elem()
 	}
-	if typ != Typeof(i) {
-		t.Errorf("after 100 PtrTo and Elem, have %s, want %s", typ, Typeof(i))
+	if typ != TypeOf(i) {
+		t.Errorf("after 100 PtrTo and Elem, have %s, want %s", typ, TypeOf(i))
 	}
 }
 
@@ -1373,7 +1386,7 @@ func TestAddr(t *testing.T) {
 		X, Y int
 	}
 
-	v := NewValue(&p)
+	v := ValueOf(&p)
 	v = v.Elem()
 	v = v.Addr()
 	v = v.Elem()
@@ -1383,9 +1396,10 @@ func TestAddr(t *testing.T) {
 		t.Errorf("Addr.Elem.Set failed to set value")
 	}
 
-	// Again but take address of the NewValue value.
+	// Again but take address of the ValueOf value.
 	// Exercises generation of PtrTypes not present in the binary.
-	v = NewValue(&p)
+	q := &p
+	v = ValueOf(&q).Elem()
 	v = v.Addr()
 	v = v.Elem()
 	v = v.Elem()
@@ -1399,7 +1413,8 @@ func TestAddr(t *testing.T) {
 
 	// Starting without pointer we should get changed value
 	// in interface.
-	v = NewValue(p)
+	qq := p
+	v = ValueOf(&qq).Elem()
 	v0 := v
 	v = v.Addr()
 	v = v.Elem()
@@ -1415,3 +1430,67 @@ func TestAddr(t *testing.T) {
 		t.Errorf("Addr.Elem.Set valued to set value in top value")
 	}
 }
+
+func noAlloc(t *testing.T, n int, f func(int)) {
+	// once to prime everything
+	f(-1)
+	runtime.MemStats.Mallocs = 0
+
+	for j := 0; j < n; j++ {
+		f(j)
+	}
+	if runtime.MemStats.Mallocs != 0 {
+		t.Fatalf("%d mallocs after %d iterations", runtime.MemStats.Mallocs, n)
+	}
+}
+
+func TestAllocations(t *testing.T) {
+	noAlloc(t, 100, func(j int) {
+		var i interface{}
+		var v Value
+		i = 42 + j
+		v = ValueOf(i)
+		if int(v.Int()) != 42+j {
+			panic("wrong int")
+		}
+	})
+}
+
+func TestSmallNegativeInt(t *testing.T) {
+	i := int16(-1)
+	v := ValueOf(i)
+	if v.Int() != -1 {
+		t.Errorf("int16(-1).Int() returned %v", v.Int())
+	}
+}
+
+func TestSlice(t *testing.T) {
+	xs := []int{1, 2, 3, 4, 5, 6, 7, 8}
+	v := ValueOf(xs).Slice(3, 5).Interface().([]int)
+	if len(v) != 2 || v[0] != 4 || v[1] != 5 {
+		t.Errorf("xs.Slice(3, 5) = %v", v)
+	}
+
+	xa := [7]int{10, 20, 30, 40, 50, 60, 70}
+	v = ValueOf(&xa).Elem().Slice(2, 5).Interface().([]int)
+	if len(v) != 3 || v[0] != 30 || v[1] != 40 || v[2] != 50 {
+		t.Errorf("xa.Slice(2, 5) = %v", v)
+	}
+}
+
+func TestVariadic(t *testing.T) {
+	var b bytes.Buffer
+	V := ValueOf
+
+	b.Reset()
+	V(fmt.Fprintf).Call([]Value{V(&b), V("%s, %d world"), V("hello"), V(42)})
+	if b.String() != "hello, 42 world" {
+		t.Errorf("after Fprintf Call: %q != %q", b.String(), "hello 42 world")
+	}
+
+	b.Reset()
+	V(fmt.Fprintf).CallSlice([]Value{V(&b), V("%s, %d world"), V([]interface{}{"hello", 42})})
+	if b.String() != "hello, 42 world" {
+		t.Errorf("after Fprintf CallSlice: %q != %q", b.String(), "hello 42 world")
+	}
+}
diff --git a/src/pkg/reflect/deepequal.go b/src/pkg/reflect/deepequal.go
index f5a7814..a483135 100644
--- a/src/pkg/reflect/deepequal.go
+++ b/src/pkg/reflect/deepequal.go
@@ -6,7 +6,6 @@
 
 package reflect
 
-
 // During deepValueEqual, must keep track of checks that are
 // in progress.  The comparison algorithm assumes that all
 // checks in progress are true when it reencounters them.
@@ -21,7 +20,7 @@ type visit struct {
 // Tests for deep equality using reflected types. The map argument tracks
 // comparisons that have already been seen, which allows short circuiting on
 // recursive types.
-func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) bool {
+func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) (b bool) {
 	if !v1.IsValid() || !v2.IsValid() {
 		return v1.IsValid() == v2.IsValid()
 	}
@@ -31,30 +30,32 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) bool {
 
 	// if depth > 10 { panic("deepValueEqual") }	// for debugging
 
-	addr1 := v1.UnsafeAddr()
-	addr2 := v2.UnsafeAddr()
-	if addr1 > addr2 {
-		// Canonicalize order to reduce number of entries in visited.
-		addr1, addr2 = addr2, addr1
-	}
-
-	// Short circuit if references are identical ...
-	if addr1 == addr2 {
-		return true
-	}
+	if v1.CanAddr() && v2.CanAddr() {
+		addr1 := v1.UnsafeAddr()
+		addr2 := v2.UnsafeAddr()
+		if addr1 > addr2 {
+			// Canonicalize order to reduce number of entries in visited.
+			addr1, addr2 = addr2, addr1
+		}
 
-	// ... or already seen
-	h := 17*addr1 + addr2
-	seen := visited[h]
-	typ := v1.Type()
-	for p := seen; p != nil; p = p.next {
-		if p.a1 == addr1 && p.a2 == addr2 && p.typ == typ {
+		// Short circuit if references are identical ...
+		if addr1 == addr2 {
 			return true
 		}
-	}
 
-	// Remember for later.
-	visited[h] = &visit{addr1, addr2, typ, seen}
+		// ... or already seen
+		h := 17*addr1 + addr2
+		seen := visited[h]
+		typ := v1.Type()
+		for p := seen; p != nil; p = p.next {
+			if p.a1 == addr1 && p.a2 == addr2 && p.typ == typ {
+				return true
+			}
+		}
+
+		// Remember for later.
+		visited[h] = &visit{addr1, addr2, typ, seen}
+	}
 
 	switch v1.Kind() {
 	case Array:
@@ -116,8 +117,8 @@ func DeepEqual(a1, a2 interface{}) bool {
 	if a1 == nil || a2 == nil {
 		return a1 == a2
 	}
-	v1 := NewValue(a1)
-	v2 := NewValue(a2)
+	v1 := ValueOf(a1)
+	v2 := ValueOf(a2)
 	if v1.Type() != v2.Type() {
 		return false
 	}
diff --git a/src/pkg/reflect/set_test.go b/src/pkg/reflect/set_test.go
new file mode 100644
index 0000000..8135a4c
--- /dev/null
+++ b/src/pkg/reflect/set_test.go
@@ -0,0 +1,211 @@
+// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package reflect_test
+
+import (
+	"bytes"
+	"go/ast"
+	"io"
+	. "reflect"
+	"testing"
+	"unsafe"
+)
+
+type MyBuffer bytes.Buffer
+
+func TestImplicitMapConversion(t *testing.T) {
+	// Test implicit conversions in MapIndex and SetMapIndex.
+	{
+		// direct
+		m := make(map[int]int)
+		mv := ValueOf(m)
+		mv.SetMapIndex(ValueOf(1), ValueOf(2))
+		x, ok := m[1]
+		if x != 2 {
+			t.Errorf("#1 after SetMapIndex(1,2): %d, %t (map=%v)", x, ok, m)
+		}
+		if n := mv.MapIndex(ValueOf(1)).Interface().(int); n != 2 {
+			t.Errorf("#1 MapIndex(1) = %d", n)
+		}
+	}
+	{
+		// convert interface key
+		m := make(map[interface{}]int)
+		mv := ValueOf(m)
+		mv.SetMapIndex(ValueOf(1), ValueOf(2))
+		x, ok := m[1]
+		if x != 2 {
+			t.Errorf("#2 after SetMapIndex(1,2): %d, %t (map=%v)", x, ok, m)
+		}
+		if n := mv.MapIndex(ValueOf(1)).Interface().(int); n != 2 {
+			t.Errorf("#2 MapIndex(1) = %d", n)
+		}
+	}
+	{
+		// convert interface value
+		m := make(map[int]interface{})
+		mv := ValueOf(m)
+		mv.SetMapIndex(ValueOf(1), ValueOf(2))
+		x, ok := m[1]
+		if x != 2 {
+			t.Errorf("#3 after SetMapIndex(1,2): %d, %t (map=%v)", x, ok, m)
+		}
+		if n := mv.MapIndex(ValueOf(1)).Interface().(int); n != 2 {
+			t.Errorf("#3 MapIndex(1) = %d", n)
+		}
+	}
+	{
+		// convert both interface key and interface value
+		m := make(map[interface{}]interface{})
+		mv := ValueOf(m)
+		mv.SetMapIndex(ValueOf(1), ValueOf(2))
+		x, ok := m[1]
+		if x != 2 {
+			t.Errorf("#4 after SetMapIndex(1,2): %d, %t (map=%v)", x, ok, m)
+		}
+		if n := mv.MapIndex(ValueOf(1)).Interface().(int); n != 2 {
+			t.Errorf("#4 MapIndex(1) = %d", n)
+		}
+	}
+	{
+		// convert both, with non-empty interfaces
+		m := make(map[io.Reader]io.Writer)
+		mv := ValueOf(m)
+		b1 := new(bytes.Buffer)
+		b2 := new(bytes.Buffer)
+		mv.SetMapIndex(ValueOf(b1), ValueOf(b2))
+		x, ok := m[b1]
+		if x != b2 {
+			t.Errorf("#5 after SetMapIndex(b1, b2): %p (!= %p), %t (map=%v)", x, b2, ok, m)
+		}
+		if p := mv.MapIndex(ValueOf(b1)).Elem().Pointer(); p != uintptr(unsafe.Pointer(b2)) {
+			t.Errorf("#5 MapIndex(b1) = %p want %p", p, b2)
+		}
+	}
+	{
+		// convert channel direction	
+		m := make(map[<-chan int]chan int)
+		mv := ValueOf(m)
+		c1 := make(chan int)
+		c2 := make(chan int)
+		mv.SetMapIndex(ValueOf(c1), ValueOf(c2))
+		x, ok := m[c1]
+		if x != c2 {
+			t.Errorf("#6 after SetMapIndex(c1, c2): %p (!= %p), %t (map=%v)", x, c2, ok, m)
+		}
+		if p := mv.MapIndex(ValueOf(c1)).Pointer(); p != ValueOf(c2).Pointer() {
+			t.Errorf("#6 MapIndex(c1) = %p want %p", p, c2)
+		}
+	}
+	{
+		// convert identical underlying types
+		// TODO(rsc): Should be able to define MyBuffer here.
+		// 6l prints very strange messages about .this.Bytes etc
+		// when we do that though, so MyBuffer is defined
+		// at top level.
+		m := make(map[*MyBuffer]*bytes.Buffer)
+		mv := ValueOf(m)
+		b1 := new(MyBuffer)
+		b2 := new(bytes.Buffer)
+		mv.SetMapIndex(ValueOf(b1), ValueOf(b2))
+		x, ok := m[b1]
+		if x != b2 {
+			t.Errorf("#7 after SetMapIndex(b1, b2): %p (!= %p), %t (map=%v)", x, b2, ok, m)
+		}
+		if p := mv.MapIndex(ValueOf(b1)).Pointer(); p != uintptr(unsafe.Pointer(b2)) {
+			t.Errorf("#7 MapIndex(b1) = %p want %p", p, b2)
+		}
+	}
+
+}
+
+func TestImplicitSetConversion(t *testing.T) {
+	// Assume TestImplicitMapConversion covered the basics.
+	// Just make sure conversions are being applied at all.
+	var r io.Reader
+	b := new(bytes.Buffer)
+	rv := ValueOf(&r).Elem()
+	rv.Set(ValueOf(b))
+	if r != b {
+		t.Errorf("after Set: r=%T(%v)", r, r)
+	}
+}
+
+func TestImplicitSendConversion(t *testing.T) {
+	c := make(chan io.Reader, 10)
+	b := new(bytes.Buffer)
+	ValueOf(c).Send(ValueOf(b))
+	if bb := <-c; bb != b {
+		t.Errorf("Received %p != %p", bb, b)
+	}
+}
+
+func TestImplicitCallConversion(t *testing.T) {
+	// Arguments must be assignable to parameter types.
+	fv := ValueOf(io.WriteString)
+	b := new(bytes.Buffer)
+	fv.Call([]Value{ValueOf(b), ValueOf("hello world")})
+	if b.String() != "hello world" {
+		t.Errorf("After call: string=%q want %q", b.String(), "hello world")
+	}
+}
+
+func TestImplicitAppendConversion(t *testing.T) {
+	// Arguments must be assignable to the slice's element type.
+	s := []io.Reader{}
+	sv := ValueOf(&s).Elem()
+	b := new(bytes.Buffer)
+	sv.Set(Append(sv, ValueOf(b)))
+	if len(s) != 1 || s[0] != b {
+		t.Errorf("after append: s=%v want [%p]", s, b)
+	}
+}
+
+var implementsTests = []struct {
+	x interface{}
+	t interface{}
+	b bool
+}{
+	{new(*bytes.Buffer), new(io.Reader), true},
+	{new(bytes.Buffer), new(io.Reader), false},
+	{new(*bytes.Buffer), new(io.ReaderAt), false},
+	{new(*ast.Ident), new(ast.Expr), true},
+}
+
+func TestImplements(t *testing.T) {
+	for _, tt := range implementsTests {
+		xv := TypeOf(tt.x).Elem()
+		xt := TypeOf(tt.t).Elem()
+		if b := xv.Implements(xt); b != tt.b {
+			t.Errorf("(%s).Implements(%s) = %v, want %v", xv.String(), xt.String(), b, tt.b)
+		}
+	}
+}
+
+var assignableTests = []struct {
+	x interface{}
+	t interface{}
+	b bool
+}{
+	{new(chan int), new(<-chan int), true},
+	{new(<-chan int), new(chan int), false},
+	{new(*int), new(IntPtr), true},
+	{new(IntPtr), new(*int), true},
+	{new(IntPtr), new(IntPtr1), false},
+	// test runs implementsTests too
+}
+
+type IntPtr *int
+type IntPtr1 *int
+
+func TestAssignableTo(t *testing.T) {
+	for _, tt := range append(assignableTests, implementsTests...) {
+		xv := TypeOf(tt.x).Elem()
+		xt := TypeOf(tt.t).Elem()
+		if b := xv.AssignableTo(xt); b != tt.b {
+			t.Errorf("(%s).AssignableTo(%s) = %v, want %v", xv.String(), xt.String(), b, tt.b)
+		}
+	}
+}
diff --git a/src/pkg/reflect/type.go b/src/pkg/reflect/type.go
index 9f3e0bf..aef6370 100644
--- a/src/pkg/reflect/type.go
+++ b/src/pkg/reflect/type.go
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The reflect package implements run-time reflection, allowing a program to
-// manipulate objects with arbitrary types.  The typical use is to take a
-// value with static type interface{} and extract its dynamic type
-// information by calling Typeof, which returns a Type.
+// Package reflect implements run-time reflection, allowing a program to
+// manipulate objects with arbitrary types.  The typical use is to take a value
+// with static type interface{} and extract its dynamic type information by
+// calling TypeOf, which returns a Type.
 //
-// A call to NewValue returns a Value representing the run-time data.
+// A call to ValueOf returns a Value representing the run-time data.
 // Zero takes a Type and returns a Value representing a zero value
 // for that type.
 package reflect
@@ -47,7 +47,7 @@ type Type interface {
 	// method signature, without a receiver, and the Func field is nil.
 	Method(int) Method
 
-	// NumMethods returns the number of methods in the type's method set.
+	// NumMethod returns the number of methods in the type's method set.
 	NumMethod() int
 
 	// Name returns the type's name within its package.
@@ -73,6 +73,12 @@ type Type interface {
 	// Kind returns the specific kind of this type.
 	Kind() Kind
 
+	// Implements returns true if the type implements the interface type u.
+	Implements(u Type) bool
+
+	// AssignableTo returns true if a value of the type is assignable to type u.
+	AssignableTo(u Type) bool
+
 	// Methods applicable only to some types, depending on Kind.
 	// The methods allowed for each kind are:
 	//
@@ -162,6 +168,8 @@ type Type interface {
 	// It panics if i is not in the range [0, NumOut()).
 	Out(i int) Type
 
+	runtimeType() *runtime.Type
+	common() *commonType
 	uncommon() *uncommonType
 }
 
@@ -258,6 +266,7 @@ const (
 type arrayType struct {
 	commonType "array"
 	elem       *runtime.Type
+	slice      *runtime.Type
 	len        uintptr
 }
 
@@ -408,9 +417,12 @@ func (t *commonType) String() string { return *t.string }
 func (t *commonType) Size() uintptr { return t.size }
 
 func (t *commonType) Bits() int {
+	if t == nil {
+		panic("reflect: Bits of nil Type")
+	}
 	k := t.Kind()
 	if k < Int || k > Complex128 {
-		panic("reflect: Bits of non-arithmetic Type")
+		panic("reflect: Bits of non-arithmetic Type " + t.String())
 	}
 	return int(t.size) * 8
 }
@@ -431,12 +443,14 @@ func (t *uncommonType) Method(i int) (m Method) {
 	if p.name != nil {
 		m.Name = *p.name
 	}
+	flag := uint32(0)
 	if p.pkgPath != nil {
 		m.PkgPath = *p.pkgPath
+		flag |= flagRO
 	}
 	m.Type = toType(p.typ)
 	fn := p.tfn
-	m.Func = Value{&funcValue{value: value{m.Type, addr(&fn), canSet}}}
+	m.Func = valueFromIword(flag, m.Type, iword(fn))
 	return
 }
 
@@ -772,24 +786,32 @@ func (t *structType) FieldByNameFunc(match func(string) bool) (f StructField, pr
 }
 
 // Convert runtime type to reflect type.
-func toType(p *runtime.Type) Type {
+func toCommonType(p *runtime.Type) *commonType {
+	if p == nil {
+		return nil
+	}
 	type hdr struct {
 		x interface{}
 		t commonType
 	}
-	t := &(*hdr)(unsafe.Pointer(p)).t
-	return t.toType()
+	x := unsafe.Pointer(p)
+	if uintptr(x)&reflectFlags != 0 {
+		panic("invalid interface value")
+	}
+	return &(*hdr)(x).t
 }
 
-// Typeof returns the reflection Type of the value in the interface{}.
-func Typeof(i interface{}) Type {
-	type hdr struct {
-		typ *byte
-		val *commonType
+func toType(p *runtime.Type) Type {
+	if p == nil {
+		return nil
 	}
-	rt := unsafe.Typeof(i)
-	t := (*(*hdr)(unsafe.Pointer(&rt))).val
-	return t.toType()
+	return toCommonType(p).toType()
+}
+
+// TypeOf returns the reflection Type of the value in the interface{}.
+func TypeOf(i interface{}) Type {
+	eface := *(*emptyInterface)(unsafe.Pointer(&i))
+	return toType(eface.typ)
 }
 
 // ptrMap is the cache for PtrTo.
@@ -798,6 +820,16 @@ var ptrMap struct {
 	m map[*commonType]*ptrType
 }
 
+func (t *commonType) runtimeType() *runtime.Type {
+	// The runtime.Type always precedes the commonType in memory.
+	// Adjust pointer to find it.
+	var rt struct {
+		i  runtime.Type
+		ct commonType
+	}
+	return (*runtime.Type)(unsafe.Pointer(uintptr(unsafe.Pointer(t)) - uintptr(unsafe.Offsetof(rt.ct))))
+}
+
 // PtrTo returns the pointer type with element t.
 // For example, if t represents type Foo, PtrTo(t) represents *Foo.
 func PtrTo(t Type) Type {
@@ -862,3 +894,164 @@ func PtrTo(t Type) Type {
 	ptrMap.Unlock()
 	return p.commonType.toType()
 }
+
+func (t *commonType) Implements(u Type) bool {
+	if u == nil {
+		panic("reflect: nil type passed to Type.Implements")
+	}
+	if u.Kind() != Interface {
+		panic("reflect: non-interface type passed to Type.Implements")
+	}
+	return implements(u.(*commonType), t)
+}
+
+func (t *commonType) AssignableTo(u Type) bool {
+	if u == nil {
+		panic("reflect: nil type passed to Type.AssignableTo")
+	}
+	uu := u.(*commonType)
+	return directlyAssignable(uu, t) || implements(uu, t)
+}
+
+// implements returns true if the type V implements the interface type T.
+func implements(T, V *commonType) bool {
+	if T.Kind() != Interface {
+		return false
+	}
+	t := (*interfaceType)(unsafe.Pointer(T))
+	if len(t.methods) == 0 {
+		return true
+	}
+
+	// The same algorithm applies in both cases, but the
+	// method tables for an interface type and a concrete type
+	// are different, so the code is duplicated.
+	// In both cases the algorithm is a linear scan over the two
+	// lists - T's methods and V's methods - simultaneously.
+	// Since method tables are stored in a unique sorted order
+	// (alphabetical, with no duplicate method names), the scan
+	// through V's methods must hit a match for each of T's
+	// methods along the way, or else V does not implement T.
+	// This lets us run the scan in overall linear time instead of
+	// the quadratic time  a naive search would require.
+	// See also ../runtime/iface.c.
+	if V.Kind() == Interface {
+		v := (*interfaceType)(unsafe.Pointer(V))
+		i := 0
+		for j := 0; j < len(v.methods); j++ {
+			tm := &t.methods[i]
+			vm := &v.methods[j]
+			if vm.name == tm.name && vm.pkgPath == tm.pkgPath && vm.typ == tm.typ {
+				if i++; i >= len(t.methods) {
+					return true
+				}
+			}
+		}
+		return false
+	}
+
+	v := V.uncommon()
+	if v == nil {
+		return false
+	}
+	i := 0
+	for j := 0; j < len(v.methods); j++ {
+		tm := &t.methods[i]
+		vm := &v.methods[j]
+		if vm.name == tm.name && vm.pkgPath == tm.pkgPath && vm.mtyp == tm.typ {
+			if i++; i >= len(t.methods) {
+				return true
+			}
+		}
+	}
+	return false
+}
+
+// directlyAssignable returns true if a value x of type V can be directly
+// assigned (using memmove) to a value of type T.
+// http://golang.org/doc/go_spec.html#Assignability
+// Ignoring the interface rules (implemented elsewhere)
+// and the ideal constant rules (no ideal constants at run time).
+func directlyAssignable(T, V *commonType) bool {
+	// x's type V is identical to T?
+	if T == V {
+		return true
+	}
+
+	// Otherwise at least one of T and V must be unnamed
+	// and they must have the same kind.
+	if T.Name() != "" && V.Name() != "" || T.Kind() != V.Kind() {
+		return false
+	}
+
+	// x's type T and V have identical underlying types.
+	// Since at least one is unnamed, only the composite types
+	// need to be considered.
+	switch T.Kind() {
+	case Array:
+		return T.Elem() == V.Elem() && T.Len() == V.Len()
+
+	case Chan:
+		// Special case:
+		// x is a bidirectional channel value, T is a channel type,
+		// and x's type V and T have identical element types.
+		if V.ChanDir() == BothDir && T.Elem() == V.Elem() {
+			return true
+		}
+
+		// Otherwise continue test for identical underlying type.
+		return V.ChanDir() == T.ChanDir() && T.Elem() == V.Elem()
+
+	case Func:
+		t := (*funcType)(unsafe.Pointer(T))
+		v := (*funcType)(unsafe.Pointer(V))
+		if t.dotdotdot != v.dotdotdot || len(t.in) != len(v.in) || len(t.out) != len(v.out) {
+			return false
+		}
+		for i, typ := range t.in {
+			if typ != v.in[i] {
+				return false
+			}
+		}
+		for i, typ := range t.out {
+			if typ != v.out[i] {
+				return false
+			}
+		}
+		return true
+
+	case Interface:
+		t := (*interfaceType)(unsafe.Pointer(T))
+		v := (*interfaceType)(unsafe.Pointer(V))
+		if len(t.methods) == 0 && len(v.methods) == 0 {
+			return true
+		}
+		// Might have the same methods but still
+		// need a run time conversion.
+		return false
+
+	case Map:
+		return T.Key() == V.Key() && T.Elem() == V.Elem()
+
+	case Ptr, Slice:
+		return T.Elem() == V.Elem()
+
+	case Struct:
+		t := (*structType)(unsafe.Pointer(T))
+		v := (*structType)(unsafe.Pointer(V))
+		if len(t.fields) != len(v.fields) {
+			return false
+		}
+		for i := range t.fields {
+			tf := &t.fields[i]
+			vf := &v.fields[i]
+			if tf.name != vf.name || tf.pkgPath != vf.pkgPath ||
+				tf.typ != vf.typ || tf.tag != vf.tag || tf.offset != vf.offset {
+				return false
+			}
+		}
+		return true
+	}
+
+	return false
+}
diff --git a/src/pkg/reflect/value.go b/src/pkg/reflect/value.go
index ddc3110..6dffb07 100644
--- a/src/pkg/reflect/value.go
+++ b/src/pkg/reflect/value.go
@@ -7,17 +7,16 @@ package reflect
 import (
 	"math"
 	"runtime"
+	"strconv"
 	"unsafe"
 )
 
 const ptrSize = uintptr(unsafe.Sizeof((*byte)(nil)))
 const cannotSet = "cannot set value obtained from unexported struct field"
 
-type addr unsafe.Pointer
-
 // TODO: This will have to go away when
 // the new gc goes in.
-func memmove(adst, asrc addr, n uintptr) {
+func memmove(adst, asrc unsafe.Pointer, n uintptr) {
 	dst := uintptr(adst)
 	src := uintptr(asrc)
 	switch {
@@ -26,17 +25,17 @@ func memmove(adst, asrc addr, n uintptr) {
 		// careful: i is unsigned
 		for i := n; i > 0; {
 			i--
-			*(*byte)(addr(dst + i)) = *(*byte)(addr(src + i))
+			*(*byte)(unsafe.Pointer(dst + i)) = *(*byte)(unsafe.Pointer(src + i))
 		}
 	case (n|src|dst)&(ptrSize-1) != 0:
 		// byte copy forward
 		for i := uintptr(0); i < n; i++ {
-			*(*byte)(addr(dst + i)) = *(*byte)(addr(src + i))
+			*(*byte)(unsafe.Pointer(dst + i)) = *(*byte)(unsafe.Pointer(src + i))
 		}
 	default:
 		// word copy forward
 		for i := uintptr(0); i < n; i += ptrSize {
-			*(*uintptr)(addr(dst + i)) = *(*uintptr)(addr(src + i))
+			*(*uintptr)(unsafe.Pointer(dst + i)) = *(*uintptr)(unsafe.Pointer(src + i))
 		}
 	}
 }
@@ -54,15 +53,16 @@ func memmove(adst, asrc addr, n uintptr) {
 // its String method returns "<invalid Value>", and all other methods panic.
 // Most functions and methods never return an invalid value.
 // If one does, its documentation states the conditions explicitly.
+//
+// The fields of Value are exported so that clients can copy and
+// pass Values around, but they should not be edited or inspected
+// directly.  A future language change may make it possible not to
+// export these fields while still keeping Values usable as values.
 type Value struct {
-	Internal valueInterface
+	Internal       interface{}
+	InternalMethod int
 }
 
-// TODO(rsc): This implementation of Value is a just a façade
-// in front of the old implementation, now called valueInterface.
-// A future CL will change it to a real implementation.
-// Changing the API is already a big enough step for one CL.
-
 // A ValueError occurs when a Value method is invoked on
 // a Value that does not support it.  Such cases are documented
 // in the description of each method.
@@ -89,37 +89,292 @@ func methodName() string {
 	return f.Name()
 }
 
-func (v Value) internal() valueInterface {
-	vi := v.Internal
-	if vi == nil {
-		panic(&ValueError{methodName(), 0})
+// An iword is the word that would be stored in an
+// interface to represent a given value v.  Specifically, if v is
+// bigger than a pointer, its word is a pointer to v's data.
+// Otherwise, its word is a zero uintptr with the data stored
+// in the leading bytes.
+type iword uintptr
+
+func loadIword(p unsafe.Pointer, size uintptr) iword {
+	// Run the copy ourselves instead of calling memmove
+	// to avoid moving v to the heap.
+	w := iword(0)
+	switch size {
+	default:
+		panic("reflect: internal error: loadIword of " + strconv.Itoa(int(size)) + "-byte value")
+	case 0:
+	case 1:
+		*(*uint8)(unsafe.Pointer(&w)) = *(*uint8)(p)
+	case 2:
+		*(*uint16)(unsafe.Pointer(&w)) = *(*uint16)(p)
+	case 3:
+		*(*[3]byte)(unsafe.Pointer(&w)) = *(*[3]byte)(p)
+	case 4:
+		*(*uint32)(unsafe.Pointer(&w)) = *(*uint32)(p)
+	case 5:
+		*(*[5]byte)(unsafe.Pointer(&w)) = *(*[5]byte)(p)
+	case 6:
+		*(*[6]byte)(unsafe.Pointer(&w)) = *(*[6]byte)(p)
+	case 7:
+		*(*[7]byte)(unsafe.Pointer(&w)) = *(*[7]byte)(p)
+	case 8:
+		*(*uint64)(unsafe.Pointer(&w)) = *(*uint64)(p)
+	}
+	return w
+}
+
+func storeIword(p unsafe.Pointer, w iword, size uintptr) {
+	// Run the copy ourselves instead of calling memmove
+	// to avoid moving v to the heap.
+	switch size {
+	default:
+		panic("reflect: internal error: storeIword of " + strconv.Itoa(int(size)) + "-byte value")
+	case 0:
+	case 1:
+		*(*uint8)(p) = *(*uint8)(unsafe.Pointer(&w))
+	case 2:
+		*(*uint16)(p) = *(*uint16)(unsafe.Pointer(&w))
+	case 3:
+		*(*[3]byte)(p) = *(*[3]byte)(unsafe.Pointer(&w))
+	case 4:
+		*(*uint32)(p) = *(*uint32)(unsafe.Pointer(&w))
+	case 5:
+		*(*[5]byte)(p) = *(*[5]byte)(unsafe.Pointer(&w))
+	case 6:
+		*(*[6]byte)(p) = *(*[6]byte)(unsafe.Pointer(&w))
+	case 7:
+		*(*[7]byte)(p) = *(*[7]byte)(unsafe.Pointer(&w))
+	case 8:
+		*(*uint64)(p) = *(*uint64)(unsafe.Pointer(&w))
+	}
+}
+
+// emptyInterface is the header for an interface{} value.
+type emptyInterface struct {
+	typ  *runtime.Type
+	word iword
+}
+
+// nonEmptyInterface is the header for a interface value with methods.
+type nonEmptyInterface struct {
+	// see ../runtime/iface.c:/Itab
+	itab *struct {
+		ityp   *runtime.Type // static interface type
+		typ    *runtime.Type // dynamic concrete type
+		link   unsafe.Pointer
+		bad    int32
+		unused int32
+		fun    [100000]unsafe.Pointer // method table
+	}
+	word iword
+}
+
+// Regarding the implementation of Value:
+//
+// The Internal interface is a true interface value in the Go sense,
+// but it also serves as a (type, address) pair in whcih one cannot
+// be changed separately from the other.  That is, it serves as a way
+// to prevent unsafe mutations of the Internal state even though
+// we cannot (yet?) hide the field while preserving the ability for
+// clients to make copies of Values.
+//
+// The internal method converts a Value into the expanded internalValue struct.
+// If we could avoid exporting fields we'd probably make internalValue the
+// definition of Value.
+//
+// If a Value is addressable (CanAddr returns true), then the Internal
+// interface value holds a pointer to the actual field data, and Set stores
+// through that pointer.  If a Value is not addressable (CanAddr returns false),
+// then the Internal interface value holds the actual value.
+//
+// In addition to whether a value is addressable, we track whether it was
+// obtained by using an unexported struct field.  Such values are allowed
+// to be read, mainly to make fmt.Print more useful, but they are not
+// allowed to be written.  We call such values read-only.
+//
+// A Value can be set (via the Set, SetUint, etc. methods) only if it is both
+// addressable and not read-only.
+//
+// The two permission bits - addressable and read-only - are stored in
+// the bottom two bits of the type pointer in the interface value.
+//
+//	ordinary value: Internal = value
+//	addressable value: Internal = value, Internal.typ |= flagAddr
+//	read-only value: Internal = value, Internal.typ |= flagRO
+//	addressable, read-only value: Internal = value, Internal.typ |= flagAddr | flagRO
+//
+// It is important that the read-only values have the extra bit set
+// (as opposed to using the bit to mean writable), because client code
+// can grab the interface field and try to use it.  Having the extra bit
+// set makes the type pointer compare not equal to any real type,
+// so that a client cannot, say, write through v.Internal.(*int).
+// The runtime routines that access interface types reject types with
+// low bits set.
+//
+// If a Value fv = v.Method(i), then fv = v with the InternalMethod
+// field set to i+1.  Methods are never addressable.
+//
+// All in all, this is a lot of effort just to avoid making this new API
+// depend on a language change we'll probably do anyway, but
+// it's helpful to keep the two separate, and much of the logic is
+// necessary to implement the Interface method anyway.
+
+const (
+	flagAddr uint32 = 1 << iota // holds address of value
+	flagRO                      // read-only
+
+	reflectFlags = 3
+)
+
+// An internalValue is the unpacked form of a Value.
+// The zero Value unpacks to a zero internalValue
+type internalValue struct {
+	typ       *commonType // type of value
+	kind      Kind        // kind of value
+	flag      uint32
+	word      iword
+	addr      unsafe.Pointer
+	rcvr      iword
+	method    bool
+	nilmethod bool
+}
+
+func (v Value) internal() internalValue {
+	var iv internalValue
+	eface := *(*emptyInterface)(unsafe.Pointer(&v.Internal))
+	p := uintptr(unsafe.Pointer(eface.typ))
+	iv.typ = toCommonType((*runtime.Type)(unsafe.Pointer(p &^ reflectFlags)))
+	if iv.typ == nil {
+		return iv
+	}
+	iv.flag = uint32(p & reflectFlags)
+	iv.word = eface.word
+	if iv.flag&flagAddr != 0 {
+		iv.addr = unsafe.Pointer(iv.word)
+		iv.typ = iv.typ.Elem().common()
+		if iv.typ.size <= ptrSize {
+			iv.word = loadIword(iv.addr, iv.typ.size)
+		}
+	} else {
+		if iv.typ.size > ptrSize {
+			iv.addr = unsafe.Pointer(iv.word)
+		}
 	}
-	return vi
+	iv.kind = iv.typ.Kind()
+
+	// Is this a method?  If so, iv describes the receiver.
+	// Rewrite to describe the method function.
+	if v.InternalMethod != 0 {
+		// If this Value is a method value (x.Method(i) for some Value x)
+		// then we will invoke it using the interface form of the method,
+		// which always passes the receiver as a single word.
+		// Record that information.
+		i := v.InternalMethod - 1
+		if iv.kind == Interface {
+			it := (*interfaceType)(unsafe.Pointer(iv.typ))
+			if i < 0 || i >= len(it.methods) {
+				panic("reflect: broken Value")
+			}
+			m := &it.methods[i]
+			if m.pkgPath != nil {
+				iv.flag |= flagRO
+			}
+			iv.typ = toCommonType(m.typ)
+			iface := (*nonEmptyInterface)(iv.addr)
+			if iface.itab == nil {
+				iv.word = 0
+				iv.nilmethod = true
+			} else {
+				iv.word = iword(iface.itab.fun[i])
+			}
+			iv.rcvr = iface.word
+		} else {
+			ut := iv.typ.uncommon()
+			if ut == nil || i < 0 || i >= len(ut.methods) {
+				panic("reflect: broken Value")
+			}
+			m := &ut.methods[i]
+			if m.pkgPath != nil {
+				iv.flag |= flagRO
+			}
+			iv.typ = toCommonType(m.mtyp)
+			iv.rcvr = iv.word
+			iv.word = iword(m.ifn)
+		}
+		iv.kind = Func
+		iv.method = true
+		iv.flag &^= flagAddr
+		iv.addr = nil
+	}
+
+	return iv
 }
 
-func (v Value) panicIfNot(want Kind) valueInterface {
-	vi := v.Internal
-	if vi == nil {
-		panic(&ValueError{methodName(), 0})
+// packValue returns a Value with the given flag bits, type, and interface word.
+func packValue(flag uint32, typ *runtime.Type, word iword) Value {
+	if typ == nil {
+		panic("packValue")
 	}
-	if k := vi.Kind(); k != want {
-		panic(&ValueError{methodName(), k})
+	t := uintptr(unsafe.Pointer(typ))
+	t |= uintptr(flag)
+	eface := emptyInterface{(*runtime.Type)(unsafe.Pointer(t)), word}
+	return Value{Internal: *(*interface{})(unsafe.Pointer(&eface))}
+}
+
+// valueFromAddr returns a Value using the given type and address.
+func valueFromAddr(flag uint32, typ Type, addr unsafe.Pointer) Value {
+	if flag&flagAddr != 0 {
+		// Addressable, so the internal value is
+		// an interface containing a pointer to the real value.
+		return packValue(flag, PtrTo(typ).runtimeType(), iword(addr))
 	}
-	return vi
+
+	var w iword
+	if n := typ.Size(); n <= ptrSize {
+		// In line, so the interface word is the actual value.
+		w = loadIword(addr, n)
+	} else {
+		// Not in line: the interface word is the address.
+		w = iword(addr)
+	}
+	return packValue(flag, typ.runtimeType(), w)
 }
 
-func (v Value) panicIfNots(wants []Kind) valueInterface {
-	vi := v.Internal
-	if vi == nil {
-		panic(&ValueError{methodName(), 0})
+// valueFromIword returns a Value using the given type and interface word.
+func valueFromIword(flag uint32, typ Type, w iword) Value {
+	if flag&flagAddr != 0 {
+		panic("reflect: internal error: valueFromIword addressable")
 	}
-	k := vi.Kind()
-	for _, want := range wants {
-		if k == want {
-			return vi
-		}
+	return packValue(flag, typ.runtimeType(), w)
+}
+
+func (iv internalValue) mustBe(want Kind) {
+	if iv.kind != want {
+		panic(&ValueError{methodName(), iv.kind})
+	}
+}
+
+func (iv internalValue) mustBeExported() {
+	if iv.kind == 0 {
+		panic(&ValueError{methodName(), iv.kind})
+	}
+	if iv.flag&flagRO != 0 {
+		panic(methodName() + " using value obtained using unexported field")
+	}
+}
+
+func (iv internalValue) mustBeAssignable() {
+	if iv.kind == 0 {
+		panic(&ValueError{methodName(), iv.kind})
+	}
+	// Assignable if addressable and not read-only.
+	if iv.flag&flagRO != 0 {
+		panic(methodName() + " using value obtained using unexported field")
+	}
+	if iv.flag&flagAddr == 0 {
+		panic(methodName() + " using unaddressable value")
 	}
-	panic(&ValueError{methodName(), k})
 }
 
 // Addr returns a pointer value representing the address of v.
@@ -128,56 +383,142 @@ func (v Value) panicIfNots(wants []Kind) valueInterface {
 // or slice element in order to call a method that requires a
 // pointer receiver.
 func (v Value) Addr() Value {
-	return v.internal().Addr()
+	iv := v.internal()
+	if iv.flag&flagAddr == 0 {
+		panic("reflect.Value.Addr of unaddressable value")
+	}
+	return valueFromIword(iv.flag&flagRO, PtrTo(iv.typ.toType()), iword(iv.addr))
 }
 
 // Bool returns v's underlying value.
 // It panics if v's kind is not Bool.
 func (v Value) Bool() bool {
-	u := v.panicIfNot(Bool).(*boolValue)
-	return *(*bool)(u.addr)
+	iv := v.internal()
+	iv.mustBe(Bool)
+	return *(*bool)(unsafe.Pointer(&iv.word))
 }
 
 // CanAddr returns true if the value's address can be obtained with Addr.
 // Such values are called addressable.  A value is addressable if it is
 // an element of a slice, an element of an addressable array,
-// a field of an addressable struct, the result of dereferencing a pointer,
-// or the result of a call to NewValue, MakeChan, MakeMap, or Zero.
+// a field of an addressable struct, or the result of dereferencing a pointer.
 // If CanAddr returns false, calling Addr will panic.
 func (v Value) CanAddr() bool {
-	return v.internal().CanAddr()
+	iv := v.internal()
+	return iv.flag&flagAddr != 0
 }
 
 // CanSet returns true if the value of v can be changed.
-// Values obtained by the use of unexported struct fields
-// can be read but not set.
+// A Value can be changed only if it is addressable and was not
+// obtained by the use of unexported struct fields.
 // If CanSet returns false, calling Set or any type-specific
 // setter (e.g., SetBool, SetInt64) will panic.
 func (v Value) CanSet() bool {
-	return v.internal().CanSet()
-}
-
-// Call calls the function v with the input parameters in.
-// It panics if v's Kind is not Func.
-// It returns the output parameters as Values.
+	iv := v.internal()
+	return iv.flag&(flagAddr|flagRO) == flagAddr
+}
+
+// Call calls the function v with the input arguments in.
+// For example, if len(in) == 3, v.Call(in) represents the Go call v(in[0], in[1], in[2]).
+// Call panics if v's Kind is not Func.
+// It returns the output results as Values.
+// As in Go, each input argument must be assignable to the
+// type of the function's corresponding input parameter.
+// If v is a variadic function, Call creates the variadic slice parameter
+// itself, copying in the corresponding values.
 func (v Value) Call(in []Value) []Value {
-	fv := v.panicIfNot(Func).(*funcValue)
-	t := fv.Type()
-	nin := len(in)
-	if fv.first != nil && !fv.isInterface {
-		nin++
+	iv := v.internal()
+	iv.mustBe(Func)
+	iv.mustBeExported()
+	return iv.call("Call", in)
+}
+
+// CallSlice calls the variadic function v with the input arguments in,
+// assigning the slice in[len(in)-1] to v's final variadic argument.  
+// For example, if len(in) == 3, v.Call(in) represents the Go call v(in[0], in[1], in[2]...).
+// Call panics if v's Kind is not Func or if v is not variadic.
+// It returns the output results as Values.
+// As in Go, each input argument must be assignable to the
+// type of the function's corresponding input parameter.
+func (v Value) CallSlice(in []Value) []Value {
+	iv := v.internal()
+	iv.mustBe(Func)
+	iv.mustBeExported()
+	return iv.call("CallSlice", in)
+}
+
+func (iv internalValue) call(method string, in []Value) []Value {
+	if iv.word == 0 {
+		if iv.nilmethod {
+			panic("reflect.Value.Call: call of method on nil interface value")
+		}
+		panic("reflect.Value.Call: call of nil function")
+	}
+
+	isSlice := method == "CallSlice"
+	t := iv.typ
+	n := t.NumIn()
+	if isSlice {
+		if !t.IsVariadic() {
+			panic("reflect: CallSlice of non-variadic function")
+		}
+		if len(in) < n {
+			panic("reflect: CallSlice with too few input arguments")
+		}
+		if len(in) > n {
+			panic("reflect: CallSlice with too many input arguments")
+		}
+	} else {
+		if t.IsVariadic() {
+			n--
+		}
+		if len(in) < n {
+			panic("reflect: Call with too few input arguments")
+		}
+		if !t.IsVariadic() && len(in) > n {
+			panic("reflect: Call with too many input arguments")
+		}
+	}
+	for _, x := range in {
+		if x.Kind() == Invalid {
+			panic("reflect: " + method + " using zero Value argument")
+		}
 	}
+	for i := 0; i < n; i++ {
+		if xt, targ := in[i].Type(), t.In(i); !xt.AssignableTo(targ) {
+			panic("reflect: " + method + " using " + xt.String() + " as type " + targ.String())
+		}
+	}
+	if !isSlice && t.IsVariadic() {
+		// prepare slice for remaining values
+		m := len(in) - n
+		slice := MakeSlice(t.In(n), m, m)
+		elem := t.In(n).Elem()
+		for i := 0; i < m; i++ {
+			x := in[n+i]
+			if xt := x.Type(); !xt.AssignableTo(elem) {
+				panic("reflect: cannot use " + xt.String() + " as type " + elem.String() + " in " + method)
+			}
+			slice.Index(i).Set(x)
+		}
+		origIn := in
+		in = make([]Value, n+1)
+		copy(in[:n], origIn)
+		in[n] = slice
+	}
+
+	nin := len(in)
 	if nin != t.NumIn() {
-		panic("funcValue: wrong argument count")
+		panic("reflect.Value.Call: wrong argument count")
 	}
 	nout := t.NumOut()
 
 	// Compute arg size & allocate.
-	// This computation is 6g/8g-dependent
+	// This computation is 5g/6g/8g-dependent
 	// and probably wrong for gccgo, but so
 	// is most of this function.
 	size := uintptr(0)
-	if fv.isInterface {
+	if iv.method {
 		// extra word for interface value
 		size += ptrSize
 	}
@@ -215,36 +556,31 @@ func (v Value) Call(in []Value) []Value {
 	args := make([]*int, size/ptrSize)
 	ptr := uintptr(unsafe.Pointer(&args[0]))
 	off := uintptr(0)
-	delta := 0
-	if v := fv.first; v != nil {
+	if iv.method {
 		// Hard-wired first argument.
-		if fv.isInterface {
-			// v is a single uninterpreted word
-			memmove(addr(ptr), v.getAddr(), ptrSize)
-			off = ptrSize
-		} else {
-			// v is a real value
-			tv := v.Type()
-			typesMustMatch(t.In(0), tv)
-			n := tv.Size()
-			memmove(addr(ptr), v.getAddr(), n)
-			off = n
-			delta = 1
-		}
+		*(*iword)(unsafe.Pointer(ptr)) = iv.rcvr
+		off = ptrSize
 	}
 	for i, v := range in {
-		tv := v.Type()
-		typesMustMatch(t.In(i+delta), tv)
-		a := uintptr(tv.Align())
+		iv := v.internal()
+		iv.mustBeExported()
+		targ := t.In(i).(*commonType)
+		a := uintptr(targ.align)
 		off = (off + a - 1) &^ (a - 1)
-		n := tv.Size()
-		memmove(addr(ptr+off), v.internal().getAddr(), n)
+		n := targ.size
+		addr := unsafe.Pointer(ptr + off)
+		iv = convertForAssignment("reflect.Value.Call", addr, targ, iv)
+		if iv.addr == nil {
+			storeIword(addr, iv.word, n)
+		} else {
+			memmove(addr, iv.addr, n)
+		}
 		off += n
 	}
 	off = (off + ptrSize - 1) &^ (ptrSize - 1)
 
-	// Call
-	call(*(**byte)(fv.addr), (*byte)(addr(ptr)), uint32(size))
+	// Call.
+	call(unsafe.Pointer(iv.word), unsafe.Pointer(ptr), uint32(size))
 
 	// Copy return values out of args.
 	//
@@ -254,111 +590,148 @@ func (v Value) Call(in []Value) []Value {
 		tv := t.Out(i)
 		a := uintptr(tv.Align())
 		off = (off + a - 1) &^ (a - 1)
-		v := Zero(tv)
-		n := tv.Size()
-		memmove(v.internal().getAddr(), addr(ptr+off), n)
-		ret[i] = v
-		off += n
+		ret[i] = valueFromAddr(0, tv, unsafe.Pointer(ptr+off))
+		off += tv.Size()
 	}
 
 	return ret
 }
 
-var capKinds = []Kind{Array, Chan, Slice}
-
 // Cap returns v's capacity.
 // It panics if v's Kind is not Array, Chan, or Slice.
 func (v Value) Cap() int {
-	switch vv := v.panicIfNots(capKinds).(type) {
-	case *arrayValue:
-		return vv.typ.Len()
-	case *chanValue:
-		ch := *(**byte)(vv.addr)
-		return int(chancap(ch))
-	case *sliceValue:
-		return int(vv.slice().Cap)
+	iv := v.internal()
+	switch iv.kind {
+	case Array:
+		return iv.typ.Len()
+	case Chan:
+		return int(chancap(iv.word))
+	case Slice:
+		return (*SliceHeader)(iv.addr).Cap
 	}
-	panic("not reached")
+	panic(&ValueError{"reflect.Value.Cap", iv.kind})
 }
 
 // Close closes the channel v.
 // It panics if v's Kind is not Chan.
 func (v Value) Close() {
-	vv := v.panicIfNot(Chan).(*chanValue)
-
-	ch := *(**byte)(vv.addr)
+	iv := v.internal()
+	iv.mustBe(Chan)
+	iv.mustBeExported()
+	ch := iv.word
 	chanclose(ch)
 }
 
-var complexKinds = []Kind{Complex64, Complex128}
-
 // Complex returns v's underlying value, as a complex128.
 // It panics if v's Kind is not Complex64 or Complex128
 func (v Value) Complex() complex128 {
-	vv := v.panicIfNots(complexKinds).(*complexValue)
-
-	switch vv.typ.Kind() {
+	iv := v.internal()
+	switch iv.kind {
 	case Complex64:
-		return complex128(*(*complex64)(vv.addr))
+		if iv.addr == nil {
+			return complex128(*(*complex64)(unsafe.Pointer(&iv.word)))
+		}
+		return complex128(*(*complex64)(iv.addr))
 	case Complex128:
-		return *(*complex128)(vv.addr)
+		return *(*complex128)(iv.addr)
 	}
-	panic("reflect: invalid complex kind")
+	panic(&ValueError{"reflect.Value.Complex", iv.kind})
 }
 
-var interfaceOrPtr = []Kind{Interface, Ptr}
-
 // Elem returns the value that the interface v contains
 // or that the pointer v points to.
 // It panics if v's Kind is not Interface or Ptr.
 // It returns the zero Value if v is nil.
 func (v Value) Elem() Value {
-	switch vv := v.panicIfNots(interfaceOrPtr).(type) {
-	case *interfaceValue:
-		return NewValue(vv.Interface())
-	case *ptrValue:
-		if v.IsNil() {
+	iv := v.internal()
+	return iv.Elem()
+}
+
+func (iv internalValue) Elem() Value {
+	switch iv.kind {
+	case Interface:
+		// Empty interface and non-empty interface have different layouts.
+		// Convert to empty interface.
+		var eface emptyInterface
+		if iv.typ.NumMethod() == 0 {
+			eface = *(*emptyInterface)(iv.addr)
+		} else {
+			iface := (*nonEmptyInterface)(iv.addr)
+			if iface.itab != nil {
+				eface.typ = iface.itab.typ
+			}
+			eface.word = iface.word
+		}
+		if eface.typ == nil {
 			return Value{}
 		}
-		flag := canAddr
-		if vv.flag&canStore != 0 {
-			flag |= canSet | canStore
+		return valueFromIword(iv.flag&flagRO, toType(eface.typ), eface.word)
+
+	case Ptr:
+		// The returned value's address is v's value.
+		if iv.word == 0 {
+			return Value{}
 		}
-		return newValue(vv.typ.Elem(), *(*addr)(vv.addr), flag)
+		return valueFromAddr(iv.flag&flagRO|flagAddr, iv.typ.Elem(), unsafe.Pointer(iv.word))
 	}
-	panic("not reached")
+	panic(&ValueError{"reflect.Value.Elem", iv.kind})
 }
 
 // Field returns the i'th field of the struct v.
-// It panics if v's Kind is not Struct.
+// It panics if v's Kind is not Struct or i is out of range.
 func (v Value) Field(i int) Value {
-	vv := v.panicIfNot(Struct).(*structValue)
-
-	t := vv.typ
+	iv := v.internal()
+	iv.mustBe(Struct)
+	t := iv.typ.toType()
 	if i < 0 || i >= t.NumField() {
 		panic("reflect: Field index out of range")
 	}
 	f := t.Field(i)
-	flag := vv.flag
+
+	// Inherit permission bits from v.
+	flag := iv.flag
+	// Using an unexported field forces flagRO.
 	if f.PkgPath != "" {
-		// unexported field
-		flag &^= canSet | canStore
+		flag |= flagRO
 	}
-	return newValue(f.Type, addr(uintptr(vv.addr)+f.Offset), flag)
+	return valueFromValueOffset(flag, f.Type, iv, f.Offset)
+}
+
+// valueFromValueOffset returns a sub-value of outer
+// (outer is an array or a struct) with the given flag and type
+// starting at the given byte offset into outer.
+func valueFromValueOffset(flag uint32, typ Type, outer internalValue, offset uintptr) Value {
+	if outer.addr != nil {
+		return valueFromAddr(flag, typ, unsafe.Pointer(uintptr(outer.addr)+offset))
+	}
+
+	// outer is so tiny it is in line.
+	// We have to use outer.word and derive
+	// the new word (it cannot possibly be bigger).
+	// In line, so not addressable.
+	if flag&flagAddr != 0 {
+		panic("reflect: internal error: misuse of valueFromValueOffset")
+	}
+	b := *(*[ptrSize]byte)(unsafe.Pointer(&outer.word))
+	for i := uintptr(0); i < typ.Size(); i++ {
+		b[i] = b[offset+i]
+	}
+	for i := typ.Size(); i < ptrSize; i++ {
+		b[i] = 0
+	}
+	w := *(*iword)(unsafe.Pointer(&b))
+	return valueFromIword(flag, typ, w)
 }
 
 // FieldByIndex returns the nested field corresponding to index.
 // It panics if v's Kind is not struct.
 func (v Value) FieldByIndex(index []int) Value {
-	v.panicIfNot(Struct)
+	v.internal().mustBe(Struct)
 	for i, x := range index {
 		if i > 0 {
-			if v.Kind() == Ptr {
+			if v.Kind() == Ptr && v.Elem().Kind() == Struct {
 				v = v.Elem()
 			}
-			if v.Kind() != Struct {
-				return Value{}
-			}
 		}
 		v = v.Field(x)
 	}
@@ -369,7 +742,9 @@ func (v Value) FieldByIndex(index []int) Value {
 // It returns the zero Value if no field was found.
 // It panics if v's Kind is not struct.
 func (v Value) FieldByName(name string) Value {
-	if f, ok := v.Type().FieldByName(name); ok {
+	iv := v.internal()
+	iv.mustBe(Struct)
+	if f, ok := iv.typ.FieldByName(name); ok {
 		return v.FieldByIndex(f.Index)
 	}
 	return Value{}
@@ -380,79 +755,100 @@ func (v Value) FieldByName(name string) Value {
 // It panics if v's Kind is not struct.
 // It returns the zero Value if no field was found.
 func (v Value) FieldByNameFunc(match func(string) bool) Value {
+	v.internal().mustBe(Struct)
 	if f, ok := v.Type().FieldByNameFunc(match); ok {
 		return v.FieldByIndex(f.Index)
 	}
 	return Value{}
 }
 
-var floatKinds = []Kind{Float32, Float64}
-
 // Float returns v's underlying value, as an float64.
 // It panics if v's Kind is not Float32 or Float64
 func (v Value) Float() float64 {
-	vv := v.panicIfNots(floatKinds).(*floatValue)
-
-	switch vv.typ.Kind() {
+	iv := v.internal()
+	switch iv.kind {
 	case Float32:
-		return float64(*(*float32)(vv.addr))
+		return float64(*(*float32)(unsafe.Pointer(&iv.word)))
 	case Float64:
-		return *(*float64)(vv.addr)
+		// If the pointer width can fit an entire float64,
+		// the value is in line when stored in an interface.
+		if iv.addr == nil {
+			return *(*float64)(unsafe.Pointer(&iv.word))
+		}
+		// Otherwise we have a pointer.
+		return *(*float64)(iv.addr)
 	}
-	panic("reflect: invalid float kind")
-
+	panic(&ValueError{"reflect.Value.Float", iv.kind})
 }
 
-var arrayOrSlice = []Kind{Array, Slice}
-
 // Index returns v's i'th element.
-// It panics if v's Kind is not Array or Slice.
+// It panics if v's Kind is not Array or Slice or i is out of range.
 func (v Value) Index(i int) Value {
-	switch vv := v.panicIfNots(arrayOrSlice).(type) {
-	case *arrayValue:
-		typ := vv.typ.Elem()
-		n := v.Len()
-		if i < 0 || i >= n {
-			panic("array index out of bounds")
+	iv := v.internal()
+	switch iv.kind {
+	default:
+		panic(&ValueError{"reflect.Value.Index", iv.kind})
+	case Array:
+		flag := iv.flag // element flag same as overall array
+		t := iv.typ.toType()
+		if i < 0 || i > t.Len() {
+			panic("reflect: array index out of range")
 		}
-		p := addr(uintptr(vv.addr()) + uintptr(i)*typ.Size())
-		return newValue(typ, p, vv.flag)
-	case *sliceValue:
-		typ := vv.typ.Elem()
-		n := v.Len()
-		if i < 0 || i >= n {
+		typ := t.Elem()
+		return valueFromValueOffset(flag, typ, iv, uintptr(i)*typ.Size())
+
+	case Slice:
+		// Element flag same as Elem of Ptr.
+		// Addressable, possibly read-only.
+		flag := iv.flag&flagRO | flagAddr
+		s := (*SliceHeader)(iv.addr)
+		if i < 0 || i >= s.Len {
 			panic("reflect: slice index out of range")
 		}
-		p := addr(uintptr(vv.addr()) + uintptr(i)*typ.Size())
-		flag := canAddr
-		if vv.flag&canStore != 0 {
-			flag |= canSet | canStore
-		}
-		return newValue(typ, p, flag)
+		typ := iv.typ.Elem()
+		addr := unsafe.Pointer(s.Data + uintptr(i)*typ.Size())
+		return valueFromAddr(flag, typ, addr)
 	}
+
 	panic("not reached")
 }
 
-var intKinds = []Kind{Int, Int8, Int16, Int32, Int64}
-
 // Int returns v's underlying value, as an int64.
-// It panics if v's Kind is not a sized or unsized Int kind.
+// It panics if v's Kind is not Int, Int8, Int16, Int32, or Int64.
 func (v Value) Int() int64 {
-	vv := v.panicIfNots(intKinds).(*intValue)
-
-	switch vv.typ.Kind() {
+	iv := v.internal()
+	switch iv.kind {
 	case Int:
-		return int64(*(*int)(vv.addr))
+		return int64(*(*int)(unsafe.Pointer(&iv.word)))
 	case Int8:
-		return int64(*(*int8)(vv.addr))
+		return int64(*(*int8)(unsafe.Pointer(&iv.word)))
 	case Int16:
-		return int64(*(*int16)(vv.addr))
+		return int64(*(*int16)(unsafe.Pointer(&iv.word)))
 	case Int32:
-		return int64(*(*int32)(vv.addr))
+		return int64(*(*int32)(unsafe.Pointer(&iv.word)))
 	case Int64:
-		return *(*int64)(vv.addr)
+		if iv.addr == nil {
+			return *(*int64)(unsafe.Pointer(&iv.word))
+		}
+		return *(*int64)(iv.addr)
 	}
-	panic("reflect: invalid int kind")
+	panic(&ValueError{"reflect.Value.Int", iv.kind})
+}
+
+// CanInterface returns true if Interface can be used without panicking.
+func (v Value) CanInterface() bool {
+	iv := v.internal()
+	if iv.kind == Invalid {
+		panic(&ValueError{"reflect.Value.CanInterface", iv.kind})
+	}
+	// TODO(rsc): Check flagRO too.  Decide what to do about asking for
+	// interface for a value obtained via an unexported field.
+	// If the field were of a known type, say chan int or *sync.Mutex,
+	// the caller could interfere with the data after getting the
+	// interface.  But fmt.Print depends on being able to look.
+	// Now that reflect is more efficient the special cases in fmt
+	// might be less important.
+	return v.InternalMethod == 0
 }
 
 // Interface returns v's value as an interface{}.
@@ -463,34 +859,62 @@ func (v Value) Interface() interface{} {
 	return v.internal().Interface()
 }
 
+func (iv internalValue) Interface() interface{} {
+	if iv.method {
+		panic("reflect.Value.Interface: cannot create interface value for method with bound receiver")
+	}
+	/*
+		if v.flag()&noExport != 0 {
+			panic("reflect.Value.Interface: cannot return value obtained from unexported struct field")
+		}
+	*/
+
+	if iv.kind == Interface {
+		// Special case: return the element inside the interface.
+		// Won't recurse further because an interface cannot contain an interface.
+		if iv.IsNil() {
+			return nil
+		}
+		return iv.Elem().Interface()
+	}
+
+	// Non-interface value.
+	var eface emptyInterface
+	eface.typ = iv.typ.runtimeType()
+	eface.word = iv.word
+	return *(*interface{})(unsafe.Pointer(&eface))
+}
+
 // InterfaceData returns the interface v's value as a uintptr pair.
 // It panics if v's Kind is not Interface.
 func (v Value) InterfaceData() [2]uintptr {
-	vv := v.panicIfNot(Interface).(*interfaceValue)
-
-	return *(*[2]uintptr)(vv.addr)
+	iv := v.internal()
+	iv.mustBe(Interface)
+	// We treat this as a read operation, so we allow
+	// it even for unexported data, because the caller
+	// has to import "unsafe" to turn it into something
+	// that can be abused.
+	return *(*[2]uintptr)(iv.addr)
 }
 
-var nilKinds = []Kind{Chan, Func, Interface, Map, Ptr, Slice}
-
 // IsNil returns true if v is a nil value.
 // It panics if v's Kind is not Chan, Func, Interface, Map, Ptr, or Slice.
 func (v Value) IsNil() bool {
-	switch vv := v.panicIfNots(nilKinds).(type) {
-	case *chanValue:
-		return *(*uintptr)(vv.addr) == 0
-	case *funcValue:
-		return *(*uintptr)(vv.addr) == 0
-	case *interfaceValue:
-		return vv.Interface() == nil
-	case *mapValue:
-		return *(*uintptr)(vv.addr) == 0
-	case *ptrValue:
-		return *(*uintptr)(vv.addr) == 0
-	case *sliceValue:
-		return vv.slice().Data == 0
+	return v.internal().IsNil()
+}
+
+func (iv internalValue) IsNil() bool {
+	switch iv.kind {
+	case Chan, Func, Map, Ptr:
+		if iv.method {
+			panic("reflect: IsNil of method Value")
+		}
+		return iv.word == 0
+	case Interface, Slice:
+		// Both interface and slice are nil if first word is 0.
+		return *(*uintptr)(iv.addr) == 0
 	}
-	panic("not reached")
+	panic(&ValueError{"reflect.Value.IsNil", iv.kind})
 }
 
 // IsValid returns true if v represents a value.
@@ -505,169 +929,179 @@ func (v Value) IsValid() bool {
 // Kind returns v's Kind.
 // If v is the zero Value (IsValid returns false), Kind returns Invalid.
 func (v Value) Kind() Kind {
-	if v.Internal == nil {
-		return Invalid
-	}
-	return v.internal().Kind()
+	return v.internal().kind
 }
 
-var lenKinds = []Kind{Array, Chan, Map, Slice}
-
 // Len returns v's length.
 // It panics if v's Kind is not Array, Chan, Map, or Slice.
 func (v Value) Len() int {
-	switch vv := v.panicIfNots(lenKinds).(type) {
-	case *arrayValue:
-		return vv.typ.Len()
-	case *chanValue:
-		ch := *(**byte)(vv.addr)
-		return int(chanlen(ch))
-	case *mapValue:
-		m := *(**byte)(vv.addr)
-		if m == nil {
-			return 0
-		}
-		return int(maplen(m))
-	case *sliceValue:
-		return int(vv.slice().Len)
+	iv := v.internal()
+	switch iv.kind {
+	case Array:
+		return iv.typ.Len()
+	case Chan:
+		return int(chanlen(iv.word))
+	case Map:
+		return int(maplen(iv.word))
+	case Slice:
+		return (*SliceHeader)(iv.addr).Len
 	}
-	panic("not reached")
+	panic(&ValueError{"reflect.Value.Len", iv.kind})
 }
 
 // MapIndex returns the value associated with key in the map v.
 // It panics if v's Kind is not Map.
-// It returns the zero Value if key is not found in the map.
+// It returns the zero Value if key is not found in the map or if v represents a nil map.
+// As in Go, the key's value must be assignable to the map's key type.
 func (v Value) MapIndex(key Value) Value {
-	vv := v.panicIfNot(Map).(*mapValue)
-	t := vv.Type()
-	typesMustMatch(t.Key(), key.Type())
-	m := *(**byte)(vv.addr)
-	if m == nil {
+	iv := v.internal()
+	iv.mustBe(Map)
+	typ := iv.typ.toType()
+
+	ikey := key.internal()
+	ikey.mustBeExported()
+	ikey = convertForAssignment("reflect.Value.MapIndex", nil, typ.Key(), ikey)
+	if iv.word == 0 {
 		return Value{}
 	}
-	newval := Zero(t.Elem())
-	if !mapaccess(m, (*byte)(key.internal().getAddr()), (*byte)(newval.internal().getAddr())) {
+
+	flag := iv.flag & flagRO
+	elemType := typ.Elem()
+	elemWord, ok := mapaccess(iv.word, ikey.word)
+	if !ok {
 		return Value{}
 	}
-	return newval
+	return valueFromIword(flag, elemType, elemWord)
 }
 
 // MapKeys returns a slice containing all the keys present in the map,
 // in unspecified order.
 // It panics if v's Kind is not Map.
+// It returns an empty slice if v represents a nil map.
 func (v Value) MapKeys() []Value {
-	vv := v.panicIfNot(Map).(*mapValue)
-	tk := vv.Type().Key()
-	m := *(**byte)(vv.addr)
+	iv := v.internal()
+	iv.mustBe(Map)
+	keyType := iv.typ.Key()
+
+	flag := iv.flag & flagRO
+	m := iv.word
 	mlen := int32(0)
-	if m != nil {
+	if m != 0 {
 		mlen = maplen(m)
 	}
 	it := mapiterinit(m)
 	a := make([]Value, mlen)
 	var i int
 	for i = 0; i < len(a); i++ {
-		k := Zero(tk)
-		if !mapiterkey(it, (*byte)(k.internal().getAddr())) {
+		keyWord, ok := mapiterkey(it)
+		if !ok {
 			break
 		}
-		a[i] = k
+		a[i] = valueFromIword(flag, keyType, keyWord)
 		mapiternext(it)
 	}
-	return a[0:i]
+	return a[:i]
 }
 
 // Method returns a function value corresponding to v's i'th method.
 // The arguments to a Call on the returned function should not include
 // a receiver; the returned function will always use v as the receiver.
+// Method panics if i is out of range.
 func (v Value) Method(i int) Value {
-	return v.internal().Method(i)
+	iv := v.internal()
+	if iv.kind == Invalid {
+		panic(&ValueError{"reflect.Value.Method", Invalid})
+	}
+	if i < 0 || i >= iv.typ.NumMethod() {
+		panic("reflect: Method index out of range")
+	}
+	return Value{v.Internal, i + 1}
 }
 
 // NumField returns the number of fields in the struct v.
 // It panics if v's Kind is not Struct.
 func (v Value) NumField() int {
-	return v.panicIfNot(Struct).(*structValue).typ.NumField()
+	iv := v.internal()
+	iv.mustBe(Struct)
+	return iv.typ.NumField()
 }
 
 // OverflowComplex returns true if the complex128 x cannot be represented by v's type.
 // It panics if v's Kind is not Complex64 or Complex128.
 func (v Value) OverflowComplex(x complex128) bool {
-	vv := v.panicIfNots(complexKinds).(*complexValue)
-
-	if vv.typ.Size() == 16 {
+	iv := v.internal()
+	switch iv.kind {
+	case Complex64:
+		return overflowFloat32(real(x)) || overflowFloat32(imag(x))
+	case Complex128:
 		return false
 	}
-	r := real(x)
-	i := imag(x)
-	if r < 0 {
-		r = -r
-	}
-	if i < 0 {
-		i = -i
-	}
-	return math.MaxFloat32 <= r && r <= math.MaxFloat64 ||
-		math.MaxFloat32 <= i && i <= math.MaxFloat64
+	panic(&ValueError{"reflect.Value.OverflowComplex", iv.kind})
 }
 
 // OverflowFloat returns true if the float64 x cannot be represented by v's type.
 // It panics if v's Kind is not Float32 or Float64.
 func (v Value) OverflowFloat(x float64) bool {
-	vv := v.panicIfNots(floatKinds).(*floatValue)
-
-	if vv.typ.Size() == 8 {
+	iv := v.internal()
+	switch iv.kind {
+	case Float32:
+		return overflowFloat32(x)
+	case Float64:
 		return false
 	}
+	panic(&ValueError{"reflect.Value.OverflowFloat", iv.kind})
+}
+
+func overflowFloat32(x float64) bool {
 	if x < 0 {
 		x = -x
 	}
-	return math.MaxFloat32 < x && x <= math.MaxFloat64
+	return math.MaxFloat32 <= x && x <= math.MaxFloat64
 }
 
 // OverflowInt returns true if the int64 x cannot be represented by v's type.
-// It panics if v's Kind is not a sized or unsized Int kind.
+// It panics if v's Kind is not Int, Int8, int16, Int32, or Int64.
 func (v Value) OverflowInt(x int64) bool {
-	vv := v.panicIfNots(intKinds).(*intValue)
-
-	bitSize := uint(vv.typ.Bits())
-	trunc := (x << (64 - bitSize)) >> (64 - bitSize)
-	return x != trunc
+	iv := v.internal()
+	switch iv.kind {
+	case Int, Int8, Int16, Int32, Int64:
+		bitSize := iv.typ.size * 8
+		trunc := (x << (64 - bitSize)) >> (64 - bitSize)
+		return x != trunc
+	}
+	panic(&ValueError{"reflect.Value.OverflowInt", iv.kind})
 }
 
 // OverflowUint returns true if the uint64 x cannot be represented by v's type.
-// It panics if v's Kind is not a sized or unsized Uint kind.
+// It panics if v's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64.
 func (v Value) OverflowUint(x uint64) bool {
-	vv := v.panicIfNots(uintKinds).(*uintValue)
-
-	bitSize := uint(vv.typ.Bits())
-	trunc := (x << (64 - bitSize)) >> (64 - bitSize)
-	return x != trunc
+	iv := v.internal()
+	switch iv.kind {
+	case Uint, Uintptr, Uint8, Uint16, Uint32, Uint64:
+		bitSize := iv.typ.size * 8
+		trunc := (x << (64 - bitSize)) >> (64 - bitSize)
+		return x != trunc
+	}
+	panic(&ValueError{"reflect.Value.OverflowUint", iv.kind})
 }
 
-var pointerKinds = []Kind{Chan, Func, Map, Ptr, Slice, UnsafePointer}
-
 // Pointer returns v's value as a uintptr.
 // It returns uintptr instead of unsafe.Pointer so that
 // code using reflect cannot obtain unsafe.Pointers
 // without importing the unsafe package explicitly.
 // It panics if v's Kind is not Chan, Func, Map, Ptr, Slice, or UnsafePointer.
 func (v Value) Pointer() uintptr {
-	switch vv := v.panicIfNots(pointerKinds).(type) {
-	case *chanValue:
-		return *(*uintptr)(vv.addr)
-	case *funcValue:
-		return *(*uintptr)(vv.addr)
-	case *mapValue:
-		return *(*uintptr)(vv.addr)
-	case *ptrValue:
-		return *(*uintptr)(vv.addr)
-	case *sliceValue:
-		typ := vv.typ
-		return uintptr(vv.addr()) + uintptr(v.Cap())*typ.Elem().Size()
-	case *unsafePointerValue:
-		return uintptr(*(*unsafe.Pointer)(vv.addr))
+	iv := v.internal()
+	switch iv.kind {
+	case Chan, Func, Map, Ptr, UnsafePointer:
+		if iv.kind == Func && v.InternalMethod != 0 {
+			panic("reflect.Value.Pointer of method Value")
+		}
+		return uintptr(iv.word)
+	case Slice:
+		return (*SliceHeader)(iv.addr).Data
 	}
-	panic("not reached")
+	panic(&ValueError{"reflect.Value.Pointer", iv.kind})
 }
 
 // Recv receives and returns a value from the channel v.
@@ -676,233 +1110,142 @@ func (v Value) Pointer() uintptr {
 // The boolean value ok is true if the value x corresponds to a send
 // on the channel, false if it is a zero value received because the channel is closed.
 func (v Value) Recv() (x Value, ok bool) {
-	return v.panicIfNot(Chan).(*chanValue).recv(nil)
+	iv := v.internal()
+	iv.mustBe(Chan)
+	iv.mustBeExported()
+	return iv.recv(false)
 }
 
-// internal recv; non-blocking if selected != nil
-func (v *chanValue) recv(selected *bool) (Value, bool) {
-	t := v.Type()
+// internal recv, possibly non-blocking (nb)
+func (iv internalValue) recv(nb bool) (val Value, ok bool) {
+	t := iv.typ.toType()
 	if t.ChanDir()&RecvDir == 0 {
 		panic("recv on send-only channel")
 	}
-	ch := *(**byte)(v.addr)
-	x := Zero(t.Elem())
-	var ok bool
-	chanrecv(ch, (*byte)(x.internal().getAddr()), selected, &ok)
-	return x, ok
+	ch := iv.word
+	if ch == 0 {
+		panic("recv on nil channel")
+	}
+	valWord, selected, ok := chanrecv(ch, nb)
+	if selected {
+		val = valueFromIword(0, t.Elem(), valWord)
+	}
+	return
 }
 
 // Send sends x on the channel v.
 // It panics if v's kind is not Chan or if x's type is not the same type as v's element type.
+// As in Go, x's value must be assignable to the channel's element type.
 func (v Value) Send(x Value) {
-	v.panicIfNot(Chan).(*chanValue).send(x, nil)
+	iv := v.internal()
+	iv.mustBe(Chan)
+	iv.mustBeExported()
+	iv.send(x, false)
 }
 
-// internal send; non-blocking if selected != nil
-func (v *chanValue) send(x Value, selected *bool) {
-	t := v.Type()
+// internal send, possibly non-blocking
+func (iv internalValue) send(x Value, nb bool) (selected bool) {
+	t := iv.typ.toType()
 	if t.ChanDir()&SendDir == 0 {
 		panic("send on recv-only channel")
 	}
-	typesMustMatch(t.Elem(), x.Type())
-	ch := *(**byte)(v.addr)
-	chansend(ch, (*byte)(x.internal().getAddr()), selected)
+	ix := x.internal()
+	ix.mustBeExported() // do not let unexported x leak
+	ix = convertForAssignment("reflect.Value.Send", nil, t.Elem(), ix)
+	ch := iv.word
+	if ch == 0 {
+		panic("send on nil channel")
+	}
+	return chansend(ch, ix.word, nb)
 }
 
-// Set assigns x to the value v; x must have the same type as v.
-// It panics if CanSet() returns false or if x is the zero Value.
+// Set assigns x to the value v.
+// It panics if CanSet returns false.
+// As in Go, x's value must be assignable to v's type.
 func (v Value) Set(x Value) {
-	x.internal()
-	switch vv := v.internal().(type) {
-	case *arrayValue:
-		xx := x.panicIfNot(Array).(*arrayValue)
-		if !vv.CanSet() {
-			panic(cannotSet)
-		}
-		typesMustMatch(vv.typ, xx.typ)
-		Copy(v, x)
+	iv := v.internal()
+	ix := x.internal()
 
-	case *boolValue:
-		v.SetBool(x.Bool())
-
-	case *chanValue:
-		x := x.panicIfNot(Chan).(*chanValue)
-		if !vv.CanSet() {
-			panic(cannotSet)
-		}
-		typesMustMatch(vv.typ, x.typ)
-		*(*uintptr)(vv.addr) = *(*uintptr)(x.addr)
-
-	case *floatValue:
-		v.SetFloat(x.Float())
-
-	case *funcValue:
-		x := x.panicIfNot(Func).(*funcValue)
-		if !vv.CanSet() {
-			panic(cannotSet)
-		}
-		typesMustMatch(vv.typ, x.typ)
-		*(*uintptr)(vv.addr) = *(*uintptr)(x.addr)
+	iv.mustBeAssignable()
+	ix.mustBeExported() // do not let unexported x leak
 
-	case *intValue:
-		v.SetInt(x.Int())
+	ix = convertForAssignment("reflect.Set", iv.addr, iv.typ, ix)
 
-	case *interfaceValue:
-		i := x.Interface()
-		if !vv.CanSet() {
-			panic(cannotSet)
-		}
-		// Two different representations; see comment in Get.
-		// Empty interface is easy.
-		t := (*interfaceType)(unsafe.Pointer(vv.typ.(*commonType)))
-		if t.NumMethod() == 0 {
-			*(*interface{})(vv.addr) = i
-			return
-		}
-
-		// Non-empty interface requires a runtime check.
-		setiface(t, &i, vv.addr)
-
-	case *mapValue:
-		x := x.panicIfNot(Map).(*mapValue)
-		if !vv.CanSet() {
-			panic(cannotSet)
-		}
-		if x == nil {
-			*(**uintptr)(vv.addr) = nil
-			return
-		}
-		typesMustMatch(vv.typ, x.typ)
-		*(*uintptr)(vv.addr) = *(*uintptr)(x.addr)
-
-	case *ptrValue:
-		x := x.panicIfNot(Ptr).(*ptrValue)
-		if x == nil {
-			*(**uintptr)(vv.addr) = nil
-			return
-		}
-		if !vv.CanSet() {
-			panic(cannotSet)
-		}
-		if x.flag&canStore == 0 {
-			panic("cannot copy pointer obtained from unexported struct field")
-		}
-		typesMustMatch(vv.typ, x.typ)
-		// TODO: This will have to move into the runtime
-		// once the new gc goes in
-		*(*uintptr)(vv.addr) = *(*uintptr)(x.addr)
-
-	case *sliceValue:
-		x := x.panicIfNot(Slice).(*sliceValue)
-		if !vv.CanSet() {
-			panic(cannotSet)
-		}
-		typesMustMatch(vv.typ, x.typ)
-		*vv.slice() = *x.slice()
-
-	case *stringValue:
-		// Do the kind check explicitly, because x.String() does not.
-		x.panicIfNot(String)
-		v.SetString(x.String())
-
-	case *structValue:
-		x := x.panicIfNot(Struct).(*structValue)
-		// TODO: This will have to move into the runtime
-		// once the gc goes in.
-		if !vv.CanSet() {
-			panic(cannotSet)
-		}
-		typesMustMatch(vv.typ, x.typ)
-		memmove(vv.addr, x.addr, vv.typ.Size())
-
-	case *uintValue:
-		v.SetUint(x.Uint())
-
-	case *unsafePointerValue:
-		// Do the kind check explicitly, because x.UnsafePointer
-		// applies to more than just the UnsafePointer Kind.
-		x.panicIfNot(UnsafePointer)
-		v.SetPointer(unsafe.Pointer(x.Pointer()))
+	n := ix.typ.size
+	if n <= ptrSize {
+		storeIword(iv.addr, ix.word, n)
+	} else {
+		memmove(iv.addr, ix.addr, n)
 	}
 }
 
 // SetBool sets v's underlying value.
 // It panics if v's Kind is not Bool or if CanSet() is false.
 func (v Value) SetBool(x bool) {
-	vv := v.panicIfNot(Bool).(*boolValue)
-
-	if !vv.CanSet() {
-		panic(cannotSet)
-	}
-	*(*bool)(vv.addr) = x
+	iv := v.internal()
+	iv.mustBeAssignable()
+	iv.mustBe(Bool)
+	*(*bool)(iv.addr) = x
 }
 
 // SetComplex sets v's underlying value to x.
 // It panics if v's Kind is not Complex64 or Complex128, or if CanSet() is false.
 func (v Value) SetComplex(x complex128) {
-	vv := v.panicIfNots(complexKinds).(*complexValue)
-
-	if !vv.CanSet() {
-		panic(cannotSet)
-	}
-	switch vv.typ.Kind() {
+	iv := v.internal()
+	iv.mustBeAssignable()
+	switch iv.kind {
 	default:
-		panic("reflect: invalid complex kind")
+		panic(&ValueError{"reflect.Value.SetComplex", iv.kind})
 	case Complex64:
-		*(*complex64)(vv.addr) = complex64(x)
+		*(*complex64)(iv.addr) = complex64(x)
 	case Complex128:
-		*(*complex128)(vv.addr) = x
+		*(*complex128)(iv.addr) = x
 	}
 }
 
 // SetFloat sets v's underlying value to x.
 // It panics if v's Kind is not Float32 or Float64, or if CanSet() is false.
 func (v Value) SetFloat(x float64) {
-	vv := v.panicIfNots(floatKinds).(*floatValue)
-
-	if !vv.CanSet() {
-		panic(cannotSet)
-	}
-	switch vv.typ.Kind() {
+	iv := v.internal()
+	iv.mustBeAssignable()
+	switch iv.kind {
 	default:
-		panic("reflect: invalid float kind")
+		panic(&ValueError{"reflect.Value.SetFloat", iv.kind})
 	case Float32:
-		*(*float32)(vv.addr) = float32(x)
+		*(*float32)(iv.addr) = float32(x)
 	case Float64:
-		*(*float64)(vv.addr) = x
+		*(*float64)(iv.addr) = x
 	}
 }
 
 // SetInt sets v's underlying value to x.
-// It panics if v's Kind is not a sized or unsized Int kind, or if CanSet() is false.
+// It panics if v's Kind is not Int, Int8, Int16, Int32, or Int64, or if CanSet() is false.
 func (v Value) SetInt(x int64) {
-	vv := v.panicIfNots(intKinds).(*intValue)
-
-	if !vv.CanSet() {
-		panic(cannotSet)
-	}
-	switch vv.typ.Kind() {
+	iv := v.internal()
+	iv.mustBeAssignable()
+	switch iv.kind {
 	default:
-		panic("reflect: invalid int kind")
+		panic(&ValueError{"reflect.Value.SetInt", iv.kind})
 	case Int:
-		*(*int)(vv.addr) = int(x)
+		*(*int)(iv.addr) = int(x)
 	case Int8:
-		*(*int8)(vv.addr) = int8(x)
+		*(*int8)(iv.addr) = int8(x)
 	case Int16:
-		*(*int16)(vv.addr) = int16(x)
+		*(*int16)(iv.addr) = int16(x)
 	case Int32:
-		*(*int32)(vv.addr) = int32(x)
+		*(*int32)(iv.addr) = int32(x)
 	case Int64:
-		*(*int64)(vv.addr) = x
+		*(*int64)(iv.addr) = x
 	}
 }
 
 // SetLen sets v's length to n.
 // It panics if v's Kind is not Slice.
 func (v Value) SetLen(n int) {
-	vv := v.panicIfNot(Slice).(*sliceValue)
-
-	s := vv.slice()
+	iv := v.internal()
+	iv.mustBeAssignable()
+	iv.mustBe(Slice)
+	s := (*SliceHeader)(iv.addr)
 	if n < 0 || n > int(s.Cap) {
 		panic("reflect: slice length out of range in SetLen")
 	}
@@ -912,91 +1255,97 @@ func (v Value) SetLen(n int) {
 // SetMapIndex sets the value associated with key in the map v to val.
 // It panics if v's Kind is not Map.
 // If val is the zero Value, SetMapIndex deletes the key from the map.
+// As in Go, key's value must be assignable to the map's key type,
+// and val's value must be assignable to the map's value type.
 func (v Value) SetMapIndex(key, val Value) {
-	vv := v.panicIfNot(Map).(*mapValue)
-	t := vv.Type()
-	typesMustMatch(t.Key(), key.Type())
-	var vaddr *byte
-	if val.IsValid() {
-		typesMustMatch(t.Elem(), val.Type())
-		vaddr = (*byte)(val.internal().getAddr())
+	iv := v.internal()
+	ikey := key.internal()
+	ival := val.internal()
+
+	iv.mustBe(Map)
+	iv.mustBeExported()
+
+	ikey.mustBeExported()
+	ikey = convertForAssignment("reflect.Value.SetMapIndex", nil, iv.typ.Key(), ikey)
+
+	if ival.kind != Invalid {
+		ival.mustBeExported()
+		ival = convertForAssignment("reflect.Value.SetMapIndex", nil, iv.typ.Elem(), ival)
 	}
-	m := *(**byte)(vv.addr)
-	mapassign(m, (*byte)(key.internal().getAddr()), vaddr)
+
+	mapassign(iv.word, ikey.word, ival.word, ival.kind != Invalid)
 }
 
 // SetUint sets v's underlying value to x.
-// It panics if v's Kind is not a sized or unsized Uint kind, or if CanSet() is false.
+// It panics if v's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64, or if CanSet() is false.
 func (v Value) SetUint(x uint64) {
-	vv := v.panicIfNots(uintKinds).(*uintValue)
-
-	if !vv.CanSet() {
-		panic(cannotSet)
-	}
-	switch vv.typ.Kind() {
+	iv := v.internal()
+	iv.mustBeAssignable()
+	switch iv.kind {
 	default:
-		panic("reflect: invalid uint kind")
+		panic(&ValueError{"reflect.Value.SetUint", iv.kind})
 	case Uint:
-		*(*uint)(vv.addr) = uint(x)
+		*(*uint)(iv.addr) = uint(x)
 	case Uint8:
-		*(*uint8)(vv.addr) = uint8(x)
+		*(*uint8)(iv.addr) = uint8(x)
 	case Uint16:
-		*(*uint16)(vv.addr) = uint16(x)
+		*(*uint16)(iv.addr) = uint16(x)
 	case Uint32:
-		*(*uint32)(vv.addr) = uint32(x)
+		*(*uint32)(iv.addr) = uint32(x)
 	case Uint64:
-		*(*uint64)(vv.addr) = x
+		*(*uint64)(iv.addr) = x
 	case Uintptr:
-		*(*uintptr)(vv.addr) = uintptr(x)
+		*(*uintptr)(iv.addr) = uintptr(x)
 	}
 }
 
 // SetPointer sets the unsafe.Pointer value v to x.
 // It panics if v's Kind is not UnsafePointer.
 func (v Value) SetPointer(x unsafe.Pointer) {
-	vv := v.panicIfNot(UnsafePointer).(*unsafePointerValue)
-
-	if !vv.CanSet() {
-		panic(cannotSet)
-	}
-	*(*unsafe.Pointer)(vv.addr) = x
+	iv := v.internal()
+	iv.mustBeAssignable()
+	iv.mustBe(UnsafePointer)
+	*(*unsafe.Pointer)(iv.addr) = x
 }
 
 // SetString sets v's underlying value to x.
 // It panics if v's Kind is not String or if CanSet() is false.
 func (v Value) SetString(x string) {
-	vv := v.panicIfNot(String).(*stringValue)
-
-	if !vv.CanSet() {
-		panic(cannotSet)
-	}
-	*(*string)(vv.addr) = x
+	iv := v.internal()
+	iv.mustBeAssignable()
+	iv.mustBe(String)
+	*(*string)(iv.addr) = x
 }
 
-// BUG(rsc): Value.Slice should allow slicing arrays.
-
 // Slice returns a slice of v.
-// It panics if v's Kind is not Slice.
+// It panics if v's Kind is not Array or Slice.
 func (v Value) Slice(beg, end int) Value {
-	vv := v.panicIfNot(Slice).(*sliceValue)
-
+	iv := v.internal()
+	if iv.kind != Array && iv.kind != Slice {
+		panic(&ValueError{"reflect.Value.Slice", iv.kind})
+	}
 	cap := v.Cap()
 	if beg < 0 || end < beg || end > cap {
-		panic("slice index out of bounds")
+		panic("reflect.Value.Slice: slice index out of bounds")
+	}
+	var typ Type
+	var base uintptr
+	switch iv.kind {
+	case Array:
+		if iv.flag&flagAddr == 0 {
+			panic("reflect.Value.Slice: slice of unaddressable array")
+		}
+		typ = toType((*arrayType)(unsafe.Pointer(iv.typ)).slice)
+		base = uintptr(iv.addr)
+	case Slice:
+		typ = iv.typ.toType()
+		base = (*SliceHeader)(iv.addr).Data
 	}
-	typ := vv.typ
 	s := new(SliceHeader)
-	s.Data = uintptr(vv.addr()) + uintptr(beg)*typ.Elem().Size()
+	s.Data = base + uintptr(beg)*typ.Elem().Size()
 	s.Len = end - beg
 	s.Cap = cap - beg
-
-	// Like the result of Addr, we treat Slice as an
-	// unaddressable temporary, so don't set canAddr.
-	flag := canSet
-	if vv.flag&canStore != 0 {
-		flag |= canStore
-	}
-	return newValue(typ, addr(s), flag)
+	return valueFromAddr(iv.flag&flagRO, typ, unsafe.Pointer(s))
 }
 
 // String returns the string v's underlying value, as a string.
@@ -1004,15 +1353,14 @@ func (v Value) Slice(beg, end int) Value {
 // Unlike the other getters, it does not panic if v's Kind is not String.
 // Instead, it returns a string of the form "<T value>" where T is v's type.
 func (v Value) String() string {
-	vi := v.Internal
-	if vi == nil {
+	iv := v.internal()
+	switch iv.kind {
+	case Invalid:
 		return "<invalid Value>"
+	case String:
+		return *(*string)(iv.addr)
 	}
-	if vi.Kind() == String {
-		vv := vi.(*stringValue)
-		return *(*string)(vv.addr)
-	}
-	return "<" + vi.Type().String() + " Value>"
+	return "<" + iv.typ.String() + " Value>"
 }
 
 // TryRecv attempts to receive a value from the channel v but will not block.
@@ -1021,241 +1369,98 @@ func (v Value) String() string {
 // The boolean ok is true if the value x corresponds to a send
 // on the channel, false if it is a zero value received because the channel is closed.
 func (v Value) TryRecv() (x Value, ok bool) {
-	vv := v.panicIfNot(Chan).(*chanValue)
-
-	var selected bool
-	x, ok = vv.recv(&selected)
-	if !selected {
-		return Value{}, false
-	}
-	return x, ok
+	iv := v.internal()
+	iv.mustBe(Chan)
+	iv.mustBeExported()
+	return iv.recv(true)
 }
 
 // TrySend attempts to send x on the channel v but will not block.
 // It panics if v's Kind is not Chan.
 // It returns true if the value was sent, false otherwise.
+// As in Go, x's value must be assignable to the channel's element type.
 func (v Value) TrySend(x Value) bool {
-	vv := v.panicIfNot(Chan).(*chanValue)
-
-	var selected bool
-	vv.send(x, &selected)
-	return selected
+	iv := v.internal()
+	iv.mustBe(Chan)
+	iv.mustBeExported()
+	return iv.send(x, true)
 }
 
 // Type returns v's type.
 func (v Value) Type() Type {
-	return v.internal().Type()
+	t := v.internal().typ
+	if t == nil {
+		panic(&ValueError{"reflect.Value.Type", Invalid})
+	}
+	return t.toType()
 }
 
-var uintKinds = []Kind{Uint, Uint8, Uint16, Uint32, Uint64, Uintptr}
-
 // Uint returns v's underlying value, as a uint64.
-// It panics if v's Kind is not a sized or unsized Uint kind.
+// It panics if v's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64.
 func (v Value) Uint() uint64 {
-	vv := v.panicIfNots(uintKinds).(*uintValue)
-
-	switch vv.typ.Kind() {
+	iv := v.internal()
+	switch iv.kind {
 	case Uint:
-		return uint64(*(*uint)(vv.addr))
+		return uint64(*(*uint)(unsafe.Pointer(&iv.word)))
 	case Uint8:
-		return uint64(*(*uint8)(vv.addr))
+		return uint64(*(*uint8)(unsafe.Pointer(&iv.word)))
 	case Uint16:
-		return uint64(*(*uint16)(vv.addr))
+		return uint64(*(*uint16)(unsafe.Pointer(&iv.word)))
 	case Uint32:
-		return uint64(*(*uint32)(vv.addr))
-	case Uint64:
-		return *(*uint64)(vv.addr)
+		return uint64(*(*uint32)(unsafe.Pointer(&iv.word)))
 	case Uintptr:
-		return uint64(*(*uintptr)(vv.addr))
+		return uint64(*(*uintptr)(unsafe.Pointer(&iv.word)))
+	case Uint64:
+		if iv.addr == nil {
+			return *(*uint64)(unsafe.Pointer(&iv.word))
+		}
+		return *(*uint64)(iv.addr)
 	}
-	panic("reflect: invalid uint kind")
+	panic(&ValueError{"reflect.Value.Uint", iv.kind})
 }
 
 // UnsafeAddr returns a pointer to v's data.
 // It is for advanced clients that also import the "unsafe" package.
+// It panics if v is not addressable.
 func (v Value) UnsafeAddr() uintptr {
-	return v.internal().UnsafeAddr()
-}
-
-// valueInterface is the common interface to reflection values.
-// The implementations of Value (e.g., arrayValue, structValue)
-// have additional type-specific methods.
-type valueInterface interface {
-	// Type returns the value's type.
-	Type() Type
-
-	// Interface returns the value as an interface{}.
-	Interface() interface{}
-
-	// CanSet returns true if the value can be changed.
-	// Values obtained by the use of non-exported struct fields
-	// can be used in Get but not Set.
-	// If CanSet returns false, calling the type-specific Set will panic.
-	CanSet() bool
-
-	// CanAddr returns true if the value's address can be obtained with Addr.
-	// Such values are called addressable.  A value is addressable if it is
-	// an element of a slice, an element of an addressable array,
-	// a field of an addressable struct, the result of dereferencing a pointer,
-	// or the result of a call to NewValue, MakeChan, MakeMap, or Zero.
-	// If CanAddr returns false, calling Addr will panic.
-	CanAddr() bool
-
-	// Addr returns the address of the value.
-	// If the value is not addressable, Addr panics.
-	// Addr is typically used to obtain a pointer to a struct field or slice element
-	// in order to call a method that requires a pointer receiver.
-	Addr() Value
-
-	// UnsafeAddr returns a pointer to the underlying data.
-	// It is for advanced clients that also import the "unsafe" package.
-	UnsafeAddr() uintptr
-
-	// Method returns a funcValue corresponding to the value's i'th method.
-	// The arguments to a Call on the returned funcValue
-	// should not include a receiver; the funcValue will use
-	// the value as the receiver.
-	Method(i int) Value
-
-	Kind() Kind
-
-	getAddr() addr
-}
-
-// flags for value
-const (
-	canSet   uint32 = 1 << iota // can set value (write to *v.addr)
-	canAddr                     // can take address of value
-	canStore                    // can store through value (write to **v.addr)
-)
-
-// value is the common implementation of most values.
-// It is embedded in other, public struct types, but always
-// with a unique tag like "uint" or "float" so that the client cannot
-// convert from, say, *uintValue to *floatValue.
-type value struct {
-	typ  Type
-	addr addr
-	flag uint32
-}
-
-func (v *value) Type() Type { return v.typ }
-
-func (v *value) Kind() Kind { return v.typ.Kind() }
-
-func (v *value) Addr() Value {
-	if !v.CanAddr() {
-		panic("reflect: cannot take address of value")
+	iv := v.internal()
+	if iv.kind == Invalid {
+		panic(&ValueError{"reflect.Value.UnsafeAddr", iv.kind})
 	}
-	a := v.addr
-	flag := canSet
-	if v.CanSet() {
-		flag |= canStore
+	if iv.flag&flagAddr == 0 {
+		panic("reflect.Value.UnsafeAddr of unaddressable value")
 	}
-	// We could safely set canAddr here too -
-	// the caller would get the address of a -
-	// but it doesn't match the Go model.
-	// The language doesn't let you say &&v.
-	return newValue(PtrTo(v.typ), addr(&a), flag)
-}
-
-func (v *value) UnsafeAddr() uintptr { return uintptr(v.addr) }
-
-func (v *value) getAddr() addr { return v.addr }
-
-func (v *value) Interface() interface{} {
-	typ := v.typ
-	if typ.Kind() == Interface {
-		// There are two different representations of interface values,
-		// one if the interface type has methods and one if it doesn't.
-		// These two representations require different expressions
-		// to extract correctly.
-		if typ.NumMethod() == 0 {
-			// Extract as interface value without methods.
-			return *(*interface{})(v.addr)
-		}
-		// Extract from v.addr as interface value with methods.
-		return *(*interface {
-			m()
-		})(v.addr)
-	}
-	return unsafe.Unreflect(v.typ, unsafe.Pointer(v.addr))
-}
-
-func (v *value) CanSet() bool { return v.flag&canSet != 0 }
-
-func (v *value) CanAddr() bool { return v.flag&canAddr != 0 }
-
-
-/*
- * basic types
- */
-
-// boolValue represents a bool value.
-type boolValue struct {
-	value "bool"
-}
-
-// floatValue represents a float value.
-type floatValue struct {
-	value "float"
-}
-
-// complexValue represents a complex value.
-type complexValue struct {
-	value "complex"
-}
-
-// intValue represents an int value.
-type intValue struct {
-	value "int"
+	return uintptr(iv.addr)
 }
 
 // StringHeader is the runtime representation of a string.
+// It cannot be used safely or portably.
 type StringHeader struct {
 	Data uintptr
 	Len  int
 }
 
-// stringValue represents a string value.
-type stringValue struct {
-	value "string"
-}
-
-// uintValue represents a uint value.
-type uintValue struct {
-	value "uint"
-}
-
-// unsafePointerValue represents an unsafe.Pointer value.
-type unsafePointerValue struct {
-	value "unsafe.Pointer"
+// SliceHeader is the runtime representation of a slice.
+// It cannot be used safely or portably.
+type SliceHeader struct {
+	Data uintptr
+	Len  int
+	Cap  int
 }
 
-func typesMustMatch(t1, t2 Type) {
+func typesMustMatch(what string, t1, t2 Type) {
 	if t1 != t2 {
-		panic("type mismatch: " + t1.String() + " != " + t2.String())
+		panic("reflect: " + what + ": " + t1.String() + " != " + t2.String())
 	}
 }
 
-/*
- * array
- */
-
-// ArrayOrSliceValue is the common interface
-// implemented by both arrayValue and sliceValue.
-type arrayOrSliceValue interface {
-	valueInterface
-	addr() addr
-}
-
 // grow grows the slice s so that it can hold extra more values, allocating
 // more capacity if needed. It also returns the old and new slice lengths.
 func grow(s Value, extra int) (Value, int, int) {
 	i0 := s.Len()
 	i1 := i0 + extra
 	if i1 < i0 {
-		panic("append: slice overflow")
+		panic("reflect.Append: slice overflow")
 	}
 	m := s.Cap()
 	if i1 <= m {
@@ -1278,10 +1483,10 @@ func grow(s Value, extra int) (Value, int, int) {
 }
 
 // Append appends the values x to a slice s and returns the resulting slice.
-// Each x must have the same type as s' element type.
+// As in Go, each x's value must be assignable to the slice's element type.
 func Append(s Value, x ...Value) Value {
+	s.internal().mustBe(Slice)
 	s, i0, i1 := grow(s, len(x))
-	s.panicIfNot(Slice)
 	for i, j := i0, 0; i < i1; i, j = i+1, j+1 {
 		s.Index(i).Set(x[j])
 	}
@@ -1291,6 +1496,9 @@ func Append(s Value, x ...Value) Value {
 // AppendSlice appends a slice t to a slice s and returns the resulting slice.
 // The slices s and t must have the same element type.
 func AppendSlice(s, t Value) Value {
+	s.internal().mustBe(Slice)
+	t.internal().mustBe(Slice)
+	typesMustMatch("reflect.AppendSlice", s.Type().Elem(), t.Type().Elem())
 	s, i0, i1 := grow(s, t.Len())
 	Copy(s.Slice(i0, i1), t)
 	return s
@@ -1299,52 +1507,61 @@ func AppendSlice(s, t Value) Value {
 // Copy copies the contents of src into dst until either
 // dst has been filled or src has been exhausted.
 // It returns the number of elements copied.
-// Dst and src each must be a slice or array, and they
-// must have the same element type.
+// Dst and src each must have kind Slice or Array, and
+// dst and src must have the same element type.
 func Copy(dst, src Value) int {
-	// TODO: This will have to move into the runtime
-	// once the real gc goes in.
-	de := dst.Type().Elem()
-	se := src.Type().Elem()
-	typesMustMatch(de, se)
-	n := dst.Len()
-	if xn := src.Len(); n > xn {
-		n = xn
-	}
-	memmove(dst.panicIfNots(arrayOrSlice).(arrayOrSliceValue).addr(),
-		src.panicIfNots(arrayOrSlice).(arrayOrSliceValue).addr(),
-		uintptr(n)*de.Size())
-	return n
-}
+	idst := dst.internal()
+	isrc := src.internal()
 
-// An arrayValue represents an array.
-type arrayValue struct {
-	value "array"
-}
+	if idst.kind != Array && idst.kind != Slice {
+		panic(&ValueError{"reflect.Copy", idst.kind})
+	}
+	if idst.kind == Array {
+		idst.mustBeAssignable()
+	}
+	idst.mustBeExported()
+	if isrc.kind != Array && isrc.kind != Slice {
+		panic(&ValueError{"reflect.Copy", isrc.kind})
+	}
+	isrc.mustBeExported()
 
-// addr returns the base address of the data in the array.
-func (v *arrayValue) addr() addr { return v.value.addr }
+	de := idst.typ.Elem()
+	se := isrc.typ.Elem()
+	typesMustMatch("reflect.Copy", de, se)
 
-/*
- * slice
- */
+	n := dst.Len()
+	if sn := src.Len(); n > sn {
+		n = sn
+	}
 
-// runtime representation of slice
-type SliceHeader struct {
-	Data uintptr
-	Len  int
-	Cap  int
-}
+	// If sk is an in-line array, cannot take its address.
+	// Instead, copy element by element.
+	if isrc.addr == nil {
+		for i := 0; i < n; i++ {
+			dst.Index(i).Set(src.Index(i))
+		}
+		return n
+	}
 
-// A sliceValue represents a slice.
-type sliceValue struct {
-	value "slice"
+	// Copy via memmove.
+	var da, sa unsafe.Pointer
+	if idst.kind == Array {
+		da = idst.addr
+	} else {
+		da = unsafe.Pointer((*SliceHeader)(idst.addr).Data)
+	}
+	if isrc.kind == Array {
+		sa = isrc.addr
+	} else {
+		sa = unsafe.Pointer((*SliceHeader)(isrc.addr).Data)
+	}
+	memmove(da, sa, uintptr(n)*de.Size())
+	return n
 }
 
-func (v *sliceValue) slice() *SliceHeader { return (*SliceHeader)(v.value.addr) }
-
-// addr returns the base address of the data in the slice.
-func (v *sliceValue) addr() addr { return addr(v.slice().Data) }
+/*
+ * constructors
+ */
 
 // MakeSlice creates a new zero-initialized slice value
 // for the specified slice type, length, and capacity.
@@ -1357,26 +1574,9 @@ func MakeSlice(typ Type, len, cap int) Value {
 		Len:  len,
 		Cap:  cap,
 	}
-	return newValue(typ, addr(s), canAddr|canSet|canStore)
-}
-
-/*
- * chan
- */
-
-// A chanValue represents a chan.
-type chanValue struct {
-	value "chan"
+	return valueFromAddr(0, typ, unsafe.Pointer(s))
 }
 
-// implemented in ../pkg/runtime/reflect.cgo
-func makechan(typ *runtime.ChanType, size uint32) (ch *byte)
-func chansend(ch, val *byte, selected *bool)
-func chanrecv(ch, val *byte, selected *bool, ok *bool)
-func chanclose(ch *byte)
-func chanlen(ch *byte) int32
-func chancap(ch *byte) int32
-
 // MakeChan creates a new channel with the specified type and buffer size.
 func MakeChan(typ Type, buffer int) Value {
 	if typ.Kind() != Chan {
@@ -1388,121 +1588,17 @@ func MakeChan(typ Type, buffer int) Value {
 	if typ.ChanDir() != BothDir {
 		panic("MakeChan: unidirectional channel type")
 	}
-	v := Zero(typ)
-	ch := v.panicIfNot(Chan).(*chanValue)
-	*(**byte)(ch.addr) = makechan((*runtime.ChanType)(unsafe.Pointer(typ.(*commonType))), uint32(buffer))
-	return v
+	ch := makechan(typ.runtimeType(), uint32(buffer))
+	return valueFromIword(0, typ, ch)
 }
 
-/*
- * func
- */
-
-// A funcValue represents a function value.
-type funcValue struct {
-	value       "func"
-	first       *value
-	isInterface bool
-}
-
-// Method returns a funcValue corresponding to v's i'th method.
-// The arguments to a Call on the returned funcValue
-// should not include a receiver; the funcValue will use v
-// as the receiver.
-func (v *value) Method(i int) Value {
-	t := v.Type().uncommon()
-	if t == nil || i < 0 || i >= len(t.methods) {
-		panic("reflect: Method index out of range")
-	}
-	p := &t.methods[i]
-	fn := p.tfn
-	fv := &funcValue{value: value{toType(p.typ), addr(&fn), 0}, first: v, isInterface: false}
-	return Value{fv}
-}
-
-// implemented in ../pkg/runtime/*/asm.s
-func call(fn, arg *byte, n uint32)
-
-// Interface returns the fv as an interface value.
-// If fv is a method obtained by invoking Value.Method
-// (as opposed to Type.Method), Interface cannot return an
-// interface value, so it panics.
-func (fv *funcValue) Interface() interface{} {
-	if fv.first != nil {
-		panic("funcValue: cannot create interface value for method with bound receiver")
-	}
-	return fv.value.Interface()
-}
-
-/*
- * interface
- */
-
-// An interfaceValue represents an interface value.
-type interfaceValue struct {
-	value "interface"
-}
-
-// ../runtime/reflect.cgo
-func setiface(typ *interfaceType, x *interface{}, addr addr)
-
-// Method returns a funcValue corresponding to v's i'th method.
-// The arguments to a Call on the returned funcValue
-// should not include a receiver; the funcValue will use v
-// as the receiver.
-func (v *interfaceValue) Method(i int) Value {
-	t := (*interfaceType)(unsafe.Pointer(v.Type().(*commonType)))
-	if t == nil || i < 0 || i >= len(t.methods) {
-		panic("reflect: Method index out of range")
-	}
-	p := &t.methods[i]
-
-	// Interface is two words: itable, data.
-	tab := *(**runtime.Itable)(v.addr)
-	data := &value{Typeof((*byte)(nil)), addr(uintptr(v.addr) + ptrSize), 0}
-
-	// Function pointer is at p.perm in the table.
-	fn := tab.Fn[i]
-	fv := &funcValue{value: value{toType(p.typ), addr(&fn), 0}, first: data, isInterface: true}
-	return Value{fv}
-}
-
-/*
- * map
- */
-
-// A mapValue represents a map value.
-type mapValue struct {
-	value "map"
-}
-
-// implemented in ../pkg/runtime/reflect.cgo
-func mapaccess(m, key, val *byte) bool
-func mapassign(m, key, val *byte)
-func maplen(m *byte) int32
-func mapiterinit(m *byte) *byte
-func mapiternext(it *byte)
-func mapiterkey(it *byte, key *byte) bool
-func makemap(t *runtime.MapType) *byte
-
 // MakeMap creates a new map of the specified type.
 func MakeMap(typ Type) Value {
 	if typ.Kind() != Map {
 		panic("reflect: MakeMap of non-map type")
 	}
-	v := Zero(typ)
-	m := v.panicIfNot(Map).(*mapValue)
-	*(**byte)(m.addr) = makemap((*runtime.MapType)(unsafe.Pointer(typ.(*commonType))))
-	return v
-}
-
-/*
- * ptr
- */
-
-// A ptrValue represents a pointer.
-type ptrValue struct {
-	value "ptr"
+	m := makemap(typ.runtimeType())
+	return valueFromIword(0, typ, m)
 }
 
 // Indirect returns the value that v points to.
@@ -1515,73 +1611,90 @@ func Indirect(v Value) Value {
 	return v.Elem()
 }
 
-/*
- * struct
- */
-
-// A structValue represents a struct value.
-type structValue struct {
-	value "struct"
-}
-
-/*
- * constructors
- */
-
-// NewValue returns a new Value initialized to the concrete value
-// stored in the interface i.  NewValue(nil) returns the zero Value.
-func NewValue(i interface{}) Value {
+// ValueOf returns a new Value initialized to the concrete value
+// stored in the interface i.  ValueOf(nil) returns the zero Value.
+func ValueOf(i interface{}) Value {
 	if i == nil {
 		return Value{}
 	}
-	_, a := unsafe.Reflect(i)
-	return newValue(Typeof(i), addr(a), canSet|canAddr|canStore)
-}
-
-func newValue(typ Type, addr addr, flag uint32) Value {
-	v := value{typ, addr, flag}
-	switch typ.Kind() {
-	case Array:
-		return Value{&arrayValue{v}}
-	case Bool:
-		return Value{&boolValue{v}}
-	case Chan:
-		return Value{&chanValue{v}}
-	case Float32, Float64:
-		return Value{&floatValue{v}}
-	case Func:
-		return Value{&funcValue{value: v}}
-	case Complex64, Complex128:
-		return Value{&complexValue{v}}
-	case Int, Int8, Int16, Int32, Int64:
-		return Value{&intValue{v}}
-	case Interface:
-		return Value{&interfaceValue{v}}
-	case Map:
-		return Value{&mapValue{v}}
-	case Ptr:
-		return Value{&ptrValue{v}}
-	case Slice:
-		return Value{&sliceValue{v}}
-	case String:
-		return Value{&stringValue{v}}
-	case Struct:
-		return Value{&structValue{v}}
-	case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
-		return Value{&uintValue{v}}
-	case UnsafePointer:
-		return Value{&unsafePointerValue{v}}
-	}
-	panic("newValue" + typ.String())
+	// For an interface value with the noAddr bit set,
+	// the representation is identical to an empty interface.
+	eface := *(*emptyInterface)(unsafe.Pointer(&i))
+	return packValue(0, eface.typ, eface.word)
 }
 
 // Zero returns a Value representing a zero value for the specified type.
 // The result is different from the zero value of the Value struct,
 // which represents no value at all.
-// For example, Zero(Typeof(42)) returns a Value with Kind Int and value 0.
+// For example, Zero(TypeOf(42)) returns a Value with Kind Int and value 0.
 func Zero(typ Type) Value {
 	if typ == nil {
 		panic("reflect: Zero(nil)")
 	}
-	return newValue(typ, addr(unsafe.New(typ)), canSet|canAddr|canStore)
+	if typ.Size() <= ptrSize {
+		return valueFromIword(0, typ, 0)
+	}
+	return valueFromAddr(0, typ, unsafe.New(typ))
 }
+
+// New returns a Value representing a pointer to a new zero value
+// for the specified type.  That is, the returned Value's Type is PtrTo(t).
+func New(typ Type) Value {
+	if typ == nil {
+		panic("reflect: New(nil)")
+	}
+	ptr := unsafe.New(typ)
+	return valueFromIword(0, PtrTo(typ), iword(ptr))
+}
+
+// convertForAssignment 
+func convertForAssignment(what string, addr unsafe.Pointer, dst Type, iv internalValue) internalValue {
+	if iv.method {
+		panic(what + ": cannot assign method value to type " + dst.String())
+	}
+
+	dst1 := dst.(*commonType)
+	if directlyAssignable(dst1, iv.typ) {
+		// Overwrite type so that they match.
+		// Same memory layout, so no harm done.
+		iv.typ = dst1
+		return iv
+	}
+	if implements(dst1, iv.typ) {
+		if addr == nil {
+			addr = unsafe.Pointer(new(interface{}))
+		}
+		x := iv.Interface()
+		if dst.NumMethod() == 0 {
+			*(*interface{})(addr) = x
+		} else {
+			ifaceE2I(dst1.runtimeType(), x, addr)
+		}
+		iv.addr = addr
+		iv.word = iword(addr)
+		iv.typ = dst1
+		return iv
+	}
+
+	// Failed.
+	panic(what + ": value of type " + iv.typ.String() + " is not assignable to type " + dst.String())
+}
+
+// implemented in ../pkg/runtime
+func chancap(ch iword) int32
+func chanclose(ch iword)
+func chanlen(ch iword) int32
+func chanrecv(ch iword, nb bool) (val iword, selected, received bool)
+func chansend(ch iword, val iword, nb bool) bool
+
+func makechan(typ *runtime.Type, size uint32) (ch iword)
+func makemap(t *runtime.Type) iword
+func mapaccess(m iword, key iword) (val iword, ok bool)
+func mapassign(m iword, key, val iword, ok bool)
+func mapiterinit(m iword) *byte
+func mapiterkey(it *byte) (key iword, ok bool)
+func mapiternext(it *byte)
+func maplen(m iword) int32
+
+func call(fn, arg unsafe.Pointer, n uint32)
+func ifaceE2I(t *runtime.Type, src interface{}, dst unsafe.Pointer)
diff --git a/src/pkg/rpc/server.go b/src/pkg/rpc/server.go
index af31a65..acadeec 100644
--- a/src/pkg/rpc/server.go
+++ b/src/pkg/rpc/server.go
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 /*
-	The rpc package provides access to the exported methods of an object across a
+	Package rpc provides access to the exported methods of an object across a
 	network or other I/O connection.  A server registers an object, making it visible
 	as a service with the name of the type of the object.  After registration, exported
 	methods of the object will be accessible remotely.  A server may register multiple
@@ -13,8 +13,11 @@
 	Only methods that satisfy these criteria will be made available for remote access;
 	other methods will be ignored:
 
-		- the method receiver and name are exported, that is, begin with an upper case letter.
-		- the method has two arguments, both pointers to exported types.
+		- the method name is exported, that is, begins with an upper case letter.
+		- the method receiver is exported or local (defined in the package
+		  registering the service).
+		- the method has two arguments, both exported or local types.
+		- the method's second argument is a pointer.
 		- the method has return type os.Error.
 
 	The method's first argument represents the arguments provided by the caller; the
@@ -133,7 +136,7 @@ const (
 // Precompute the reflect type for os.Error.  Can't use os.Error directly
 // because Typeof takes an empty interface value.  This is annoying.
 var unusedError *os.Error
-var typeOfOsError = reflect.Typeof(unusedError).Elem()
+var typeOfOsError = reflect.TypeOf(unusedError).Elem()
 
 type methodType struct {
 	sync.Mutex // protects counters
@@ -193,6 +196,14 @@ func isExported(name string) bool {
 	return unicode.IsUpper(rune)
 }
 
+// Is this type exported or local to this package?
+func isExportedOrLocalType(t reflect.Type) bool {
+	for t.Kind() == reflect.Ptr {
+		t = t.Elem()
+	}
+	return t.PkgPath() == "" || isExported(t.Name())
+}
+
 // Register publishes in the server the set of methods of the
 // receiver value that satisfy the following conditions:
 //	- exported method
@@ -219,8 +230,8 @@ func (server *Server) register(rcvr interface{}, name string, useName bool) os.E
 		server.serviceMap = make(map[string]*service)
 	}
 	s := new(service)
-	s.typ = reflect.Typeof(rcvr)
-	s.rcvr = reflect.NewValue(rcvr)
+	s.typ = reflect.TypeOf(rcvr)
+	s.rcvr = reflect.ValueOf(rcvr)
 	sname := reflect.Indirect(s.rcvr).Type().Name()
 	if useName {
 		sname = name
@@ -252,23 +263,20 @@ func (server *Server) register(rcvr interface{}, name string, useName bool) os.E
 			log.Println("method", mname, "has wrong number of ins:", mtype.NumIn())
 			continue
 		}
+		// First arg need not be a pointer.
 		argType := mtype.In(1)
-		ok := argType.Kind() == reflect.Ptr
-		if !ok {
-			log.Println(mname, "arg type not a pointer:", mtype.In(1))
+		if !isExportedOrLocalType(argType) {
+			log.Println(mname, "argument type not exported or local:", argType)
 			continue
 		}
+		// Second arg must be a pointer.
 		replyType := mtype.In(2)
 		if replyType.Kind() != reflect.Ptr {
-			log.Println(mname, "reply type not a pointer:", mtype.In(2))
-			continue
-		}
-		if argType.Elem().PkgPath() != "" && !isExported(argType.Elem().Name()) {
-			log.Println(mname, "argument type not exported:", argType)
+			log.Println("method", mname, "reply type not a pointer:", replyType)
 			continue
 		}
-		if replyType.Elem().PkgPath() != "" && !isExported(replyType.Elem().Name()) {
-			log.Println(mname, "reply type not exported:", replyType)
+		if !isExportedOrLocalType(replyType) {
+			log.Println("method", mname, "reply type not exported or local:", replyType)
 			continue
 		}
 		// Method needs one out: os.Error.
@@ -297,12 +305,6 @@ type InvalidRequest struct{}
 
 var invalidRequest = InvalidRequest{}
 
-func _new(t reflect.Type) reflect.Value {
-	v := reflect.Zero(t)
-	v.Set(reflect.Zero(t.Elem()).Addr())
-	return v
-}
-
 func (server *Server) sendResponse(sending *sync.Mutex, req *Request, reply interface{}, codec ServerCodec, errmsg string) {
 	resp := server.getResponse()
 	// Encode the response header
@@ -411,8 +413,16 @@ func (server *Server) ServeCodec(codec ServerCodec) {
 		}
 
 		// Decode the argument value.
-		argv := _new(mtype.ArgType)
-		replyv := _new(mtype.ReplyType)
+		var argv reflect.Value
+		argIsValue := false // if true, need to indirect before calling.
+		if mtype.ArgType.Kind() == reflect.Ptr {
+			argv = reflect.New(mtype.ArgType.Elem())
+		} else {
+			argv = reflect.New(mtype.ArgType)
+			argIsValue = true
+		}
+		// argv guaranteed to be a pointer now.
+		replyv := reflect.New(mtype.ReplyType.Elem())
 		err = codec.ReadRequestBody(argv.Interface())
 		if err != nil {
 			if err == os.EOF || err == io.ErrUnexpectedEOF {
@@ -424,6 +434,9 @@ func (server *Server) ServeCodec(codec ServerCodec) {
 			server.sendResponse(sending, req, replyv.Interface(), codec, err.String())
 			continue
 		}
+		if argIsValue {
+			argv = argv.Elem()
+		}
 		go service.call(server, sending, mtype, req, argv, replyv, codec)
 	}
 	codec.Close()
diff --git a/src/pkg/rpc/server_test.go b/src/pkg/rpc/server_test.go
index d4041ae..cfff0c9 100644
--- a/src/pkg/rpc/server_test.go
+++ b/src/pkg/rpc/server_test.go
@@ -38,7 +38,9 @@ type Reply struct {
 
 type Arith int
 
-func (t *Arith) Add(args *Args, reply *Reply) os.Error {
+// Some of Arith's methods have value args, some have pointer args. That's deliberate.
+
+func (t *Arith) Add(args Args, reply *Reply) os.Error {
 	reply.C = args.A + args.B
 	return nil
 }
@@ -48,7 +50,7 @@ func (t *Arith) Mul(args *Args, reply *Reply) os.Error {
 	return nil
 }
 
-func (t *Arith) Div(args *Args, reply *Reply) os.Error {
+func (t *Arith) Div(args Args, reply *Reply) os.Error {
 	if args.B == 0 {
 		return os.ErrorString("divide by zero")
 	}
@@ -61,8 +63,8 @@ func (t *Arith) String(args *Args, reply *string) os.Error {
 	return nil
 }
 
-func (t *Arith) Scan(args *string, reply *Reply) (err os.Error) {
-	_, err = fmt.Sscan(*args, &reply.C)
+func (t *Arith) Scan(args string, reply *Reply) (err os.Error) {
+	_, err = fmt.Sscan(args, &reply.C)
 	return
 }
 
@@ -262,16 +264,11 @@ func testHTTPRPC(t *testing.T, path string) {
 	}
 }
 
-type ArgNotPointer int
 type ReplyNotPointer int
 type ArgNotPublic int
 type ReplyNotPublic int
 type local struct{}
 
-func (t *ArgNotPointer) ArgNotPointer(args Args, reply *Reply) os.Error {
-	return nil
-}
-
 func (t *ReplyNotPointer) ReplyNotPointer(args *Args, reply Reply) os.Error {
 	return nil
 }
@@ -286,11 +283,7 @@ func (t *ReplyNotPublic) ReplyNotPublic(args *Args, reply *local) os.Error {
 
 // Check that registration handles lots of bad methods and a type with no suitable methods.
 func TestRegistrationError(t *testing.T) {
-	err := Register(new(ArgNotPointer))
-	if err == nil {
-		t.Errorf("expected error registering ArgNotPointer")
-	}
-	err = Register(new(ReplyNotPointer))
+	err := Register(new(ReplyNotPointer))
 	if err == nil {
 		t.Errorf("expected error registering ReplyNotPointer")
 	}
@@ -351,18 +344,26 @@ func testSendDeadlock(client *Client) {
 	client.Call("Arith.Add", args, reply)
 }
 
-func TestCountMallocs(t *testing.T) {
+func dialDirect() (*Client, os.Error) {
+	return Dial("tcp", serverAddr)
+}
+
+func dialHTTP() (*Client, os.Error) {
+	return DialHTTP("tcp", httpServerAddr)
+}
+
+func countMallocs(dial func() (*Client, os.Error), t *testing.T) uint64 {
 	once.Do(startServer)
-	client, err := Dial("tcp", serverAddr)
+	client, err := dial()
 	if err != nil {
-		t.Error("error dialing", err)
+		t.Fatal("error dialing", err)
 	}
 	args := &Args{7, 8}
 	reply := new(Reply)
 	mallocs := 0 - runtime.MemStats.Mallocs
 	const count = 100
 	for i := 0; i < count; i++ {
-		err = client.Call("Arith.Add", args, reply)
+		err := client.Call("Arith.Add", args, reply)
 		if err != nil {
 			t.Errorf("Add: expected no error but got string %q", err.String())
 		}
@@ -371,13 +372,21 @@ func TestCountMallocs(t *testing.T) {
 		}
 	}
 	mallocs += runtime.MemStats.Mallocs
-	fmt.Printf("mallocs per rpc round trip: %d\n", mallocs/count)
+	return mallocs / count
 }
 
-func BenchmarkEndToEnd(b *testing.B) {
+func TestCountMallocs(t *testing.T) {
+	fmt.Printf("mallocs per rpc round trip: %d\n", countMallocs(dialDirect, t))
+}
+
+func TestCountMallocsOverHTTP(t *testing.T) {
+	fmt.Printf("mallocs per HTTP rpc round trip: %d\n", countMallocs(dialHTTP, t))
+}
+
+func benchmarkEndToEnd(dial func() (*Client, os.Error), b *testing.B) {
 	b.StopTimer()
 	once.Do(startServer)
-	client, err := Dial("tcp", serverAddr)
+	client, err := dial()
 	if err != nil {
 		fmt.Println("error dialing", err)
 		return
@@ -399,3 +408,11 @@ func BenchmarkEndToEnd(b *testing.B) {
 		}
 	}
 }
+
+func BenchmarkEndToEnd(b *testing.B) {
+	benchmarkEndToEnd(dialDirect, b)
+}
+
+func BenchmarkEndToEndHTTP(b *testing.B) {
+	benchmarkEndToEnd(dialHTTP, b)
+}
diff --git a/src/pkg/runtime/386/asm.s b/src/pkg/runtime/386/asm.s
index 598fc68..e2cabef 100644
--- a/src/pkg/runtime/386/asm.s
+++ b/src/pkg/runtime/386/asm.s
@@ -149,7 +149,7 @@ TEXT runtime·gogocall(SB), 7, $0
 
 // void mcall(void (*fn)(G*))
 // Switch to m->g0's stack, call fn(g).
-// Fn must never return.  It should gogo(&g->gobuf)
+// Fn must never return.  It should gogo(&g->sched)
 // to keep running g.
 TEXT runtime·mcall(SB), 7, $0
 	MOVL	fn+0(FP), DI
diff --git a/src/pkg/runtime/Makefile b/src/pkg/runtime/Makefile
index 4da78c5..b122e05 100644
--- a/src/pkg/runtime/Makefile
+++ b/src/pkg/runtime/Makefile
@@ -71,7 +71,6 @@ OFILES=\
 	msize.$O\
 	print.$O\
 	proc.$O\
-	reflect.$O\
 	rune.$O\
 	runtime.$O\
 	runtime1.$O\
diff --git a/src/pkg/runtime/amd64/asm.s b/src/pkg/runtime/amd64/asm.s
index a611985..46d82e3 100644
--- a/src/pkg/runtime/amd64/asm.s
+++ b/src/pkg/runtime/amd64/asm.s
@@ -133,7 +133,7 @@ TEXT runtime·gogocall(SB), 7, $0
 
 // void mcall(void (*fn)(G*))
 // Switch to m->g0's stack, call fn(g).
-// Fn must never return.  It should gogo(&g->gobuf)
+// Fn must never return.  It should gogo(&g->sched)
 // to keep running g.
 TEXT runtime·mcall(SB), 7, $0
 	MOVQ	fn+0(FP), DI
diff --git a/src/pkg/runtime/arm/asm.s b/src/pkg/runtime/arm/asm.s
index 4d36606..6315365 100644
--- a/src/pkg/runtime/arm/asm.s
+++ b/src/pkg/runtime/arm/asm.s
@@ -128,7 +128,7 @@ TEXT runtime·gogocall(SB), 7, $-4
 
 // void mcall(void (*fn)(G*))
 // Switch to m->g0's stack, call fn(g).
-// Fn must never return.  It should gogo(&g->gobuf)
+// Fn must never return.  It should gogo(&g->sched)
 // to keep running g.
 TEXT runtime·mcall(SB), 7, $-4
 	MOVW	fn+0(FP), R0
diff --git a/src/pkg/runtime/arm/softfloat.c b/src/pkg/runtime/arm/softfloat.c
index f60fab1..f91a6fc 100644
--- a/src/pkg/runtime/arm/softfloat.c
+++ b/src/pkg/runtime/arm/softfloat.c
@@ -91,6 +91,7 @@ static uint32
 stepflt(uint32 *pc, uint32 *regs)
 {
 	uint32 i, regd, regm, regn;
+	int32 delta;
 	uint32 *addr;
 	uint64 uval;
 	int64 sval;
@@ -117,7 +118,7 @@ stepflt(uint32 *pc, uint32 *regs)
 		return 1;
 	}
 	if(i == 0xe08bb00d) {
-		// add sp to 11.
+		// add sp to r11.
 		// might be part of a large stack offset address
 		// (or might not, but again no harm done).
 		regs[11] += regs[13];
@@ -134,6 +135,19 @@ stepflt(uint32 *pc, uint32 *regs)
 			runtime·printf("*** fpsr R[CPSR] = F[CPSR] %x\n", regs[CPSR]);
 		return 1;
 	}
+	if((i&0xff000000) == 0xea000000) {
+		// unconditional branch
+		// can happen in the middle of floating point
+		// if the linker decides it is time to lay down
+		// a sequence of instruction stream constants.
+		delta = i&0xffffff;
+		delta = (delta<<8) >> 8;	// sign extend
+
+		if(trace)
+			runtime·printf("*** cpu PC += %x\n", (delta+2)*4);
+		return delta+2;
+	}
+
 	goto stage1;
 
 stage1:	// load/store regn is cpureg, regm is 8bit offset
@@ -489,8 +503,10 @@ runtime·_sfloat2(uint32 *lr, uint32 r0)
 	uint32 skip;
 
 	skip = stepflt(lr, &r0);
-	if(skip == 0)
+	if(skip == 0) {
+		runtime·printf("sfloat2 %p %x\n", lr, *lr);
 		fabort(); // not ok to fail first instruction
+	}
 
 	lr += skip;
 	while(skip = stepflt(lr, &r0))
diff --git a/src/pkg/runtime/chan.c b/src/pkg/runtime/chan.c
index 8c45b07..f94c3ef 100644
--- a/src/pkg/runtime/chan.c
+++ b/src/pkg/runtime/chan.c
@@ -9,7 +9,6 @@
 
 static	int32	debug	= 0;
 
-typedef	struct	Link	Link;
 typedef	struct	WaitQ	WaitQ;
 typedef	struct	SudoG	SudoG;
 typedef	struct	Select	Select;
@@ -51,12 +50,6 @@ struct	Hchan
 // chanbuf(c, i) is pointer to the i'th slot in the buffer.
 #define chanbuf(c, i) ((byte*)((c)+1)+(uintptr)(c)->elemsize*(i))
 
-struct	Link
-{
-	Link*	link;			// asynch queue circular linked list
-	byte	elem[8];		// asynch queue data element (+ more)
-};
-
 enum
 {
 	// Scase.kind
@@ -121,7 +114,6 @@ runtime·makechan_c(Type *elem, int64 hint)
 	by = runtime·mal(n + hint*elem->size);
 
 	c = (Hchan*)by;
-	by += n;
 	runtime·addfinalizer(c, destroychan, 0);
 
 	c->elemsize = elem->size;
@@ -136,6 +128,15 @@ runtime·makechan_c(Type *elem, int64 hint)
 	return c;
 }
 
+// For reflect
+//	func makechan(typ *ChanType, size uint32) (chan)
+void
+reflect·makechan(ChanType *t, uint32 size, Hchan *c)
+{
+	c = runtime·makechan_c(t->elem, size);
+	FLUSH(&c);
+}
+
 static void
 destroychan(Hchan *c)
 {
@@ -271,6 +272,7 @@ closed:
 	runtime·panicstring("send on closed channel");
 }
 
+
 void
 runtime·chanrecv(Hchan* c, byte *ep, bool *selected, bool *received)
 {
@@ -527,6 +529,71 @@ runtime·selectnbrecv2(byte *v, bool *received, Hchan *c, bool selected)
 	runtime·chanrecv(c, v, &selected, received);
 }	
 
+// For reflect:
+//	func chansend(c chan, val iword, nb bool) (selected bool)
+// where an iword is the same word an interface value would use:
+// the actual data if it fits, or else a pointer to the data.
+//
+// The "uintptr selected" is really "bool selected" but saying
+// uintptr gets us the right alignment for the output parameter block.
+void
+reflect·chansend(Hchan *c, uintptr val, bool nb, uintptr selected)
+{
+	bool *sp;
+	byte *vp;
+	
+	if(c == nil)
+		runtime·panicstring("send to nil channel");
+
+	if(nb) {
+		selected = false;
+		sp = (bool*)&selected;
+	} else {
+		*(bool*)&selected = true;
+		FLUSH(&selected);
+		sp = nil;
+	}
+	if(c->elemsize <= sizeof(val))
+		vp = (byte*)&val;
+	else
+		vp = (byte*)val;
+	runtime·chansend(c, vp, sp);
+}
+
+// For reflect:
+//	func chanrecv(c chan, nb bool) (val iword, selected, received bool)
+// where an iword is the same word an interface value would use:
+// the actual data if it fits, or else a pointer to the data.
+void
+reflect·chanrecv(Hchan *c, bool nb, uintptr val, bool selected, bool received)
+{
+	byte *vp;
+	bool *sp;
+	
+	if(c == nil)
+		runtime·panicstring("receive from nil channel");
+
+	if(nb) {
+		selected = false;
+		sp = &selected;
+	} else {
+		selected = true;
+		FLUSH(&selected);
+		sp = nil;
+	}
+	received = false;
+	FLUSH(&received);
+	if(c->elemsize <= sizeof(val)) {
+		val = 0;
+		vp = (byte*)&val;
+	} else {
+		vp = runtime·mal(c->elemsize);
+		val = (uintptr)vp;
+		FLUSH(&val);
+	}
+	runtime·chanrecv(c, vp, sp, &received);
+}
+
 static void newselect(int32, Select**);
 
 // newselect(size uint32) (sel *byte);
@@ -1044,22 +1111,36 @@ runtime·closechan(Hchan *c)
 	runtime·unlock(c);
 }
 
+// For reflect
+//	func chanclose(c chan)
 void
-runtime·chanclose(Hchan *c)
+reflect·chanclose(Hchan *c)
 {
 	runtime·closechan(c);
 }
 
-int32
-runtime·chanlen(Hchan *c)
+// For reflect
+//	func chanlen(c chan) (len int32)
+void
+reflect·chanlen(Hchan *c, int32 len)
 {
-	return c->qcount;
+	if(c == nil)
+		len = 0;
+	else
+		len = c->qcount;
+	FLUSH(&len);
 }
 
-int32
-runtime·chancap(Hchan *c)
+// For reflect
+//	func chancap(c chan) (cap int32)
+void
+reflect·chancap(Hchan *c, int32 cap)
 {
-	return c->dataqsiz;
+	if(c == nil)
+		cap = 0;
+	else
+		cap = c->dataqsiz;
+	FLUSH(&cap);
 }
 
 static SudoG*
diff --git a/src/pkg/runtime/darwin/386/signal.c b/src/pkg/runtime/darwin/386/signal.c
index 35bbb17..29170b6 100644
--- a/src/pkg/runtime/darwin/386/signal.c
+++ b/src/pkg/runtime/darwin/386/signal.c
@@ -185,3 +185,10 @@ runtime·resetcpuprofiler(int32 hz)
 	}
 	m->profilehz = hz;
 }
+
+void
+os·sigpipe(void)
+{
+	sigaction(SIGPIPE, SIG_DFL, false);
+	runtime·raisesigpipe();
+}
diff --git a/src/pkg/runtime/darwin/386/sys.s b/src/pkg/runtime/darwin/386/sys.s
index 08eca9d..87fbdbb 100644
--- a/src/pkg/runtime/darwin/386/sys.s
+++ b/src/pkg/runtime/darwin/386/sys.s
@@ -33,6 +33,16 @@ TEXT runtime·write(SB),7,$0
 	INT	$0x80
 	RET
 
+TEXT runtime·raisesigpipe(SB),7,$8
+	get_tls(CX)
+	MOVL	m(CX), DX
+	MOVL	m_procid(DX), DX
+	MOVL	DX, 0(SP)	// thread_port
+	MOVL	$13, 4(SP)	// signal: SIGPIPE
+	MOVL	$328, AX	// __pthread_kill
+	INT	$0x80
+	RET
+
 TEXT runtime·mmap(SB),7,$0
 	MOVL	$197, AX
 	INT	$0x80
diff --git a/src/pkg/runtime/darwin/amd64/signal.c b/src/pkg/runtime/darwin/amd64/signal.c
index 3a99d23..036a3ac 100644
--- a/src/pkg/runtime/darwin/amd64/signal.c
+++ b/src/pkg/runtime/darwin/amd64/signal.c
@@ -195,3 +195,10 @@ runtime·resetcpuprofiler(int32 hz)
 	}
 	m->profilehz = hz;
 }
+
+void
+os·sigpipe(void)
+{
+	sigaction(SIGPIPE, SIG_DFL, false);
+	runtime·raisesigpipe();
+}
diff --git a/src/pkg/runtime/darwin/amd64/sys.s b/src/pkg/runtime/darwin/amd64/sys.s
index 39398e0..8d1b20f 100644
--- a/src/pkg/runtime/darwin/amd64/sys.s
+++ b/src/pkg/runtime/darwin/amd64/sys.s
@@ -38,6 +38,15 @@ TEXT runtime·write(SB),7,$0
 	SYSCALL
 	RET
 
+TEXT runtime·raisesigpipe(SB),7,$24
+	get_tls(CX)
+	MOVQ	m(CX), DX
+	MOVL	$13, DI	// arg 1 SIGPIPE
+	MOVQ	m_procid(DX), SI	// arg 2 thread_port
+	MOVL	$(0x2000000+328), AX	// syscall entry __pthread_kill
+	SYSCALL
+	RET
+
 TEXT runtime·setitimer(SB), 7, $0
 	MOVL	8(SP), DI
 	MOVQ	16(SP), SI
diff --git a/src/pkg/runtime/darwin/mem.c b/src/pkg/runtime/darwin/mem.c
index cbae187..935c032 100644
--- a/src/pkg/runtime/darwin/mem.c
+++ b/src/pkg/runtime/darwin/mem.c
@@ -36,6 +36,11 @@ runtime·SysReserve(void *v, uintptr n)
 	return runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
 }
 
+enum
+{
+	ENOMEM = 12,
+};
+
 void
 runtime·SysMap(void *v, uintptr n)
 {
@@ -43,6 +48,8 @@ runtime·SysMap(void *v, uintptr n)
 	
 	mstats.sys += n;
 	p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
+	if(p == (void*)-ENOMEM)
+		runtime·throw("runtime: out of memory");
 	if(p != v)
 		runtime·throw("runtime: cannot map pages in arena address space");
 }
diff --git a/src/pkg/runtime/darwin/os.h b/src/pkg/runtime/darwin/os.h
index 339768e..db3c2e8 100644
--- a/src/pkg/runtime/darwin/os.h
+++ b/src/pkg/runtime/darwin/os.h
@@ -27,3 +27,5 @@ void	runtime·sigaltstack(struct StackT*, struct StackT*);
 void	runtime·sigtramp(void);
 void	runtime·sigpanic(void);
 void	runtime·setitimer(int32, Itimerval*, Itimerval*);
+
+void	runtime·raisesigpipe(void);
diff --git a/src/pkg/runtime/debug/stack.go b/src/pkg/runtime/debug/stack.go
index e7d56ac..e5fae63 100644
--- a/src/pkg/runtime/debug/stack.go
+++ b/src/pkg/runtime/debug/stack.go
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The debug package contains facilities for programs to debug themselves
-// while they are running.
+// Package debug contains facilities for programs to debug themselves while
+// they are running.
 package debug
 
 import (
diff --git a/src/pkg/runtime/extern.go b/src/pkg/runtime/extern.go
index c6e664a..9da3423 100644
--- a/src/pkg/runtime/extern.go
+++ b/src/pkg/runtime/extern.go
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 /*
-	The runtime package contains operations that interact with Go's runtime system,
+	Package runtime contains operations that interact with Go's runtime system,
 	such as functions to control goroutines. It also includes the low-level type information
 	used by the reflect package; see reflect's documentation for the programmable
 	interface to the run-time type system.
diff --git a/src/pkg/runtime/freebsd/386/signal.c b/src/pkg/runtime/freebsd/386/signal.c
index 1ae2554..3600f07 100644
--- a/src/pkg/runtime/freebsd/386/signal.c
+++ b/src/pkg/runtime/freebsd/386/signal.c
@@ -182,3 +182,10 @@ runtime·resetcpuprofiler(int32 hz)
 	}
 	m->profilehz = hz;
 }
+
+void
+os·sigpipe(void)
+{
+	sigaction(SIGPIPE, SIG_DFL, false);
+	runtime·raisesigpipe();
+}
diff --git a/src/pkg/runtime/freebsd/386/sys.s b/src/pkg/runtime/freebsd/386/sys.s
index c4715b6..765e2fc 100644
--- a/src/pkg/runtime/freebsd/386/sys.s
+++ b/src/pkg/runtime/freebsd/386/sys.s
@@ -60,6 +60,20 @@ TEXT runtime·write(SB),7,$-4
 	INT	$0x80
 	RET
 
+TEXT runtime·raisesigpipe(SB),7,$12
+	// thr_self(&8(SP))
+	LEAL	8(SP), AX
+	MOVL	AX, 0(SP)
+	MOVL	$432, AX
+	INT	$0x80
+	// thr_kill(self, SIGPIPE)
+	MOVL	8(SP), AX
+	MOVL	AX, 0(SP)
+	MOVL	$13, 4(SP)
+	MOVL	$433, AX
+	INT	$0x80
+	RET
+
 TEXT runtime·notok(SB),7,$0
 	MOVL	$0xf1, 0xf1
 	RET
diff --git a/src/pkg/runtime/freebsd/amd64/signal.c b/src/pkg/runtime/freebsd/amd64/signal.c
index 9d8e5e6..85cb1d8 100644
--- a/src/pkg/runtime/freebsd/amd64/signal.c
+++ b/src/pkg/runtime/freebsd/amd64/signal.c
@@ -190,3 +190,10 @@ runtime·resetcpuprofiler(int32 hz)
 	}
 	m->profilehz = hz;
 }
+
+void
+os·sigpipe(void)
+{
+	sigaction(SIGPIPE, SIG_DFL, false);
+	runtime·raisesigpipe();
+}
diff --git a/src/pkg/runtime/freebsd/amd64/sys.s b/src/pkg/runtime/freebsd/amd64/sys.s
index 9a6fdf1..c5cc082 100644
--- a/src/pkg/runtime/freebsd/amd64/sys.s
+++ b/src/pkg/runtime/freebsd/amd64/sys.s
@@ -65,6 +65,18 @@ TEXT runtime·write(SB),7,$-8
 	SYSCALL
 	RET
 
+TEXT runtime·raisesigpipe(SB),7,$16
+	// thr_self(&8(SP))
+	LEAQ	8(SP), DI	// arg 1 &8(SP)
+	MOVL	$432, AX
+	SYSCALL
+	// thr_kill(self, SIGPIPE)
+	MOVQ	8(SP), DI	// arg 1 id
+	MOVQ	$13, SI	// arg 2 SIGPIPE
+	MOVL	$433, AX
+	SYSCALL
+	RET
+
 TEXT runtime·setitimer(SB), 7, $-8
 	MOVL	8(SP), DI
 	MOVQ	16(SP), SI
diff --git a/src/pkg/runtime/freebsd/mem.c b/src/pkg/runtime/freebsd/mem.c
index f80439e..07abf2c 100644
--- a/src/pkg/runtime/freebsd/mem.c
+++ b/src/pkg/runtime/freebsd/mem.c
@@ -42,6 +42,11 @@ runtime·SysReserve(void *v, uintptr n)
 	return runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
 }
 
+enum
+{
+	ENOMEM = 12,
+};
+
 void
 runtime·SysMap(void *v, uintptr n)
 {
@@ -52,6 +57,8 @@ runtime·SysMap(void *v, uintptr n)
 	// On 64-bit, we don't actually have v reserved, so tread carefully.
 	if(sizeof(void*) == 8) {
 		p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
+		if(p == (void*)-ENOMEM)
+			runtime·throw("runtime: out of memory");
 		if(p != v) {
 			runtime·printf("runtime: address space conflict: map(%p) = %p\n", v, p);
 			runtime·throw("runtime: address space conflict");
@@ -60,6 +67,8 @@ runtime·SysMap(void *v, uintptr n)
 	}
 
 	p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
+	if(p == (void*)-ENOMEM)
+		runtime·throw("runtime: out of memory");
 	if(p != v)
 		runtime·throw("runtime: cannot map pages in arena address space");
 }
diff --git a/src/pkg/runtime/freebsd/os.h b/src/pkg/runtime/freebsd/os.h
index 1375468..007856c 100644
--- a/src/pkg/runtime/freebsd/os.h
+++ b/src/pkg/runtime/freebsd/os.h
@@ -8,3 +8,5 @@ struct sigaction;
 void runtime·sigaction(int32, struct sigaction*, struct sigaction*);
 void	runtiem·setitimerval(int32, Itimerval*, Itimerval*);
 void	runtime·setitimer(int32, Itimerval*, Itimerval*);
+
+void	runtime·raisesigpipe(void);
diff --git a/src/pkg/runtime/hashmap.c b/src/pkg/runtime/hashmap.c
index e50cefd..5ba1eb2 100644
--- a/src/pkg/runtime/hashmap.c
+++ b/src/pkg/runtime/hashmap.c
@@ -776,6 +776,15 @@ runtime·makemap(Type *key, Type *val, int64 hint, Hmap *ret)
 	FLUSH(&ret);
 }
 
+// For reflect:
+//	func makemap(Type *mapType) (hmap *map)
+void
+reflect·makemap(MapType *t, Hmap *ret)
+{
+	ret = runtime·makemap_c(t->key, t->elem, 0);
+	FLUSH(&ret);
+}
+
 void
 runtime·mapaccess(Hmap *h, byte *ak, byte *av, bool *pres)
 {
@@ -855,6 +864,34 @@ runtime·mapaccess2(Hmap *h, ...)
 	}
 }
 
+// For reflect:
+//	func mapaccess(h map, key iword) (val iword, pres bool)
+// where an iword is the same word an interface value would use:
+// the actual data if it fits, or else a pointer to the data.
+void
+reflect·mapaccess(Hmap *h, uintptr key, uintptr val, bool pres)
+{
+	byte *ak, *av;
+
+	if(h == nil)
+		runtime·panicstring("lookup in nil map");
+	if(h->keysize <= sizeof(key))
+		ak = (byte*)&key;
+	else
+		ak = (byte*)key;
+	val = 0;
+	pres = false;
+	if(h->valsize <= sizeof(val))
+		av = (byte*)&val;
+	else {
+		av = runtime·mal(h->valsize);
+		val = (uintptr)av;
+	}
+	runtime·mapaccess(h, ak, av, &pres);
+	FLUSH(&val);
+	FLUSH(&pres);
+}
+
 void
 runtime·mapassign(Hmap *h, byte *ak, byte *av)
 {
@@ -938,6 +975,30 @@ runtime·mapassign2(Hmap *h, ...)
 	}
 }
 
+// For reflect:
+//	func mapassign(h map, key, val iword, pres bool)
+// where an iword is the same word an interface value would use:
+// the actual data if it fits, or else a pointer to the data.
+void
+reflect·mapassign(Hmap *h, uintptr key, uintptr val, bool pres)
+{
+	byte *ak, *av;
+
+	if(h == nil)
+		runtime·panicstring("lookup in nil map");
+	if(h->keysize <= sizeof(key))
+		ak = (byte*)&key;
+	else
+		ak = (byte*)key;
+	if(h->valsize <= sizeof(val))
+		av = (byte*)&val;
+	else
+		av = (byte*)val;
+	if(!pres)
+		av = nil;
+	runtime·mapassign(h, ak, av);
+}
+
 // mapiterinit(hmap *map[any]any, hiter *any);
 void
 runtime·mapiterinit(Hmap *h, struct hash_iter *it)
@@ -959,14 +1020,14 @@ runtime·mapiterinit(Hmap *h, struct hash_iter *it)
 	}
 }
 
-struct hash_iter*
-runtime·newmapiterinit(Hmap *h)
+// For reflect:
+//	func mapiterinit(h map) (it iter)
+void
+reflect·mapiterinit(Hmap *h, struct hash_iter *it)
 {
-	struct hash_iter *it;
-
 	it = runtime·mal(sizeof *it);
+	FLUSH(&it);
 	runtime·mapiterinit(h, it);
-	return it;
 }
 
 // mapiternext(hiter *any);
@@ -986,6 +1047,14 @@ runtime·mapiternext(struct hash_iter *it)
 	}
 }
 
+// For reflect:
+//	func mapiternext(it iter)
+void
+reflect·mapiternext(struct hash_iter *it)
+{
+	runtime·mapiternext(it);
+}
+
 // mapiter1(hiter *any) (key any);
 #pragma textflag 7
 void
@@ -1026,6 +1095,48 @@ runtime·mapiterkey(struct hash_iter *it, void *ak)
 	return true;
 }
 
+// For reflect:
+//	func mapiterkey(h map) (key iword, ok bool)
+// where an iword is the same word an interface value would use:
+// the actual data if it fits, or else a pointer to the data.
+void
+reflect·mapiterkey(struct hash_iter *it, uintptr key, bool ok)
+{
+	Hmap *h;
+	byte *res;
+
+	key = 0;
+	ok = false;
+	h = it->h;
+	res = it->data;
+	if(res == nil) {
+		key = 0;
+		ok = false;
+	} else {
+		key = 0;
+		if(h->keysize <= sizeof(key))
+			h->keyalg->copy(h->keysize, (byte*)&key, res);
+		else
+			key = (uintptr)res;
+		ok = true;
+	}
+	FLUSH(&key);
+	FLUSH(&ok);
+}
+
+// For reflect:
+//	func maplen(h map) (len int32)
+// Like len(m) in the actual language, we treat the nil map as length 0.
+void
+reflect·maplen(Hmap *h, int32 len)
+{
+	if(h == nil)
+		len = 0;
+	else
+		len = h->count;
+	FLUSH(&len);
+}
+
 // mapiter2(hiter *any) (key any, val any);
 #pragma textflag 7
 void
diff --git a/src/pkg/runtime/iface.c b/src/pkg/runtime/iface.c
index 698aead..b1015f6 100644
--- a/src/pkg/runtime/iface.c
+++ b/src/pkg/runtime/iface.c
@@ -6,6 +6,14 @@
 #include "type.h"
 #include "malloc.h"
 
+enum 
+{
+	// If an empty interface has these bits set in its type
+	// pointer, it was copied from a reflect.Value and is
+	// not a valid empty interface.
+	reflectFlags = 3,
+};
+
 void
 runtime·printiface(Iface i)
 {
@@ -42,7 +50,7 @@ itab(InterfaceType *inter, Type *type, int32 canfail)
 	Method *t, *et;
 	IMethod *i, *ei;
 	uint32 h;
-	String *iname;
+	String *iname, *ipkgPath;
 	Itab *m;
 	UncommonType *x;
 	Type *itype;
@@ -112,6 +120,7 @@ search:
 	for(; i < ei; i++) {
 		itype = i->type;
 		iname = i->name;
+		ipkgPath = i->pkgPath;
 		for(;; t++) {
 			if(t >= et) {
 				if(!canfail) {
@@ -128,7 +137,7 @@ search:
 				m->bad = 1;
 				goto out;
 			}
-			if(t->mtyp == itype && t->name == iname)
+			if(t->mtyp == itype && t->name == iname && t->pkgPath == ipkgPath)
 				break;
 		}
 		if(m)
@@ -276,6 +285,8 @@ runtime·assertE2T(Type *t, Eface e, ...)
 {
 	byte *ret;
 
+	if(((uintptr)e.type&reflectFlags) != 0)
+		runtime·throw("invalid interface value");
 	ret = (byte*)(&e+1);
 	assertE2Tret(t, e, ret);
 }
@@ -285,6 +296,8 @@ assertE2Tret(Type *t, Eface e, byte *ret)
 {
 	Eface err;
 
+	if(((uintptr)e.type&reflectFlags) != 0)
+		runtime·throw("invalid interface value");
 	if(e.type == nil) {
 		runtime·newTypeAssertionError(nil, nil, t,
 			nil, nil, t->string,
@@ -309,6 +322,8 @@ runtime·assertE2T2(Type *t, Eface e, ...)
 	bool *ok;
 	int32 wid;
 
+	if(((uintptr)e.type&reflectFlags) != 0)
+		runtime·throw("invalid interface value");
 	ret = (byte*)(&e+1);
 	wid = t->size;
 	ok = (bool*)(ret+runtime·rnd(wid, 1));
@@ -444,6 +459,8 @@ runtime·ifaceE2I(InterfaceType *inter, Eface e, Iface *ret)
 	Type *t;
 	Eface err;
 
+	if(((uintptr)e.type&reflectFlags) != 0)
+		runtime·throw("invalid interface value");
 	t = e.type;
 	if(t == nil) {
 		// explicit conversions require non-nil interface value.
@@ -456,6 +473,14 @@ runtime·ifaceE2I(InterfaceType *inter, Eface e, Iface *ret)
 	ret->tab = itab(inter, t, 0);
 }
 
+// For reflect
+//	func ifaceE2I(t *InterfaceType, e interface{}, dst *Iface)
+void
+reflect·ifaceE2I(InterfaceType *inter, Eface e, Iface *dst)
+{
+	runtime·ifaceE2I(inter, e, dst);
+}
+
 // func ifaceE2I(sigi *byte, iface any) (ret any)
 void
 runtime·assertE2I(InterfaceType* inter, Eface e, Iface ret)
@@ -467,6 +492,8 @@ runtime·assertE2I(InterfaceType* inter, Eface e, Iface ret)
 void
 runtime·assertE2I2(InterfaceType *inter, Eface e, Iface ret, bool ok)
 {
+	if(((uintptr)e.type&reflectFlags) != 0)
+		runtime·throw("invalid interface value");
 	if(e.type == nil) {
 		ok = 0;
 		ret.data = nil;
@@ -489,6 +516,8 @@ runtime·assertE2E(InterfaceType* inter, Eface e, Eface ret)
 	Type *t;
 	Eface err;
 
+	if(((uintptr)e.type&reflectFlags) != 0)
+		runtime·throw("invalid interface value");
 	t = e.type;
 	if(t == nil) {
 		// explicit conversions require non-nil interface value.
@@ -505,6 +534,8 @@ runtime·assertE2E(InterfaceType* inter, Eface e, Eface ret)
 void
 runtime·assertE2E2(InterfaceType* inter, Eface e, Eface ret, bool ok)
 {
+	if(((uintptr)e.type&reflectFlags) != 0)
+		runtime·throw("invalid interface value");
 	USED(inter);
 	ret = e;
 	ok = e.type != nil;
@@ -582,6 +613,10 @@ runtime·ifaceeq_c(Iface i1, Iface i2)
 bool
 runtime·efaceeq_c(Eface e1, Eface e2)
 {
+	if(((uintptr)e1.type&reflectFlags) != 0)
+		runtime·throw("invalid interface value");
+	if(((uintptr)e2.type&reflectFlags) != 0)
+		runtime·throw("invalid interface value");
 	if(e1.type != e2.type)
 		return false;
 	if(e1.type == nil)
@@ -624,6 +659,8 @@ runtime·efacethash(Eface e1, uint32 ret)
 {
 	Type *t;
 
+	if(((uintptr)e1.type&reflectFlags) != 0)
+		runtime·throw("invalid interface value");
 	ret = 0;
 	t = e1.type;
 	if(t != nil)
@@ -634,11 +671,14 @@ runtime·efacethash(Eface e1, uint32 ret)
 void
 unsafe·Typeof(Eface e, Eface ret)
 {
+	if(((uintptr)e.type&reflectFlags) != 0)
+		runtime·throw("invalid interface value");
 	if(e.type == nil) {
 		ret.type = nil;
 		ret.data = nil;
-	} else
-		ret = *(Eface*)e.type;
+	} else {
+		ret = *(Eface*)(e.type);
+	}
 	FLUSH(&ret);
 }
 
@@ -648,6 +688,8 @@ unsafe·Reflect(Eface e, Eface rettype, void *retaddr)
 	uintptr *p;
 	uintptr x;
 
+	if(((uintptr)e.type&reflectFlags) != 0)
+		runtime·throw("invalid interface value");
 	if(e.type == nil) {
 		rettype.type = nil;
 		rettype.data = nil;
@@ -678,6 +720,9 @@ unsafe·Reflect(Eface e, Eface rettype, void *retaddr)
 void
 unsafe·Unreflect(Eface typ, void *addr, Eface e)
 {
+	if(((uintptr)typ.type&reflectFlags) != 0)
+		runtime·throw("invalid interface value");
+
 	// Reflect library has reinterpreted typ
 	// as its own kind of type structure.
 	// We know that the pointer to the original
@@ -702,6 +747,9 @@ unsafe·New(Eface typ, void *ret)
 {
 	Type *t;
 
+	if(((uintptr)typ.type&reflectFlags) != 0)
+		runtime·throw("invalid interface value");
+
 	// Reflect library has reinterpreted typ
 	// as its own kind of type structure.
 	// We know that the pointer to the original
@@ -721,6 +769,9 @@ unsafe·NewArray(Eface typ, uint32 n, void *ret)
 	uint64 size;
 	Type *t;
 
+	if(((uintptr)typ.type&reflectFlags) != 0)
+		runtime·throw("invalid interface value");
+
 	// Reflect library has reinterpreted typ
 	// as its own kind of type structure.
 	// We know that the pointer to the original
diff --git a/src/pkg/runtime/linux/386/signal.c b/src/pkg/runtime/linux/386/signal.c
index 9b72ecb..8916e10 100644
--- a/src/pkg/runtime/linux/386/signal.c
+++ b/src/pkg/runtime/linux/386/signal.c
@@ -175,3 +175,10 @@ runtime·resetcpuprofiler(int32 hz)
 	}
 	m->profilehz = hz;
 }
+
+void
+os·sigpipe(void)
+{
+	sigaction(SIGPIPE, SIG_DFL, false);
+	runtime·raisesigpipe();
+}
diff --git a/src/pkg/runtime/linux/386/sys.s b/src/pkg/runtime/linux/386/sys.s
index c39ce25..868a0d9 100644
--- a/src/pkg/runtime/linux/386/sys.s
+++ b/src/pkg/runtime/linux/386/sys.s
@@ -30,6 +30,14 @@ TEXT runtime·write(SB),7,$0
 	INT	$0x80
 	RET
 
+TEXT runtime·raisesigpipe(SB),7,$12
+	MOVL	$224, AX	// syscall - gettid
+	INT	$0x80
+	MOVL	AX, 0(SP)	// arg 1 tid
+	MOVL	$13, 4(SP)	// arg 2 SIGPIPE
+	MOVL	$238, AX	// syscall - tkill
+	INT	$0x80
+	RET
 
 TEXT runtime·setitimer(SB),7,$0-24
 	MOVL	$104, AX			// syscall - setitimer
diff --git a/src/pkg/runtime/linux/amd64/signal.c b/src/pkg/runtime/linux/amd64/signal.c
index 1db9c95..ee90271 100644
--- a/src/pkg/runtime/linux/amd64/signal.c
+++ b/src/pkg/runtime/linux/amd64/signal.c
@@ -185,3 +185,10 @@ runtime·resetcpuprofiler(int32 hz)
 	}
 	m->profilehz = hz;
 }
+
+void
+os·sigpipe(void)
+{
+	sigaction(SIGPIPE, SIG_DFL, false);
+	runtime·raisesigpipe();
+}
diff --git a/src/pkg/runtime/linux/amd64/sys.s b/src/pkg/runtime/linux/amd64/sys.s
index 11df1f8..eadd300 100644
--- a/src/pkg/runtime/linux/amd64/sys.s
+++ b/src/pkg/runtime/linux/amd64/sys.s
@@ -36,6 +36,15 @@ TEXT runtime·write(SB),7,$0-24
 	SYSCALL
 	RET
 
+TEXT runtime·raisesigpipe(SB),7,$12
+	MOVL	$186, AX	// syscall - gettid
+	SYSCALL
+	MOVL	AX, DI	// arg 1 tid
+	MOVL	$13, SI	// arg 2 SIGPIPE
+	MOVL	$200, AX	// syscall - tkill
+	SYSCALL
+	RET
+
 TEXT runtime·setitimer(SB),7,$0-24
 	MOVL	8(SP), DI
 	MOVQ	16(SP), SI
diff --git a/src/pkg/runtime/linux/arm/signal.c b/src/pkg/runtime/linux/arm/signal.c
index 05c6b02..88a84d1 100644
--- a/src/pkg/runtime/linux/arm/signal.c
+++ b/src/pkg/runtime/linux/arm/signal.c
@@ -180,3 +180,10 @@ runtime·resetcpuprofiler(int32 hz)
 	}
 	m->profilehz = hz;
 }
+
+void
+os·sigpipe(void)
+{
+	sigaction(SIGPIPE, SIG_DFL, false);
+	runtime·raisesigpipe();
+}
diff --git a/src/pkg/runtime/linux/arm/sys.s b/src/pkg/runtime/linux/arm/sys.s
index b9767a0..d866b0e 100644
--- a/src/pkg/runtime/linux/arm/sys.s
+++ b/src/pkg/runtime/linux/arm/sys.s
@@ -22,11 +22,12 @@
 #define SYS_rt_sigaction (SYS_BASE + 174)
 #define SYS_sigaltstack (SYS_BASE + 186)
 #define SYS_mmap2 (SYS_BASE + 192)
-#define SYS_gettid (SYS_BASE + 224)
 #define SYS_futex (SYS_BASE + 240)
 #define SYS_exit_group (SYS_BASE + 248)
 #define SYS_munmap (SYS_BASE + 91)
 #define SYS_setitimer (SYS_BASE + 104)
+#define SYS_gettid (SYS_BASE + 224)
+#define SYS_tkill (SYS_BASE + 238)
 
 #define ARM_BASE (SYS_BASE + 0x0f0000)
 #define SYS_ARM_cacheflush (ARM_BASE + 2)
@@ -55,6 +56,15 @@ TEXT runtime·exit1(SB),7,$-4
 	MOVW	$1003, R1
 	MOVW	R0, (R1)	// fail hard
 
+TEXT	runtime·raisesigpipe(SB),7,$-4
+	MOVW	$SYS_gettid, R7
+	SWI	$0
+	// arg 1 tid already in R0 from gettid
+	MOVW	$13, R1	// arg 2 SIGPIPE
+	MOVW	$SYS_tkill, R7
+	SWI	$0
+	RET
+
 TEXT runtime·mmap(SB),7,$0
 	MOVW	0(FP), R0
 	MOVW	4(FP), R1
diff --git a/src/pkg/runtime/linux/mem.c b/src/pkg/runtime/linux/mem.c
index d2f6f82..ce1a8aa 100644
--- a/src/pkg/runtime/linux/mem.c
+++ b/src/pkg/runtime/linux/mem.c
@@ -48,6 +48,11 @@ runtime·SysReserve(void *v, uintptr n)
 	return runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
 }
 
+enum
+{
+	ENOMEM = 12,
+};
+
 void
 runtime·SysMap(void *v, uintptr n)
 {
@@ -66,6 +71,8 @@ runtime·SysMap(void *v, uintptr n)
 	}
 
 	p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
+	if(p == (void*)-ENOMEM)
+		runtime·throw("runtime: out of memory");
 	if(p != v)
 		runtime·throw("runtime: cannot map pages in arena address space");
 }
diff --git a/src/pkg/runtime/linux/os.h b/src/pkg/runtime/linux/os.h
index 6ae0889..0bb8d03 100644
--- a/src/pkg/runtime/linux/os.h
+++ b/src/pkg/runtime/linux/os.h
@@ -15,3 +15,5 @@ void	runtime·rt_sigaction(uintptr, struct Sigaction*, void*, uintptr);
 void	runtime·sigaltstack(Sigaltstack*, Sigaltstack*);
 void	runtime·sigpanic(void);
 void runtime·setitimer(int32, Itimerval*, Itimerval*);
+
+void	runtime·raisesigpipe(void);
diff --git a/src/pkg/runtime/malloc.goc b/src/pkg/runtime/malloc.goc
index 4106068..1f2d6da 100644
--- a/src/pkg/runtime/malloc.goc
+++ b/src/pkg/runtime/malloc.goc
@@ -346,7 +346,7 @@ runtime·MHeap_SysAlloc(MHeap *h, uintptr n)
 		return nil;
 
 	if(p < h->arena_start || p+n - h->arena_start >= MaxArena32) {
-		runtime·printf("runtime: memory allocated by OS not in usable range");
+		runtime·printf("runtime: memory allocated by OS not in usable range\n");
 		runtime·SysFree(p, n);
 		return nil;
 	}
diff --git a/src/pkg/runtime/mcache.c b/src/pkg/runtime/mcache.c
index 0f41a0e..e406211 100644
--- a/src/pkg/runtime/mcache.c
+++ b/src/pkg/runtime/mcache.c
@@ -22,6 +22,8 @@ runtime·MCache_Alloc(MCache *c, int32 sizeclass, uintptr size, int32 zeroed)
 		// Replenish using central lists.
 		n = runtime·MCentral_AllocList(&runtime·mheap.central[sizeclass],
 			runtime·class_to_transfercount[sizeclass], &first);
+		if(n == 0)
+			runtime·throw("out of memory");
 		l->list = first;
 		l->nlist = n;
 		c->size += n*size;
diff --git a/src/pkg/runtime/mgc0.c b/src/pkg/runtime/mgc0.c
index 14d485b..ac6a1fa 100644
--- a/src/pkg/runtime/mgc0.c
+++ b/src/pkg/runtime/mgc0.c
@@ -6,6 +6,7 @@
 
 #include "runtime.h"
 #include "malloc.h"
+#include "stack.h"
 
 enum {
 	Debug = 0,
@@ -92,6 +93,11 @@ scanblock(byte *b, int64 n)
 	void **bw, **w, **ew;
 	Workbuf *wbuf;
 
+	if((int64)(uintptr)n != n || n < 0) {
+		runtime·printf("scanblock %p %D\n", b, n);
+		runtime·throw("scanblock");
+	}
+
 	// Memory arena parameters.
 	arena_start = runtime·mheap.arena_start;
 	
@@ -323,20 +329,46 @@ getfull(Workbuf *b)
 static void
 scanstack(G *gp)
 {
+	int32 n;
 	Stktop *stk;
-	byte *sp;
+	byte *sp, *guard;
+
+	stk = (Stktop*)gp->stackbase;
+	guard = gp->stackguard;
 
-	if(gp == g)
+	if(gp == g) {
+		// Scanning our own stack: start at &gp.
 		sp = (byte*)&gp;
-	else
+	} else {
+		// Scanning another goroutine's stack.
+		// The goroutine is usually asleep (the world is stopped).
 		sp = 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 != nil) {
+			stk = (Stktop*)gp->gcstack;
+			sp = gp->gcsp;
+			guard = gp->gcguard;
+		}
+	}
+
 	if(Debug > 1)
 		runtime·printf("scanstack %d %p\n", gp->goid, sp);
-	stk = (Stktop*)gp->stackbase;
+	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");
+		}
 		scanblock(sp, (byte*)stk - sp);
 		sp = stk->gobuf.sp;
+		guard = stk->stackguard;
 		stk = (Stktop*)stk->stackbase;
+		n++;
 	}
 }
 
diff --git a/src/pkg/runtime/mheap.c b/src/pkg/runtime/mheap.c
index 8061b7c..dde31ce 100644
--- a/src/pkg/runtime/mheap.c
+++ b/src/pkg/runtime/mheap.c
@@ -180,9 +180,7 @@ MHeap_Grow(MHeap *h, uintptr npage)
 	// Allocate a multiple of 64kB (16 pages).
 	npage = (npage+15)&~15;
 	ask = npage<<PageShift;
-	if(ask > h->arena_end - h->arena_used)
-		return false;
-	if(ask < HeapAllocChunk && HeapAllocChunk <= h->arena_end - h->arena_used)
+	if(ask < HeapAllocChunk)
 		ask = HeapAllocChunk;
 
 	v = runtime·MHeap_SysAlloc(h, ask);
@@ -191,8 +189,10 @@ MHeap_Grow(MHeap *h, uintptr npage)
 			ask = npage<<PageShift;
 			v = runtime·MHeap_SysAlloc(h, ask);
 		}
-		if(v == nil)
+		if(v == nil) {
+			runtime·printf("runtime: out of memory: cannot allocate %D-byte block (%D in use)\n", (uint64)ask, mstats.heap_sys);
 			return false;
+		}
 	}
 	mstats.heap_sys += ask;
 
diff --git a/src/pkg/runtime/mkversion.c b/src/pkg/runtime/mkversion.c
index 56afa18..0d96aa3 100644
--- a/src/pkg/runtime/mkversion.c
+++ b/src/pkg/runtime/mkversion.c
@@ -4,7 +4,7 @@
 char *template =
 	"// generated by mkversion.c; do not edit.\n"
 	"package runtime\n"
-	"const defaultGoroot = \"%s\"\n"
+	"const defaultGoroot = `%s`\n"
 	"const theVersion = \"%s\"\n";
 
 void
diff --git a/src/pkg/runtime/plan9/mem.c b/src/pkg/runtime/plan9/mem.c
index b840de9..9dfdf2c 100644
--- a/src/pkg/runtime/plan9/mem.c
+++ b/src/pkg/runtime/plan9/mem.c
@@ -4,6 +4,7 @@
 
 #include "runtime.h"
 #include "malloc.h"
+#include "os.h"
 
 extern byte end[];
 static byte *bloc = { end };
@@ -52,5 +53,6 @@ runtime·SysMap(void *v, uintptr nbytes)
 void*
 runtime·SysReserve(void *v, uintptr nbytes)
 {
+	USED(v);
 	return runtime·SysAlloc(nbytes);
 }
diff --git a/src/pkg/runtime/plan9/thread.c b/src/pkg/runtime/plan9/thread.c
index fa96552..7c6ca45 100644
--- a/src/pkg/runtime/plan9/thread.c
+++ b/src/pkg/runtime/plan9/thread.c
@@ -138,3 +138,8 @@ runtime·notewakeup(Note *n)
 	runtime·usemrelease(&n->sema);
 }
 
+void
+os·sigpipe(void)
+{
+	runtime·throw("too many writes on closed pipe");
+}
diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c
index e212c78..5278485 100644
--- a/src/pkg/runtime/proc.c
+++ b/src/pkg/runtime/proc.c
@@ -590,6 +590,9 @@ schedule(G *gp)
 // re-queues g and runs everyone else who is waiting
 // before running g again.  If g->status is Gmoribund,
 // kills off g.
+// Cannot split stack because it is called from exitsyscall.
+// See comment below.
+#pragma textflag 7
 void
 runtime·gosched(void)
 {
@@ -604,19 +607,17 @@ runtime·gosched(void)
 // Record that it's not using the cpu anymore.
 // This is called only from the go syscall library and cgocall,
 // not from the low-level system calls used by the runtime.
+//
 // Entersyscall cannot split the stack: the runtime·gosave must
-// make g->sched refer to the caller's stack pointer.
+// make g->sched refer to the caller's stack segment, because
+// entersyscall is going to return immediately after.
 // It's okay to call matchmg and notewakeup even after
 // decrementing mcpu, because we haven't released the
-// sched lock yet.
+// sched lock yet, so the garbage collector cannot be running.
 #pragma textflag 7
 void
 runtime·entersyscall(void)
 {
-	// Leave SP around for gc and traceback.
-	// Do before notewakeup so that gc
-	// never sees Gsyscall with wrong stack.
-	runtime·gosave(&g->sched);
 	if(runtime·sched.predawn)
 		return;
 	schedlock();
@@ -625,10 +626,23 @@ runtime·entersyscall(void)
 	runtime·sched.msyscall++;
 	if(runtime·sched.gwait != 0)
 		matchmg();
+
 	if(runtime·sched.waitstop && runtime·sched.mcpu <= runtime·sched.mcpumax) {
 		runtime·sched.waitstop = 0;
 		runtime·notewakeup(&runtime·sched.stopped);
 	}
+
+	// Leave SP around for gc and traceback.
+	// Do before schedunlock so that gc
+	// never sees Gsyscall with wrong stack.
+	runtime·gosave(&g->sched);
+	g->gcsp = g->sched.sp;
+	g->gcstack = g->stackbase;
+	g->gcguard = g->stackguard;
+	if(g->gcsp < g->gcguard-StackGuard || g->gcstack < g->gcsp) {
+		runtime·printf("entersyscall inconsistent %p [%p,%p]\n", g->gcsp, g->gcguard-StackGuard, g->gcstack);
+		runtime·throw("entersyscall");
+	}
 	schedunlock();
 }
 
@@ -647,7 +661,11 @@ runtime·exitsyscall(void)
 	runtime·sched.mcpu++;
 	// Fast path - if there's room for this m, we're done.
 	if(m->profilehz == runtime·sched.profilehz && runtime·sched.mcpu <= runtime·sched.mcpumax) {
+		// There's a cpu for us, so we can run.
 		g->status = Grunning;
+		// Garbage collector isn't running (since we are),
+		// so okay to clear gcstack.
+		g->gcstack = nil;
 		schedunlock();
 		return;
 	}
@@ -663,6 +681,14 @@ runtime·exitsyscall(void)
 	// When the scheduler takes g away from m,
 	// it will undo the runtime·sched.mcpu++ above.
 	runtime·gosched();
+	
+	// Gosched returned, so we're allowed to run now.
+	// Delete the gcstack information that we left for
+	// the garbage collector during the system call.
+	// Must wait until now because until gosched returns
+	// we don't know for sure that the garbage collector
+	// is not running.
+	g->gcstack = nil;
 }
 
 void
@@ -1196,6 +1222,12 @@ runtime·gomaxprocsfunc(int32 n)
 	if (n <= 0)
 		n = ret;
 	runtime·gomaxprocs = n;
+ 	if (runtime·gcwaiting != 0) {
+ 		if (runtime·sched.mcpumax != 1)
+ 			runtime·throw("invalid runtime·sched.mcpumax during gc");
+		schedunlock();
+		return ret;
+	}
 	runtime·sched.mcpumax = n;
 	// handle fewer procs?
 	if(runtime·sched.mcpu > runtime·sched.mcpumax) {
diff --git a/src/pkg/runtime/proc_test.go b/src/pkg/runtime/proc_test.go
new file mode 100644
index 0000000..a15b2d8
--- /dev/null
+++ b/src/pkg/runtime/proc_test.go
@@ -0,0 +1,43 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime_test
+
+import (
+	"runtime"
+	"testing"
+)
+
+var stop = make(chan bool, 1)
+
+func perpetuumMobile() {
+	select {
+	case <-stop:
+	default:
+		go perpetuumMobile()
+	}
+}
+
+func TestStopTheWorldDeadlock(t *testing.T) {
+	if testing.Short() {
+		t.Logf("skipping during short test")
+		return
+	}
+	runtime.GOMAXPROCS(3)
+	compl := make(chan int, 1)
+	go func() {
+		for i := 0; i != 1000; i += 1 {
+			runtime.GC()
+		}
+		compl <- 0
+	}()
+	go func() {
+		for i := 0; i != 1000; i += 1 {
+			runtime.GOMAXPROCS(3)
+		}
+	}()
+	go perpetuumMobile()
+	<-compl
+	stop <- true
+}
diff --git a/src/pkg/runtime/reflect.goc b/src/pkg/runtime/reflect.goc
deleted file mode 100644
index 9bdc48a..0000000
--- a/src/pkg/runtime/reflect.goc
+++ /dev/null
@@ -1,114 +0,0 @@
-// 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.
-
-package reflect
-#include "runtime.h"
-#include "type.h"
-
-static Type*
-gettype(void *typ)
-{
-	// typ is a *runtime.Type (or *runtime.MapType, etc), but the Type
-	// defined in type.h includes an interface value header
-	// in front of the raw structure.  the -2 below backs up
-	// to the interface value header.
-	return (Type*)((void**)typ - 2);
-}
-
-/*
- * Go wrappers around the C functions near the bottom of hashmap.c
- * There's no recursion here even though it looks like there is:
- * the names after func are in the reflect package name space
- * but the names in the C bodies are in the standard C name space.
- */
-
-func mapaccess(map *byte, key *byte, val *byte) (pres bool) {
-	runtime·mapaccess((Hmap*)map, key, val, &pres);
-}
-
-func mapassign(map *byte, key *byte, val *byte) {
-	runtime·mapassign((Hmap*)map, key, val);
-}
-
-func maplen(map *byte) (len int32) {
-	// length is first word of map
-	len = *(uint32*)map;
-}
-
-func mapiterinit(map *byte) (it *byte) {
-	it = (byte*)runtime·newmapiterinit((Hmap*)map);
-}
-
-func mapiternext(it *byte) {
-	runtime·mapiternext((struct hash_iter*)it);
-}
-
-func mapiterkey(it *byte, key *byte) (ok bool) {
-	ok = runtime·mapiterkey((struct hash_iter*)it, key);
-}
-
-func makemap(typ *byte) (map *byte) {
-	MapType *t;
-
-	t = (MapType*)gettype(typ);
-	map = (byte*)runtime·makemap_c(t->key, t->elem, 0);
-}
-
-/*
- * Go wrappers around the C functions in chan.c
- */
-
-func makechan(typ *byte, size uint32) (ch *byte) {
-	ChanType *t;
-
-	// typ is a *runtime.ChanType, but the ChanType
-	// defined in type.h includes an interface value header
-	// in front of the raw ChanType.  the -2 below backs up
-	// to the interface value header.
-	t = (ChanType*)gettype(typ);
-	ch = (byte*)runtime·makechan_c(t->elem, size);
-}
-
-func chansend(ch *byte, val *byte, selected *bool) {
-	runtime·chansend((Hchan*)ch, val, selected);
-}
-
-func chanrecv(ch *byte, val *byte, selected *bool, received *bool) {
-	runtime·chanrecv((Hchan*)ch, val, selected, received);
-}
-
-func chanclose(ch *byte) {
-	runtime·chanclose((Hchan*)ch);
-}
-
-func chanlen(ch *byte) (r int32) {
-	r = runtime·chanlen((Hchan*)ch);
-}
-
-func chancap(ch *byte) (r int32) {
-	r = runtime·chancap((Hchan*)ch);
-}
-
-
-/*
- * Go wrappers around the functions in iface.c
- */
-
-func setiface(typ *byte, x *byte, ret *byte) {
-	InterfaceType *t;
-
-	t = (InterfaceType*)gettype(typ);
-	if(t->mhdr.len == 0) {
-		// already an empty interface
-		*(Eface*)ret = *(Eface*)x;
-		return;
-	}
-	if(((Eface*)x)->type == nil) {
-		// can assign nil to any interface
-		((Iface*)ret)->tab = nil;
-		((Iface*)ret)->data = nil;
-		return;
-	}
-	runtime·ifaceE2I((InterfaceType*)gettype(typ), *(Eface*)x, (Iface*)ret);
-}
diff --git a/src/pkg/runtime/runtime-gdb.py b/src/pkg/runtime/runtime-gdb.py
index 08772a4..3f767fb 100644
--- a/src/pkg/runtime/runtime-gdb.py
+++ b/src/pkg/runtime/runtime-gdb.py
@@ -122,10 +122,13 @@ class ChanTypePrinter:
 		return str(self.val.type)
 
 	def children(self):
-		ptr = self.val['recvdataq']
-		for idx in range(self.val["qcount"]):
-			yield ('[%d]' % idx, ptr['elem'])
-			ptr = ptr['link']
+		# see chan.c chanbuf()
+		et = [x.type for x in self.val['free'].type.target().fields() if x.name == 'elem'][0]
+                ptr = (self.val.address + 1).cast(et.pointer())
+                for i in range(self.val["qcount"]):
+			j = (self.val["recvx"] + i) % self.val["dataqsiz"]
+			yield ('[%d]' % i, (ptr + j).dereference())
+
 
 #
 #  Register all the *Printer classes above.
diff --git a/src/pkg/runtime/runtime.h b/src/pkg/runtime/runtime.h
index 6cf2685..f9b404e 100644
--- a/src/pkg/runtime/runtime.h
+++ b/src/pkg/runtime/runtime.h
@@ -183,6 +183,9 @@ struct	G
 	Defer*	defer;
 	Panic*	panic;
 	Gobuf	sched;
+	byte*	gcstack;		// if status==Gsyscall, gcstack = stackbase to use during gc
+	byte*	gcsp;		// if status==Gsyscall, gcsp = sched.sp to use during gc
+	byte*	gcguard;		// if status==Gsyscall, gcguard = stackguard to use during gc
 	byte*	stack0;
 	byte*	entry;		// initial function
 	G*	alllink;	// on allg
@@ -241,6 +244,7 @@ struct	M
 	void*	sehframe;
 #endif
 };
+
 struct	Stktop
 {
 	// The offsets of these fields are known to (hard-coded in) libmach.
@@ -580,7 +584,6 @@ int32	runtime·gomaxprocsfunc(int32 n);
 
 void	runtime·mapassign(Hmap*, byte*, byte*);
 void	runtime·mapaccess(Hmap*, byte*, byte*, bool*);
-struct hash_iter*	runtime·newmapiterinit(Hmap*);
 void	runtime·mapiternext(struct hash_iter*);
 bool	runtime·mapiterkey(struct hash_iter*, void*);
 void	runtime·mapiterkeyvalue(struct hash_iter*, void*, void*);
@@ -589,7 +592,6 @@ Hmap*	runtime·makemap_c(Type*, Type*, int64);
 Hchan*	runtime·makechan_c(Type*, int64);
 void	runtime·chansend(Hchan*, void*, bool*);
 void	runtime·chanrecv(Hchan*, void*, bool*, bool*);
-void	runtime·chanclose(Hchan*);
 int32	runtime·chanlen(Hchan*);
 int32	runtime·chancap(Hchan*);
 
diff --git a/src/pkg/runtime/symtab.c b/src/pkg/runtime/symtab.c
index 6f0eea0..da45797 100644
--- a/src/pkg/runtime/symtab.c
+++ b/src/pkg/runtime/symtab.c
@@ -291,7 +291,9 @@ splitpcln(void)
 		if(f < ef && pc >= (f+1)->entry) {
 			f->pcln.len = p - f->pcln.array;
 			f->pcln.cap = f->pcln.len;
-			f++;
+			do
+				f++;
+			while(f < ef && pc >= (f+1)->entry);
 			f->pcln.array = p;
 			// pc0 and ln0 are the starting values for
 			// the loop over f->pcln, so pc must be 
diff --git a/src/pkg/runtime/type.go b/src/pkg/runtime/type.go
index 71ad4e7..30f3ec6 100644
--- a/src/pkg/runtime/type.go
+++ b/src/pkg/runtime/type.go
@@ -117,8 +117,9 @@ type UnsafePointerType commonType
 // ArrayType represents a fixed array type.
 type ArrayType struct {
 	commonType
-	elem *Type // array element type
-	len  uintptr
+	elem  *Type // array element type
+	slice *Type // slice type
+	len   uintptr
 }
 
 // SliceType represents a slice type.
diff --git a/src/pkg/runtime/windows/thread.c b/src/pkg/runtime/windows/thread.c
index aedd242..2ce92dc 100644
--- a/src/pkg/runtime/windows/thread.c
+++ b/src/pkg/runtime/windows/thread.c
@@ -378,3 +378,9 @@ runtime·compilecallback(Eface fn, bool cleanstack)
 
 	return ret;
 }
+
+void
+os·sigpipe(void)
+{
+	runtime·throw("too many writes on closed pipe");
+}
diff --git a/src/pkg/scanner/scanner.go b/src/pkg/scanner/scanner.go
index ec22664..e79d392 100644
--- a/src/pkg/scanner/scanner.go
+++ b/src/pkg/scanner/scanner.go
@@ -2,10 +2,11 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// A scanner and tokenizer for UTF-8-encoded text.  Takes an io.Reader
-// providing the source, which then can be tokenized through repeated calls
-// to the Scan function.  For compatibility with existing tools, the NUL
-// character is not allowed (implementation restriction).
+// Package scanner provides a scanner and tokenizer for UTF-8-encoded text.
+// It takes an io.Reader providing the source, which then can be tokenized
+// through repeated calls to the Scan function.  For compatibility with
+// existing tools, the NUL character is not allowed (implementation
+// restriction).
 //
 // By default, a Scanner skips white space and Go comments and recognizes all
 // literals as defined by the Go language specification.  It may be
diff --git a/src/pkg/sort/sort.go b/src/pkg/sort/sort.go
index c7945d2..30b1819 100644
--- a/src/pkg/sort/sort.go
+++ b/src/pkg/sort/sort.go
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The sort package provides primitives for sorting arrays
-// and user-defined collections.
+// Package sort provides primitives for sorting arrays and user-defined
+// collections.
 package sort
 
 // A type, typically a collection, that satisfies sort.Interface can be
diff --git a/src/pkg/strconv/atof.go b/src/pkg/strconv/atof.go
index 72f162c..a91e8bf 100644
--- a/src/pkg/strconv/atof.go
+++ b/src/pkg/strconv/atof.go
@@ -2,16 +2,16 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// Package strconv implements conversions to and from string representations
+// of basic data types.
+package strconv
+
 // decimal to binary floating point conversion.
 // Algorithm:
 //   1) Store input in multiprecision decimal.
 //   2) Multiply/divide decimal by powers of two until in range [0.5, 1)
 //   3) Multiply by 2^precision and round to get mantissa.
 
-// The strconv package implements conversions to and from
-// string representations of basic data types.
-package strconv
-
 import (
 	"math"
 	"os"
diff --git a/src/pkg/strings/strings.go b/src/pkg/strings/strings.go
index 93c7c46..bfd0571 100644
--- a/src/pkg/strings/strings.go
+++ b/src/pkg/strings/strings.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// A package of simple functions to manipulate strings.
+// Package strings implements simple functions to manipulate strings.
 package strings
 
 import (
diff --git a/src/pkg/sync/mutex.go b/src/pkg/sync/mutex.go
index da565d3..13f03ca 100644
--- a/src/pkg/sync/mutex.go
+++ b/src/pkg/sync/mutex.go
@@ -2,11 +2,10 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The sync package provides basic synchronization primitives
-// such as mutual exclusion locks.  Other than the Once and
-// WaitGroup types, most are intended for use by low-level
-// library routines.  Higher-level synchronization is better
-// done via channels and communication.
+// Package sync provides basic synchronization primitives such as mutual
+// exclusion locks.  Other than the Once and WaitGroup types, most are intended
+// for use by low-level library routines.  Higher-level synchronization is
+// better done via channels and communication.
 package sync
 
 import (
diff --git a/src/pkg/syscall/exec_windows.go b/src/pkg/syscall/exec_windows.go
index aeee191..85b1c2e 100644
--- a/src/pkg/syscall/exec_windows.go
+++ b/src/pkg/syscall/exec_windows.go
@@ -8,6 +8,7 @@ package syscall
 
 import (
 	"sync"
+	"unsafe"
 	"utf16"
 )
 
@@ -217,9 +218,10 @@ func joinExeDirAndFName(dir, p string) (name string, err int) {
 }
 
 type ProcAttr struct {
-	Dir   string
-	Env   []string
-	Files []int
+	Dir        string
+	Env        []string
+	Files      []int
+	HideWindow bool
 }
 
 var zeroAttributes ProcAttr
@@ -279,8 +281,12 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid, handle int,
 		}
 	}
 	si := new(StartupInfo)
-	GetStartupInfo(si)
+	si.Cb = uint32(unsafe.Sizeof(*si))
 	si.Flags = STARTF_USESTDHANDLES
+	if attr.HideWindow {
+		si.Flags |= STARTF_USESHOWWINDOW
+		si.ShowWindow = SW_HIDE
+	}
 	si.StdInput = fd[0]
 	si.StdOutput = fd[1]
 	si.StdErr = fd[2]
diff --git a/src/pkg/syscall/mkerrors.sh b/src/pkg/syscall/mkerrors.sh
index 68a1684..0bfd9af 100755
--- a/src/pkg/syscall/mkerrors.sh
+++ b/src/pkg/syscall/mkerrors.sh
@@ -47,6 +47,7 @@ includes_Darwin='
 #include <sys/sysctl.h>
 #include <sys/mman.h>
 #include <sys/wait.h>
+#include <net/bpf.h>
 #include <net/if.h>
 #include <net/route.h>
 #include <netinet/in.h>
@@ -134,6 +135,7 @@ done
 		$2 ~ /^SIOC/ ||
 		$2 ~ /^(IFF|NET_RT|RTM|RTF|RTV|RTA|RTAX)_/ ||
 		$2 ~ /^BIOC/ ||
+		$2 !~ /^(BPF_TIMEVAL)$/ &&
 		$2 ~ /^(BPF|DLT)_/ ||
 		$2 !~ "WMESGLEN" &&
 		$2 ~ /^W[A-Z0-9]+$/ {printf("\t$%s = %s,\n", $2, $2)}
diff --git a/src/pkg/syscall/syscall.go b/src/pkg/syscall/syscall.go
index 2a9ffd4..157abaa 100644
--- a/src/pkg/syscall/syscall.go
+++ b/src/pkg/syscall/syscall.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package contains an interface to the low-level operating system
+// Package syscall contains an interface to the low-level operating system
 // primitives.  The details vary depending on the underlying system.
 // Its primary use is inside other packages that provide a more portable
 // interface to the system, such as "os", "time" and "net".  Use those
diff --git a/src/pkg/syscall/syscall_linux.go b/src/pkg/syscall/syscall_linux.go
index 2b221bd..4a3797c 100644
--- a/src/pkg/syscall/syscall_linux.go
+++ b/src/pkg/syscall/syscall_linux.go
@@ -814,6 +814,13 @@ func Munmap(b []byte) (errno int) {
 	return mapper.Munmap(b)
 }
 
+//sys	Madvise(b []byte, advice int) (errno int)
+//sys	Mprotect(b []byte, prot int) (errno int)
+//sys	Mlock(b []byte) (errno int)
+//sys	Munlock(b []byte) (errno int)
+//sys	Mlockall(flags int) (errno int)
+//sys	Munlockall() (errno int)
+
 /*
  * Unimplemented
  */
@@ -868,12 +875,9 @@ func Munmap(b []byte) (errno int) {
 // LookupDcookie
 // Lremovexattr
 // Lsetxattr
-// Madvise
 // Mbind
 // MigratePages
 // Mincore
-// Mlock
-// Mmap
 // ModifyLdt
 // Mount
 // MovePages
@@ -890,9 +894,6 @@ func Munmap(b []byte) (errno int) {
 // Msgrcv
 // Msgsnd
 // Msync
-// Munlock
-// Munlockall
-// Munmap
 // Newfstatat
 // Nfsservctl
 // Personality
diff --git a/src/pkg/syscall/syscall_linux_arm.go b/src/pkg/syscall/syscall_linux_arm.go
index 6472c4d..4587458 100644
--- a/src/pkg/syscall/syscall_linux_arm.go
+++ b/src/pkg/syscall/syscall_linux_arm.go
@@ -24,7 +24,6 @@ func NsecToTimeval(nsec int64) (tv Timeval) {
 }
 
 // Pread and Pwrite are special: they insert padding before the int64.
-// (Ftruncate and truncate are not; go figure.)
 
 func Pread(fd int, p []byte, offset int64) (n int, errno int) {
 	var _p0 unsafe.Pointer
@@ -48,6 +47,20 @@ func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
 	return
 }
 
+func Ftruncate(fd int, length int64) (errno int) {
+	// ARM EABI requires 64-bit arguments should be put in a pair
+	// of registers from an even register number.
+	_, _, e1 := Syscall6(SYS_FTRUNCATE64, uintptr(fd), 0, uintptr(length), uintptr(length>>32), 0, 0)
+	errno = int(e1)
+	return
+}
+
+func Truncate(path string, length int64) (errno int) {
+	_, _, e1 := Syscall6(SYS_TRUNCATE64, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, uintptr(length), uintptr(length>>32), 0, 0)
+	errno = int(e1)
+	return
+}
+
 // Seek is defined in assembly.
 
 func Seek(fd int, offset int64, whence int) (newoffset int64, errno int)
@@ -72,7 +85,6 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, errno int)
 //sys	Fchown(fd int, uid int, gid int) (errno int)
 //sys	Fstat(fd int, stat *Stat_t) (errno int) = SYS_FSTAT64
 //sys	Fstatfs(fd int, buf *Statfs_t) (errno int) = SYS_FSTATFS64
-//sys	Ftruncate(fd int, length int64) (errno int) = SYS_FTRUNCATE64
 //sysnb	Getegid() (egid int)
 //sysnb	Geteuid() (euid int)
 //sysnb	Getgid() (gid int)
@@ -92,7 +104,6 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, errno int)
 //sys	Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int, errno int)
 //sys	Stat(path string, stat *Stat_t) (errno int) = SYS_STAT64
 //sys	Statfs(path string, buf *Statfs_t) (errno int) = SYS_STATFS64
-//sys	Truncate(path string, length int64) (errno int) = SYS_TRUNCATE64
 
 // Vsyscalls on amd64.
 //sysnb	Gettimeofday(tv *Timeval) (errno int)
diff --git a/src/pkg/syscall/syscall_windows.go b/src/pkg/syscall/syscall_windows.go
index 4ac2154..1fbb3cc 100644
--- a/src/pkg/syscall/syscall_windows.go
+++ b/src/pkg/syscall/syscall_windows.go
@@ -220,9 +220,12 @@ func Open(path string, mode int, perm uint32) (fd int, errno int) {
 	var createmode uint32
 	switch {
 	case mode&O_CREAT != 0:
-		if mode&O_EXCL != 0 {
+		switch {
+		case mode&O_EXCL != 0:
 			createmode = CREATE_NEW
-		} else {
+		case mode&O_APPEND != 0:
+			createmode = OPEN_ALWAYS
+		default:
 			createmode = CREATE_ALWAYS
 		}
 	case mode&O_TRUNC != 0:
@@ -247,27 +250,6 @@ func Read(fd int, p []byte) (n int, errno int) {
 	return int(done), 0
 }
 
-// TODO(brainman): ReadFile/WriteFile change file offset, therefore
-// i use Seek here to preserve semantics of unix pread/pwrite,
-// not sure if I should do that
-
-func Pread(fd int, p []byte, offset int64) (n int, errno int) {
-	curoffset, e := Seek(fd, 0, 1)
-	if e != 0 {
-		return 0, e
-	}
-	defer Seek(fd, curoffset, 0)
-	var o Overlapped
-	o.OffsetHigh = uint32(offset >> 32)
-	o.Offset = uint32(offset)
-	var done uint32
-	e = ReadFile(int32(fd), p, &done, &o)
-	if e != 0 {
-		return 0, e
-	}
-	return int(done), 0
-}
-
 func Write(fd int, p []byte) (n int, errno int) {
 	var done uint32
 	e := WriteFile(int32(fd), p, &done, nil)
@@ -277,23 +259,6 @@ func Write(fd int, p []byte) (n int, errno int) {
 	return int(done), 0
 }
 
-func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
-	curoffset, e := Seek(fd, 0, 1)
-	if e != 0 {
-		return 0, e
-	}
-	defer Seek(fd, curoffset, 0)
-	var o Overlapped
-	o.OffsetHigh = uint32(offset >> 32)
-	o.Offset = uint32(offset)
-	var done uint32
-	e = WriteFile(int32(fd), p, &done, &o)
-	if e != 0 {
-		return 0, e
-	}
-	return int(done), 0
-}
-
 func Seek(fd int, offset int64, whence int) (newoffset int64, errno int) {
 	var w uint32
 	switch whence {
diff --git a/src/pkg/syscall/types_darwin.c b/src/pkg/syscall/types_darwin.c
index 4096bcf..666923a 100644
--- a/src/pkg/syscall/types_darwin.c
+++ b/src/pkg/syscall/types_darwin.c
@@ -29,6 +29,7 @@ Input to godefs.  See also mkerrors.sh and mkall.sh
 #include <sys/types.h>
 #include <sys/un.h>
 #include <sys/wait.h>
+#include <net/bpf.h>
 #include <net/if.h>
 #include <net/if_dl.h>
 #include <net/if_var.h>
@@ -59,6 +60,7 @@ typedef long long $_C_long_long;
 
 typedef struct timespec $Timespec;
 typedef struct timeval $Timeval;
+typedef struct timeval32 $Timeval32;
 
 // Processes
 
@@ -157,3 +159,19 @@ typedef struct if_data $IfData;
 typedef struct ifa_msghdr $IfaMsghdr;
 typedef struct rt_msghdr $RtMsghdr;
 typedef struct rt_metrics $RtMetrics;
+
+// Berkeley packet filter
+
+enum {
+	$SizeofBpfVersion = sizeof(struct bpf_version),
+	$SizeofBpfStat = sizeof(struct bpf_stat),
+	$SizeofBpfProgram = sizeof(struct bpf_program),
+	$SizeofBpfInsn = sizeof(struct bpf_insn),
+	$SizeofBpfHdr = sizeof(struct bpf_hdr),
+};
+
+typedef struct bpf_version $BpfVersion;
+typedef struct bpf_stat $BpfStat;
+typedef struct bpf_program $BpfProgram;
+typedef struct bpf_insn $BpfInsn;
+typedef struct bpf_hdr $BpfHdr;
diff --git a/src/pkg/syscall/zerrors_darwin_386.go b/src/pkg/syscall/zerrors_darwin_386.go
index 48f563f..7bc1280 100644
--- a/src/pkg/syscall/zerrors_darwin_386.go
+++ b/src/pkg/syscall/zerrors_darwin_386.go
@@ -45,8 +45,109 @@ const (
 	AF_SYSTEM                   = 0x20
 	AF_UNIX                     = 0x1
 	AF_UNSPEC                   = 0
+	BIOCFLUSH                   = 0x20004268
+	BIOCGBLEN                   = 0x40044266
+	BIOCGDLT                    = 0x4004426a
+	BIOCGDLTLIST                = 0xc00c4279
+	BIOCGETIF                   = 0x4020426b
+	BIOCGHDRCMPLT               = 0x40044274
+	BIOCGRSIG                   = 0x40044272
+	BIOCGRTIMEOUT               = 0x4008426e
+	BIOCGSEESENT                = 0x40044276
+	BIOCGSTATS                  = 0x4008426f
+	BIOCIMMEDIATE               = 0x80044270
+	BIOCPROMISC                 = 0x20004269
+	BIOCSBLEN                   = 0xc0044266
+	BIOCSDLT                    = 0x80044278
+	BIOCSETF                    = 0x80084267
+	BIOCSETIF                   = 0x8020426c
+	BIOCSHDRCMPLT               = 0x80044275
+	BIOCSRSIG                   = 0x80044273
+	BIOCSRTIMEOUT               = 0x8008426d
+	BIOCSSEESENT                = 0x80044277
+	BIOCVERSION                 = 0x40044271
+	BPF_A                       = 0x10
+	BPF_ABS                     = 0x20
+	BPF_ADD                     = 0
+	BPF_ALIGNMENT               = 0x4
+	BPF_ALU                     = 0x4
+	BPF_AND                     = 0x50
+	BPF_B                       = 0x10
+	BPF_DIV                     = 0x30
+	BPF_H                       = 0x8
+	BPF_IMM                     = 0
+	BPF_IND                     = 0x40
+	BPF_JA                      = 0
+	BPF_JEQ                     = 0x10
+	BPF_JGE                     = 0x30
+	BPF_JGT                     = 0x20
+	BPF_JMP                     = 0x5
+	BPF_JSET                    = 0x40
+	BPF_K                       = 0
+	BPF_LD                      = 0
+	BPF_LDX                     = 0x1
+	BPF_LEN                     = 0x80
+	BPF_LSH                     = 0x60
+	BPF_MAJOR_VERSION           = 0x1
+	BPF_MAXBUFSIZE              = 0x80000
+	BPF_MAXINSNS                = 0x200
+	BPF_MEM                     = 0x60
+	BPF_MEMWORDS                = 0x10
+	BPF_MINBUFSIZE              = 0x20
+	BPF_MINOR_VERSION           = 0x1
+	BPF_MISC                    = 0x7
+	BPF_MSH                     = 0xa0
+	BPF_MUL                     = 0x20
+	BPF_NEG                     = 0x80
+	BPF_OR                      = 0x40
+	BPF_RELEASE                 = 0x30bb6
+	BPF_RET                     = 0x6
+	BPF_RSH                     = 0x70
+	BPF_ST                      = 0x2
+	BPF_STX                     = 0x3
+	BPF_SUB                     = 0x10
+	BPF_TAX                     = 0
+	BPF_TXA                     = 0x80
+	BPF_W                       = 0
+	BPF_X                       = 0x8
 	CTL_MAXNAME                 = 0xc
 	CTL_NET                     = 0x4
+	DLT_APPLE_IP_OVER_IEEE1394  = 0x8a
+	DLT_ARCNET                  = 0x7
+	DLT_ATM_CLIP                = 0x13
+	DLT_ATM_RFC1483             = 0xb
+	DLT_AX25                    = 0x3
+	DLT_CHAOS                   = 0x5
+	DLT_CHDLC                   = 0x68
+	DLT_C_HDLC                  = 0x68
+	DLT_EN10MB                  = 0x1
+	DLT_EN3MB                   = 0x2
+	DLT_FDDI                    = 0xa
+	DLT_IEEE802                 = 0x6
+	DLT_IEEE802_11              = 0x69
+	DLT_IEEE802_11_RADIO        = 0x7f
+	DLT_IEEE802_11_RADIO_AVS    = 0xa3
+	DLT_LINUX_SLL               = 0x71
+	DLT_LOOP                    = 0x6c
+	DLT_NULL                    = 0
+	DLT_PFLOG                   = 0x75
+	DLT_PFSYNC                  = 0x12
+	DLT_PPP                     = 0x9
+	DLT_PPP_BSDOS               = 0x10
+	DLT_PPP_SERIAL              = 0x32
+	DLT_PRONET                  = 0x4
+	DLT_RAW                     = 0xc
+	DLT_SLIP                    = 0x8
+	DLT_SLIP_BSDOS              = 0xf
+	DT_BLK                      = 0x6
+	DT_CHR                      = 0x2
+	DT_DIR                      = 0x4
+	DT_FIFO                     = 0x1
+	DT_LNK                      = 0xa
+	DT_REG                      = 0x8
+	DT_SOCK                     = 0xc
+	DT_UNKNOWN                  = 0
+	DT_WHT                      = 0xe
 	E2BIG                       = 0x7
 	EACCES                      = 0xd
 	EADDRINUSE                  = 0x30
@@ -196,6 +297,7 @@ const (
 	F_GETLK                     = 0x7
 	F_GETOWN                    = 0x5
 	F_GETPATH                   = 0x32
+	F_GETPROTECTIONCLASS        = 0x3e
 	F_GLOBAL_NOCACHE            = 0x37
 	F_LOG2PHYS                  = 0x31
 	F_MARKDEPENDENCY            = 0x3c
@@ -212,6 +314,7 @@ const (
 	F_SETLK                     = 0x8
 	F_SETLKW                    = 0x9
 	F_SETOWN                    = 0x6
+	F_SETPROTECTIONCLASS        = 0x3f
 	F_SETSIZE                   = 0x2b
 	F_THAW_FS                   = 0x36
 	F_UNLCK                     = 0x2
@@ -459,6 +562,16 @@ const (
 	IP_TOS                      = 0x3
 	IP_TRAFFIC_MGT_BACKGROUND   = 0x41
 	IP_TTL                      = 0x4
+	MADV_CAN_REUSE              = 0x9
+	MADV_DONTNEED               = 0x4
+	MADV_FREE                   = 0x5
+	MADV_FREE_REUSABLE          = 0x7
+	MADV_FREE_REUSE             = 0x8
+	MADV_NORMAL                 = 0
+	MADV_RANDOM                 = 0x1
+	MADV_SEQUENTIAL             = 0x2
+	MADV_WILLNEED               = 0x3
+	MADV_ZERO_WIRED_PAGES       = 0x6
 	MAP_ANON                    = 0x1000
 	MAP_COPY                    = 0x2
 	MAP_FILE                    = 0
@@ -556,6 +669,7 @@ const (
 	RTF_DYNAMIC                 = 0x10
 	RTF_GATEWAY                 = 0x2
 	RTF_HOST                    = 0x4
+	RTF_IFREF                   = 0x4000000
 	RTF_IFSCOPE                 = 0x1000000
 	RTF_LLINFO                  = 0x400
 	RTF_LOCAL                   = 0x200000
@@ -649,6 +763,7 @@ const (
 	SIOCDIFADDR                 = 0x80206919
 	SIOCDIFPHYADDR              = 0x80206941
 	SIOCDLIFADDR                = 0x8118691f
+	SIOCGDRVSPEC                = 0xc01c697b
 	SIOCGETSGCNT                = 0xc014721c
 	SIOCGETVIFCNT               = 0xc014721b
 	SIOCGETVLAN                 = 0xc020697f
@@ -680,8 +795,10 @@ const (
 	SIOCGLOWAT                  = 0x40047303
 	SIOCGPGRP                   = 0x40047309
 	SIOCIFCREATE                = 0xc0206978
+	SIOCIFCREATE2               = 0xc020697a
 	SIOCIFDESTROY               = 0x80206979
 	SIOCRSLVMULTI               = 0xc008693b
+	SIOCSDRVSPEC                = 0x801c697b
 	SIOCSETVLAN                 = 0x8020697e
 	SIOCSHIWAT                  = 0x80047300
 	SIOCSIFADDR                 = 0x8020690c
diff --git a/src/pkg/syscall/zerrors_darwin_amd64.go b/src/pkg/syscall/zerrors_darwin_amd64.go
index 840ea13..d76f092 100644
--- a/src/pkg/syscall/zerrors_darwin_amd64.go
+++ b/src/pkg/syscall/zerrors_darwin_amd64.go
@@ -45,8 +45,109 @@ const (
 	AF_SYSTEM                   = 0x20
 	AF_UNIX                     = 0x1
 	AF_UNSPEC                   = 0
+	BIOCFLUSH                   = 0x20004268
+	BIOCGBLEN                   = 0x40044266
+	BIOCGDLT                    = 0x4004426a
+	BIOCGDLTLIST                = 0xc00c4279
+	BIOCGETIF                   = 0x4020426b
+	BIOCGHDRCMPLT               = 0x40044274
+	BIOCGRSIG                   = 0x40044272
+	BIOCGRTIMEOUT               = 0x4008426e
+	BIOCGSEESENT                = 0x40044276
+	BIOCGSTATS                  = 0x4008426f
+	BIOCIMMEDIATE               = 0x80044270
+	BIOCPROMISC                 = 0x20004269
+	BIOCSBLEN                   = 0xc0044266
+	BIOCSDLT                    = 0x80044278
+	BIOCSETF                    = 0x80104267
+	BIOCSETIF                   = 0x8020426c
+	BIOCSHDRCMPLT               = 0x80044275
+	BIOCSRSIG                   = 0x80044273
+	BIOCSRTIMEOUT               = 0x8008426d
+	BIOCSSEESENT                = 0x80044277
+	BIOCVERSION                 = 0x40044271
+	BPF_A                       = 0x10
+	BPF_ABS                     = 0x20
+	BPF_ADD                     = 0
+	BPF_ALIGNMENT               = 0x4
+	BPF_ALU                     = 0x4
+	BPF_AND                     = 0x50
+	BPF_B                       = 0x10
+	BPF_DIV                     = 0x30
+	BPF_H                       = 0x8
+	BPF_IMM                     = 0
+	BPF_IND                     = 0x40
+	BPF_JA                      = 0
+	BPF_JEQ                     = 0x10
+	BPF_JGE                     = 0x30
+	BPF_JGT                     = 0x20
+	BPF_JMP                     = 0x5
+	BPF_JSET                    = 0x40
+	BPF_K                       = 0
+	BPF_LD                      = 0
+	BPF_LDX                     = 0x1
+	BPF_LEN                     = 0x80
+	BPF_LSH                     = 0x60
+	BPF_MAJOR_VERSION           = 0x1
+	BPF_MAXBUFSIZE              = 0x80000
+	BPF_MAXINSNS                = 0x200
+	BPF_MEM                     = 0x60
+	BPF_MEMWORDS                = 0x10
+	BPF_MINBUFSIZE              = 0x20
+	BPF_MINOR_VERSION           = 0x1
+	BPF_MISC                    = 0x7
+	BPF_MSH                     = 0xa0
+	BPF_MUL                     = 0x20
+	BPF_NEG                     = 0x80
+	BPF_OR                      = 0x40
+	BPF_RELEASE                 = 0x30bb6
+	BPF_RET                     = 0x6
+	BPF_RSH                     = 0x70
+	BPF_ST                      = 0x2
+	BPF_STX                     = 0x3
+	BPF_SUB                     = 0x10
+	BPF_TAX                     = 0
+	BPF_TXA                     = 0x80
+	BPF_W                       = 0
+	BPF_X                       = 0x8
 	CTL_MAXNAME                 = 0xc
 	CTL_NET                     = 0x4
+	DLT_APPLE_IP_OVER_IEEE1394  = 0x8a
+	DLT_ARCNET                  = 0x7
+	DLT_ATM_CLIP                = 0x13
+	DLT_ATM_RFC1483             = 0xb
+	DLT_AX25                    = 0x3
+	DLT_CHAOS                   = 0x5
+	DLT_CHDLC                   = 0x68
+	DLT_C_HDLC                  = 0x68
+	DLT_EN10MB                  = 0x1
+	DLT_EN3MB                   = 0x2
+	DLT_FDDI                    = 0xa
+	DLT_IEEE802                 = 0x6
+	DLT_IEEE802_11              = 0x69
+	DLT_IEEE802_11_RADIO        = 0x7f
+	DLT_IEEE802_11_RADIO_AVS    = 0xa3
+	DLT_LINUX_SLL               = 0x71
+	DLT_LOOP                    = 0x6c
+	DLT_NULL                    = 0
+	DLT_PFLOG                   = 0x75
+	DLT_PFSYNC                  = 0x12
+	DLT_PPP                     = 0x9
+	DLT_PPP_BSDOS               = 0x10
+	DLT_PPP_SERIAL              = 0x32
+	DLT_PRONET                  = 0x4
+	DLT_RAW                     = 0xc
+	DLT_SLIP                    = 0x8
+	DLT_SLIP_BSDOS              = 0xf
+	DT_BLK                      = 0x6
+	DT_CHR                      = 0x2
+	DT_DIR                      = 0x4
+	DT_FIFO                     = 0x1
+	DT_LNK                      = 0xa
+	DT_REG                      = 0x8
+	DT_SOCK                     = 0xc
+	DT_UNKNOWN                  = 0
+	DT_WHT                      = 0xe
 	E2BIG                       = 0x7
 	EACCES                      = 0xd
 	EADDRINUSE                  = 0x30
@@ -196,6 +297,7 @@ const (
 	F_GETLK                     = 0x7
 	F_GETOWN                    = 0x5
 	F_GETPATH                   = 0x32
+	F_GETPROTECTIONCLASS        = 0x3e
 	F_GLOBAL_NOCACHE            = 0x37
 	F_LOG2PHYS                  = 0x31
 	F_MARKDEPENDENCY            = 0x3c
@@ -212,6 +314,7 @@ const (
 	F_SETLK                     = 0x8
 	F_SETLKW                    = 0x9
 	F_SETOWN                    = 0x6
+	F_SETPROTECTIONCLASS        = 0x3f
 	F_SETSIZE                   = 0x2b
 	F_THAW_FS                   = 0x36
 	F_UNLCK                     = 0x2
@@ -459,6 +562,16 @@ const (
 	IP_TOS                      = 0x3
 	IP_TRAFFIC_MGT_BACKGROUND   = 0x41
 	IP_TTL                      = 0x4
+	MADV_CAN_REUSE              = 0x9
+	MADV_DONTNEED               = 0x4
+	MADV_FREE                   = 0x5
+	MADV_FREE_REUSABLE          = 0x7
+	MADV_FREE_REUSE             = 0x8
+	MADV_NORMAL                 = 0
+	MADV_RANDOM                 = 0x1
+	MADV_SEQUENTIAL             = 0x2
+	MADV_WILLNEED               = 0x3
+	MADV_ZERO_WIRED_PAGES       = 0x6
 	MAP_ANON                    = 0x1000
 	MAP_COPY                    = 0x2
 	MAP_FILE                    = 0
@@ -556,6 +669,7 @@ const (
 	RTF_DYNAMIC                 = 0x10
 	RTF_GATEWAY                 = 0x2
 	RTF_HOST                    = 0x4
+	RTF_IFREF                   = 0x4000000
 	RTF_IFSCOPE                 = 0x1000000
 	RTF_LLINFO                  = 0x400
 	RTF_LOCAL                   = 0x200000
@@ -649,6 +763,7 @@ const (
 	SIOCDIFADDR                 = 0x80206919
 	SIOCDIFPHYADDR              = 0x80206941
 	SIOCDLIFADDR                = 0x8118691f
+	SIOCGDRVSPEC                = 0xc028697b
 	SIOCGETSGCNT                = 0xc014721c
 	SIOCGETVIFCNT               = 0xc014721b
 	SIOCGETVLAN                 = 0xc020697f
@@ -680,8 +795,10 @@ const (
 	SIOCGLOWAT                  = 0x40047303
 	SIOCGPGRP                   = 0x40047309
 	SIOCIFCREATE                = 0xc0206978
+	SIOCIFCREATE2               = 0xc020697a
 	SIOCIFDESTROY               = 0x80206979
 	SIOCRSLVMULTI               = 0xc010693b
+	SIOCSDRVSPEC                = 0x8028697b
 	SIOCSETVLAN                 = 0x8020697e
 	SIOCSHIWAT                  = 0x80047300
 	SIOCSIFADDR                 = 0x8020690c
diff --git a/src/pkg/syscall/zsyscall_linux_386.go b/src/pkg/syscall/zsyscall_linux_386.go
index 83f3bad..4f331aa 100644
--- a/src/pkg/syscall/zsyscall_linux_386.go
+++ b/src/pkg/syscall/zsyscall_linux_386.go
@@ -773,6 +773,78 @@ func munmap(addr uintptr, length uintptr) (errno int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Madvise(b []byte, advice int) (errno int) {
+	var _p0 unsafe.Pointer
+	if len(b) > 0 {
+		_p0 = unsafe.Pointer(&b[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall(SYS_MADVISE, uintptr(_p0), uintptr(len(b)), uintptr(advice))
+	errno = int(e1)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mprotect(b []byte, prot int) (errno int) {
+	var _p0 unsafe.Pointer
+	if len(b) > 0 {
+		_p0 = unsafe.Pointer(&b[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall(SYS_MPROTECT, uintptr(_p0), uintptr(len(b)), uintptr(prot))
+	errno = int(e1)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mlock(b []byte) (errno int) {
+	var _p0 unsafe.Pointer
+	if len(b) > 0 {
+		_p0 = unsafe.Pointer(&b[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall(SYS_MLOCK, uintptr(_p0), uintptr(len(b)), 0)
+	errno = int(e1)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Munlock(b []byte) (errno int) {
+	var _p0 unsafe.Pointer
+	if len(b) > 0 {
+		_p0 = unsafe.Pointer(&b[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall(SYS_MUNLOCK, uintptr(_p0), uintptr(len(b)), 0)
+	errno = int(e1)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mlockall(flags int) (errno int) {
+	_, _, e1 := Syscall(SYS_MLOCKALL, uintptr(flags), 0, 0)
+	errno = int(e1)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Munlockall() (errno int) {
+	_, _, e1 := Syscall(SYS_MUNLOCKALL, 0, 0, 0)
+	errno = int(e1)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Chown(path string, uid int, gid int) (errno int) {
 	_, _, e1 := Syscall(SYS_CHOWN32, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
 	errno = int(e1)
diff --git a/src/pkg/syscall/zsyscall_linux_amd64.go b/src/pkg/syscall/zsyscall_linux_amd64.go
index c054349..19501db 100644
--- a/src/pkg/syscall/zsyscall_linux_amd64.go
+++ b/src/pkg/syscall/zsyscall_linux_amd64.go
@@ -773,6 +773,78 @@ func munmap(addr uintptr, length uintptr) (errno int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Madvise(b []byte, advice int) (errno int) {
+	var _p0 unsafe.Pointer
+	if len(b) > 0 {
+		_p0 = unsafe.Pointer(&b[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall(SYS_MADVISE, uintptr(_p0), uintptr(len(b)), uintptr(advice))
+	errno = int(e1)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mprotect(b []byte, prot int) (errno int) {
+	var _p0 unsafe.Pointer
+	if len(b) > 0 {
+		_p0 = unsafe.Pointer(&b[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall(SYS_MPROTECT, uintptr(_p0), uintptr(len(b)), uintptr(prot))
+	errno = int(e1)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mlock(b []byte) (errno int) {
+	var _p0 unsafe.Pointer
+	if len(b) > 0 {
+		_p0 = unsafe.Pointer(&b[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall(SYS_MLOCK, uintptr(_p0), uintptr(len(b)), 0)
+	errno = int(e1)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Munlock(b []byte) (errno int) {
+	var _p0 unsafe.Pointer
+	if len(b) > 0 {
+		_p0 = unsafe.Pointer(&b[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall(SYS_MUNLOCK, uintptr(_p0), uintptr(len(b)), 0)
+	errno = int(e1)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mlockall(flags int) (errno int) {
+	_, _, e1 := Syscall(SYS_MLOCKALL, uintptr(flags), 0, 0)
+	errno = int(e1)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Munlockall() (errno int) {
+	_, _, e1 := Syscall(SYS_MUNLOCKALL, 0, 0, 0)
+	errno = int(e1)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Chown(path string, uid int, gid int) (errno int) {
 	_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
 	errno = int(e1)
diff --git a/src/pkg/syscall/zsyscall_linux_arm.go b/src/pkg/syscall/zsyscall_linux_arm.go
index 49d164a..db49b64 100644
--- a/src/pkg/syscall/zsyscall_linux_arm.go
+++ b/src/pkg/syscall/zsyscall_linux_arm.go
@@ -773,6 +773,78 @@ func munmap(addr uintptr, length uintptr) (errno int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Madvise(b []byte, advice int) (errno int) {
+	var _p0 unsafe.Pointer
+	if len(b) > 0 {
+		_p0 = unsafe.Pointer(&b[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall(SYS_MADVISE, uintptr(_p0), uintptr(len(b)), uintptr(advice))
+	errno = int(e1)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mprotect(b []byte, prot int) (errno int) {
+	var _p0 unsafe.Pointer
+	if len(b) > 0 {
+		_p0 = unsafe.Pointer(&b[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall(SYS_MPROTECT, uintptr(_p0), uintptr(len(b)), uintptr(prot))
+	errno = int(e1)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mlock(b []byte) (errno int) {
+	var _p0 unsafe.Pointer
+	if len(b) > 0 {
+		_p0 = unsafe.Pointer(&b[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall(SYS_MLOCK, uintptr(_p0), uintptr(len(b)), 0)
+	errno = int(e1)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Munlock(b []byte) (errno int) {
+	var _p0 unsafe.Pointer
+	if len(b) > 0 {
+		_p0 = unsafe.Pointer(&b[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall(SYS_MUNLOCK, uintptr(_p0), uintptr(len(b)), 0)
+	errno = int(e1)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mlockall(flags int) (errno int) {
+	_, _, e1 := Syscall(SYS_MLOCKALL, uintptr(flags), 0, 0)
+	errno = int(e1)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Munlockall() (errno int) {
+	_, _, e1 := Syscall(SYS_MUNLOCKALL, 0, 0, 0)
+	errno = int(e1)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int) {
 	r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
 	fd = int(r0)
@@ -942,14 +1014,6 @@ func Fstatfs(fd int, buf *Statfs_t) (errno int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Ftruncate(fd int, length int64) (errno int) {
-	_, _, e1 := Syscall(SYS_FTRUNCATE64, uintptr(fd), uintptr(length>>32), uintptr(length))
-	errno = int(e1)
-	return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
 func Getegid() (egid int) {
 	r0, _, _ := RawSyscall(SYS_GETEGID, 0, 0, 0)
 	egid = int(r0)
@@ -1104,14 +1168,6 @@ func Statfs(path string, buf *Statfs_t) (errno int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Truncate(path string, length int64) (errno int) {
-	_, _, e1 := Syscall(SYS_TRUNCATE64, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(length>>32), uintptr(length))
-	errno = int(e1)
-	return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
 func Gettimeofday(tv *Timeval) (errno int) {
 	_, _, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
 	errno = int(e1)
diff --git a/src/pkg/syscall/ztypes_darwin_386.go b/src/pkg/syscall/ztypes_darwin_386.go
index 736c654..b354177 100644
--- a/src/pkg/syscall/ztypes_darwin_386.go
+++ b/src/pkg/syscall/ztypes_darwin_386.go
@@ -29,6 +29,11 @@ const (
 	SizeofIfaMsghdr        = 0x14
 	SizeofRtMsghdr         = 0x5c
 	SizeofRtMetrics        = 0x38
+	SizeofBpfVersion       = 0x4
+	SizeofBpfStat          = 0x8
+	SizeofBpfProgram       = 0x8
+	SizeofBpfInsn          = 0x8
+	SizeofBpfHdr           = 0x14
 )
 
 // Types
@@ -334,3 +339,33 @@ type RtMetrics struct {
 	Pksent   uint32
 	Filler   [4]uint32
 }
+
+type BpfVersion struct {
+	Major uint16
+	Minor uint16
+}
+
+type BpfStat struct {
+	Recv uint32
+	Drop uint32
+}
+
+type BpfProgram struct {
+	Len   uint32
+	Insns *BpfInsn
+}
+
+type BpfInsn struct {
+	Code uint16
+	Jt   uint8
+	Jf   uint8
+	K    uint32
+}
+
+type BpfHdr struct {
+	Tstamp       Timeval
+	Caplen       uint32
+	Datalen      uint32
+	Hdrlen       uint16
+	Pad_godefs_0 [2]byte
+}
diff --git a/src/pkg/syscall/ztypes_darwin_amd64.go b/src/pkg/syscall/ztypes_darwin_amd64.go
index 936a4e8..d61c8b8 100644
--- a/src/pkg/syscall/ztypes_darwin_amd64.go
+++ b/src/pkg/syscall/ztypes_darwin_amd64.go
@@ -29,6 +29,11 @@ const (
 	SizeofIfaMsghdr        = 0x14
 	SizeofRtMsghdr         = 0x5c
 	SizeofRtMetrics        = 0x38
+	SizeofBpfVersion       = 0x4
+	SizeofBpfStat          = 0x8
+	SizeofBpfProgram       = 0x10
+	SizeofBpfInsn          = 0x8
+	SizeofBpfHdr           = 0x14
 )
 
 // Types
@@ -52,6 +57,11 @@ type Timeval struct {
 	Pad_godefs_0 [4]byte
 }
 
+type Timeval32 struct {
+	Sec  int32
+	Usec int32
+}
+
 type Rusage struct {
 	Utime    Timeval
 	Stime    Timeval
@@ -229,7 +239,7 @@ type Msghdr struct {
 	Name         *byte
 	Namelen      uint32
 	Pad_godefs_0 [4]byte
-	Iov          uint64
+	Iov          *Iovec
 	Iovlen       int32
 	Pad_godefs_1 [4]byte
 	Control      *byte
@@ -292,7 +302,7 @@ type IfData struct {
 	Noproto    uint32
 	Recvtiming uint32
 	Xmittiming uint32
-	Lastchange [8]byte /* timeval32 */
+	Lastchange Timeval32
 	Unused2    uint32
 	Hwassist   uint32
 	Reserved1  uint32
@@ -339,3 +349,34 @@ type RtMetrics struct {
 	Pksent   uint32
 	Filler   [4]uint32
 }
+
+type BpfVersion struct {
+	Major uint16
+	Minor uint16
+}
+
+type BpfStat struct {
+	Recv uint32
+	Drop uint32
+}
+
+type BpfProgram struct {
+	Len          uint32
+	Pad_godefs_0 [4]byte
+	Insns        *BpfInsn
+}
+
+type BpfInsn struct {
+	Code uint16
+	Jt   uint8
+	Jf   uint8
+	K    uint32
+}
+
+type BpfHdr struct {
+	Tstamp       Timeval32
+	Caplen       uint32
+	Datalen      uint32
+	Hdrlen       uint16
+	Pad_godefs_0 [2]byte
+}
diff --git a/src/pkg/syscall/ztypes_windows_386.go b/src/pkg/syscall/ztypes_windows_386.go
index 56d4198..3a50be1 100644
--- a/src/pkg/syscall/ztypes_windows_386.go
+++ b/src/pkg/syscall/ztypes_windows_386.go
@@ -77,6 +77,7 @@ const (
 
 	HANDLE_FLAG_INHERIT    = 0x00000001
 	STARTF_USESTDHANDLES   = 0x00000100
+	STARTF_USESHOWWINDOW   = 0x00000001
 	DUPLICATE_CLOSE_SOURCE = 0x00000001
 	DUPLICATE_SAME_ACCESS  = 0x00000002
 
@@ -240,6 +241,25 @@ type ByHandleFileInformation struct {
 	FileIndexLow       uint32
 }
 
+// ShowWindow constants
+const (
+	// winuser.h
+	SW_HIDE            = 0
+	SW_NORMAL          = 1
+	SW_SHOWNORMAL      = 1
+	SW_SHOWMINIMIZED   = 2
+	SW_SHOWMAXIMIZED   = 3
+	SW_MAXIMIZE        = 3
+	SW_SHOWNOACTIVATE  = 4
+	SW_SHOW            = 5
+	SW_MINIMIZE        = 6
+	SW_SHOWMINNOACTIVE = 7
+	SW_SHOWNA          = 8
+	SW_RESTORE         = 9
+	SW_SHOWDEFAULT     = 10
+	SW_FORCEMINIMIZE   = 11
+)
+
 type StartupInfo struct {
 	Cb            uint32
 	_             *uint16
diff --git a/src/pkg/syslog/syslog.go b/src/pkg/syslog/syslog.go
index 4ada113..6933372 100644
--- a/src/pkg/syslog/syslog.go
+++ b/src/pkg/syslog/syslog.go
@@ -2,9 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The syslog package provides a simple interface to
-// the system log service. It can send messages to the
-// syslog daemon using UNIX domain sockets, UDP, or
+// Package syslog provides a simple interface to the system log service. It
+// can send messages to the syslog daemon using UNIX domain sockets, UDP, or
 // TCP connections.
 package syslog
 
diff --git a/src/pkg/syslog/syslog_test.go b/src/pkg/syslog/syslog_test.go
index 2958bcb..4816ddf 100644
--- a/src/pkg/syslog/syslog_test.go
+++ b/src/pkg/syslog/syslog_test.go
@@ -52,6 +52,10 @@ func TestNewLogger(t *testing.T) {
 }
 
 func TestDial(t *testing.T) {
+	if testing.Short() {
+		// Depends on syslog daemon running, and sometimes it's not.
+		t.Logf("skipping syslog test during -short")
+	}
 	l, err := Dial("", "", LOG_ERR, "syslog_test")
 	if err != nil {
 		t.Fatalf("Dial() failed: %s", err)
diff --git a/src/pkg/tabwriter/tabwriter.go b/src/pkg/tabwriter/tabwriter.go
index 848703e..d91a07d 100644
--- a/src/pkg/tabwriter/tabwriter.go
+++ b/src/pkg/tabwriter/tabwriter.go
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The tabwriter package implements a write filter (tabwriter.Writer)
-// that translates tabbed columns in input into properly aligned text.
+// Package tabwriter implements a write filter (tabwriter.Writer) that
+// translates tabbed columns in input into properly aligned text.
 //
 // The package is using the Elastic Tabstops algorithm described at
 // http://nickgravgaard.com/elastictabstops/index.html.
diff --git a/src/pkg/template/template.go b/src/pkg/template/template.go
index 28872db..2532078 100644
--- a/src/pkg/template/template.go
+++ b/src/pkg/template/template.go
@@ -3,8 +3,8 @@
 // license that can be found in the LICENSE file.
 
 /*
-	Data-driven templates for generating textual output such as
-	HTML.
+	Package template implements data-driven templates for generating textual
+	output such as HTML.
 
 	Templates are executed by applying them to a data structure.
 	Annotations in the template refer to elements of the data
@@ -646,7 +646,7 @@ func (t *Template) lookup(st *state, v reflect.Value, name string) reflect.Value
 			}
 			return av.FieldByName(name)
 		case reflect.Map:
-			if v := av.MapIndex(reflect.NewValue(name)); v.IsValid() {
+			if v := av.MapIndex(reflect.ValueOf(name)); v.IsValid() {
 				return v
 			}
 			return reflect.Zero(typ.Elem())
@@ -797,7 +797,7 @@ func (t *Template) executeElement(i int, st *state) int {
 		return elem.end
 	}
 	e := t.elems.At(i)
-	t.execError(st, 0, "internal error: bad directive in execute: %v %T\n", reflect.NewValue(e).Interface(), e)
+	t.execError(st, 0, "internal error: bad directive in execute: %v %T\n", reflect.ValueOf(e).Interface(), e)
 	return 0
 }
 
@@ -980,7 +980,7 @@ func (t *Template) ParseFile(filename string) (err os.Error) {
 // generating output to wr.
 func (t *Template) Execute(wr io.Writer, data interface{}) (err os.Error) {
 	// Extract the driver data.
-	val := reflect.NewValue(data)
+	val := reflect.ValueOf(data)
 	defer checkError(&err)
 	t.p = 0
 	t.execute(0, t.elems.Len(), &state{parent: nil, data: val, wr: wr})
diff --git a/src/pkg/testing/iotest/reader.go b/src/pkg/testing/iotest/reader.go
index 647520a..e4003d7 100644
--- a/src/pkg/testing/iotest/reader.go
+++ b/src/pkg/testing/iotest/reader.go
@@ -2,8 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The iotest package implements Readers and Writers
-// useful only for testing.
+// Package iotest implements Readers and Writers useful only for testing.
 package iotest
 
 import (
diff --git a/src/pkg/testing/quick/quick.go b/src/pkg/testing/quick/quick.go
index 52fd38d..756a60e 100644
--- a/src/pkg/testing/quick/quick.go
+++ b/src/pkg/testing/quick/quick.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package implements utility functions to help with black box testing.
+// Package quick implements utility functions to help with black box testing.
 package quick
 
 import (
@@ -59,37 +59,37 @@ func Value(t reflect.Type, rand *rand.Rand) (value reflect.Value, ok bool) {
 
 	switch concrete := t; concrete.Kind() {
 	case reflect.Bool:
-		return reflect.NewValue(rand.Int()&1 == 0), true
+		return reflect.ValueOf(rand.Int()&1 == 0), true
 	case reflect.Float32:
-		return reflect.NewValue(randFloat32(rand)), true
+		return reflect.ValueOf(randFloat32(rand)), true
 	case reflect.Float64:
-		return reflect.NewValue(randFloat64(rand)), true
+		return reflect.ValueOf(randFloat64(rand)), true
 	case reflect.Complex64:
-		return reflect.NewValue(complex(randFloat32(rand), randFloat32(rand))), true
+		return reflect.ValueOf(complex(randFloat32(rand), randFloat32(rand))), true
 	case reflect.Complex128:
-		return reflect.NewValue(complex(randFloat64(rand), randFloat64(rand))), true
+		return reflect.ValueOf(complex(randFloat64(rand), randFloat64(rand))), true
 	case reflect.Int16:
-		return reflect.NewValue(int16(randInt64(rand))), true
+		return reflect.ValueOf(int16(randInt64(rand))), true
 	case reflect.Int32:
-		return reflect.NewValue(int32(randInt64(rand))), true
+		return reflect.ValueOf(int32(randInt64(rand))), true
 	case reflect.Int64:
-		return reflect.NewValue(randInt64(rand)), true
+		return reflect.ValueOf(randInt64(rand)), true
 	case reflect.Int8:
-		return reflect.NewValue(int8(randInt64(rand))), true
+		return reflect.ValueOf(int8(randInt64(rand))), true
 	case reflect.Int:
-		return reflect.NewValue(int(randInt64(rand))), true
+		return reflect.ValueOf(int(randInt64(rand))), true
 	case reflect.Uint16:
-		return reflect.NewValue(uint16(randInt64(rand))), true
+		return reflect.ValueOf(uint16(randInt64(rand))), true
 	case reflect.Uint32:
-		return reflect.NewValue(uint32(randInt64(rand))), true
+		return reflect.ValueOf(uint32(randInt64(rand))), true
 	case reflect.Uint64:
-		return reflect.NewValue(uint64(randInt64(rand))), true
+		return reflect.ValueOf(uint64(randInt64(rand))), true
 	case reflect.Uint8:
-		return reflect.NewValue(uint8(randInt64(rand))), true
+		return reflect.ValueOf(uint8(randInt64(rand))), true
 	case reflect.Uint:
-		return reflect.NewValue(uint(randInt64(rand))), true
+		return reflect.ValueOf(uint(randInt64(rand))), true
 	case reflect.Uintptr:
-		return reflect.NewValue(uintptr(randInt64(rand))), true
+		return reflect.ValueOf(uintptr(randInt64(rand))), true
 	case reflect.Map:
 		numElems := rand.Intn(complexSize)
 		m := reflect.MakeMap(concrete)
@@ -107,8 +107,8 @@ func Value(t reflect.Type, rand *rand.Rand) (value reflect.Value, ok bool) {
 		if !ok {
 			return reflect.Value{}, false
 		}
-		p := reflect.Zero(concrete)
-		p.Set(v.Addr())
+		p := reflect.New(concrete.Elem())
+		p.Elem().Set(v)
 		return p, true
 	case reflect.Slice:
 		numElems := rand.Intn(complexSize)
@@ -127,9 +127,9 @@ func Value(t reflect.Type, rand *rand.Rand) (value reflect.Value, ok bool) {
 		for i := 0; i < numChars; i++ {
 			codePoints[i] = rand.Intn(0x10ffff)
 		}
-		return reflect.NewValue(string(codePoints)), true
+		return reflect.ValueOf(string(codePoints)), true
 	case reflect.Struct:
-		s := reflect.Zero(t)
+		s := reflect.New(t).Elem()
 		for i := 0; i < s.NumField(); i++ {
 			v, ok := Value(concrete.Field(i).Type, rand)
 			if !ok {
@@ -336,7 +336,7 @@ func arbitraryValues(args []reflect.Value, f reflect.Type, config *Config, rand
 }
 
 func functionAndType(f interface{}) (v reflect.Value, t reflect.Type, ok bool) {
-	v = reflect.NewValue(f)
+	v = reflect.ValueOf(f)
 	ok = v.Kind() == reflect.Func
 	if !ok {
 		return
diff --git a/src/pkg/testing/quick/quick_test.go b/src/pkg/testing/quick/quick_test.go
index b126e4a..f2618c3 100644
--- a/src/pkg/testing/quick/quick_test.go
+++ b/src/pkg/testing/quick/quick_test.go
@@ -102,7 +102,7 @@ type myStruct struct {
 }
 
 func (m myStruct) Generate(r *rand.Rand, _ int) reflect.Value {
-	return reflect.NewValue(myStruct{x: 42})
+	return reflect.ValueOf(myStruct{x: 42})
 }
 
 func myStructProperty(in myStruct) bool { return in.x == 42 }
diff --git a/src/pkg/testing/script/script.go b/src/pkg/testing/script/script.go
index b180184..afb286f 100644
--- a/src/pkg/testing/script/script.go
+++ b/src/pkg/testing/script/script.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package aids in the testing of code that uses channels.
+// Package script aids in the testing of code that uses channels.
 package script
 
 import (
@@ -134,19 +134,19 @@ type empty struct {
 }
 
 func newEmptyInterface(e empty) reflect.Value {
-	return reflect.NewValue(e).Field(0)
+	return reflect.ValueOf(e).Field(0)
 }
 
 func (s Send) send() {
 	// With reflect.ChanValue.Send, we must match the types exactly. So, if
 	// s.Channel is a chan interface{} we convert s.Value to an interface{}
 	// first.
-	c := reflect.NewValue(s.Channel)
+	c := reflect.ValueOf(s.Channel)
 	var v reflect.Value
 	if iface := c.Type().Elem(); iface.Kind() == reflect.Interface && iface.NumMethod() == 0 {
 		v = newEmptyInterface(empty{s.Value})
 	} else {
-		v = reflect.NewValue(s.Value)
+		v = reflect.ValueOf(s.Value)
 	}
 	c.Send(v)
 }
@@ -162,7 +162,7 @@ func (s Close) getSend() sendAction { return s }
 
 func (s Close) getChannel() interface{} { return s.Channel }
 
-func (s Close) send() { reflect.NewValue(s.Channel).Close() }
+func (s Close) send() { reflect.ValueOf(s.Channel).Close() }
 
 // A ReceivedUnexpected error results if no active Events match a value
 // received from a channel.
@@ -278,7 +278,7 @@ func getChannels(events []*Event) ([]interface{}, os.Error) {
 			continue
 		}
 		c := event.action.getChannel()
-		if reflect.NewValue(c).Kind() != reflect.Chan {
+		if reflect.ValueOf(c).Kind() != reflect.Chan {
 			return nil, SetupError("one of the channel values is not a channel")
 		}
 
@@ -303,7 +303,7 @@ func getChannels(events []*Event) ([]interface{}, os.Error) {
 // channel repeatedly, wrapping them up as either a channelRecv or
 // channelClosed structure, and forwards them to the multiplex channel.
 func recvValues(multiplex chan<- interface{}, channel interface{}) {
-	c := reflect.NewValue(channel)
+	c := reflect.ValueOf(channel)
 
 	for {
 		v, ok := c.Recv()
diff --git a/src/pkg/testing/testing.go b/src/pkg/testing/testing.go
index 1e65528..8781b20 100644
--- a/src/pkg/testing/testing.go
+++ b/src/pkg/testing/testing.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The testing package provides support for automated testing of Go packages.
+// Package testing provides support for automated testing of Go packages.
 // It is intended to be used in concert with the ``gotest'' utility, which automates
 // execution of any function of the form
 //     func TestXxx(*testing.T)
diff --git a/src/pkg/time/time.go b/src/pkg/time/time.go
index 40338f7..a048078 100644
--- a/src/pkg/time/time.go
+++ b/src/pkg/time/time.go
@@ -2,8 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The time package provides functionality for measuring and
-// displaying time.
+// Package time provides functionality for measuring and displaying time.
 package time
 
 // Days of the week.
diff --git a/src/pkg/time/zoneinfo_unix.go b/src/pkg/time/zoneinfo_unix.go
index 6685da7..42659ed 100644
--- a/src/pkg/time/zoneinfo_unix.go
+++ b/src/pkg/time/zoneinfo_unix.go
@@ -17,8 +17,6 @@ import (
 
 const (
 	headerSize = 4 + 16 + 4*7
-	zoneDir    = "/usr/share/zoneinfo/"
-	zoneDir2   = "/usr/share/lib/zoneinfo/"
 )
 
 // Simple I/O interface to binary blob of data.
@@ -211,16 +209,22 @@ func setupZone() {
 	// no $TZ means use the system default /etc/localtime.
 	// $TZ="" means use UTC.
 	// $TZ="foo" means use /usr/share/zoneinfo/foo.
+	// Many systems use /usr/share/zoneinfo, Solaris 2 has
+	// /usr/share/lib/zoneinfo, IRIX 6 has /usr/lib/locale/TZ.
+	zoneDirs := []string{"/usr/share/zoneinfo/",
+		"/usr/share/lib/zoneinfo/",
+		"/usr/lib/locale/TZ/"}
 
 	tz, err := os.Getenverror("TZ")
 	switch {
 	case err == os.ENOENV:
 		zones, _ = readinfofile("/etc/localtime")
 	case len(tz) > 0:
-		var ok bool
-		zones, ok = readinfofile(zoneDir + tz)
-		if !ok {
-			zones, _ = readinfofile(zoneDir2 + tz)
+		for _, zoneDir := range zoneDirs {
+			var ok bool
+			if zones, ok = readinfofile(zoneDir + tz); ok {
+				break
+			}
 		}
 	case len(tz) == 0:
 		// do nothing: use UTC
diff --git a/src/pkg/try/try.go b/src/pkg/try/try.go
index 1171c80..2a3dbf9 100644
--- a/src/pkg/try/try.go
+++ b/src/pkg/try/try.go
@@ -67,7 +67,7 @@ func printSlice(firstArg string, args []interface{}) {
 func tryMethods(pkg, firstArg string, args []interface{}) {
 	defer func() { recover() }()
 	// Is the first argument something with methods?
-	v := reflect.NewValue(args[0])
+	v := reflect.ValueOf(args[0])
 	typ := v.Type()
 	if typ.NumMethod() == 0 {
 		return
@@ -90,7 +90,7 @@ func tryMethod(pkg, firstArg string, method reflect.Method, args []interface{})
 // tryFunction sees if fn satisfies the arguments.
 func tryFunction(pkg, name string, fn interface{}, args []interface{}) {
 	defer func() { recover() }()
-	rfn := reflect.NewValue(fn)
+	rfn := reflect.ValueOf(fn)
 	typ := rfn.Type()
 	tryOneFunction(pkg, "", name, typ, rfn, args)
 }
@@ -120,7 +120,7 @@ func tryOneFunction(pkg, firstArg, name string, typ reflect.Type, rfn reflect.Va
 	// Build the call args.
 	argsVal := make([]reflect.Value, typ.NumIn()+typ.NumOut())
 	for i, a := range args {
-		argsVal[i] = reflect.NewValue(a)
+		argsVal[i] = reflect.ValueOf(a)
 	}
 	// Call the function and see if the results are as expected.
 	resultVal := rfn.Call(argsVal[:typ.NumIn()])
@@ -161,7 +161,7 @@ func tryOneFunction(pkg, firstArg, name string, typ reflect.Type, rfn reflect.Va
 
 // compatible reports whether the argument is compatible with the type.
 func compatible(arg interface{}, typ reflect.Type) bool {
-	if reflect.Typeof(arg) == typ {
+	if reflect.TypeOf(arg) == typ {
 		return true
 	}
 	if arg == nil {
diff --git a/src/pkg/unicode/letter.go b/src/pkg/unicode/letter.go
index 9380624..382c6eb 100644
--- a/src/pkg/unicode/letter.go
+++ b/src/pkg/unicode/letter.go
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package provides data and functions to test some properties of Unicode code points.
+// Package unicode provides data and functions to test some properties of
+// Unicode code points.
 package unicode
 
 const (
diff --git a/src/pkg/unsafe/unsafe.go b/src/pkg/unsafe/unsafe.go
index 3cd4cff..8507bed 100644
--- a/src/pkg/unsafe/unsafe.go
+++ b/src/pkg/unsafe/unsafe.go
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 /*
-	The unsafe package contains operations that step around the type safety of Go programs.
+	Package unsafe contains operations that step around the type safety of Go programs.
 */
 package unsafe
 
diff --git a/src/pkg/utf8/utf8.go b/src/pkg/utf8/utf8.go
index 455499e..f542358 100644
--- a/src/pkg/utf8/utf8.go
+++ b/src/pkg/utf8/utf8.go
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Functions and constants to support text encoded in UTF-8.
-// This package calls a Unicode character a rune for brevity.
+// Package utf8 implements functions and constants to support text encoded in
+// UTF-8. This package calls a Unicode character a rune for brevity.
 package utf8
 
 import "unicode" // only needed for a couple of constants
diff --git a/src/pkg/websocket/server.go b/src/pkg/websocket/server.go
index 1119b2d..3762652 100644
--- a/src/pkg/websocket/server.go
+++ b/src/pkg/websocket/server.go
@@ -150,6 +150,7 @@ func (f Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
 		return
 	}
 	ws := newConn(origin, location, protocol, buf, rwc)
+	ws.Request = req
 	f(ws)
 }
 
diff --git a/src/pkg/websocket/websocket.go b/src/pkg/websocket/websocket.go
index d5996ab..edde61b 100644
--- a/src/pkg/websocket/websocket.go
+++ b/src/pkg/websocket/websocket.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The websocket package implements a client and server for the Web Socket protocol.
+// Package websocket implements a client and server for the Web Socket protocol.
 // The protocol is defined at http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol
 package websocket
 
@@ -13,6 +13,7 @@ import (
 	"bufio"
 	"crypto/md5"
 	"encoding/binary"
+	"http"
 	"io"
 	"net"
 	"os"
@@ -43,6 +44,8 @@ type Conn struct {
 	Location string
 	// The subprotocol for the Web Socket.
 	Protocol string
+	// The initial http Request (for the Server side only).
+	Request *http.Request
 
 	buf *bufio.ReadWriter
 	rwc io.ReadWriteCloser
diff --git a/src/pkg/websocket/websocket_test.go b/src/pkg/websocket/websocket_test.go
index 8b3cf89..10f88df 100644
--- a/src/pkg/websocket/websocket_test.go
+++ b/src/pkg/websocket/websocket_test.go
@@ -186,11 +186,12 @@ func TestTrailingSpaces(t *testing.T) {
 	once.Do(startServer)
 	for i := 0; i < 30; i++ {
 		// body
-		_, err := Dial(fmt.Sprintf("ws://%s/echo", serverAddr), "",
-			"http://localhost/")
+		ws, err := Dial(fmt.Sprintf("ws://%s/echo", serverAddr), "", "http://localhost/")
 		if err != nil {
-			panic("Dial failed: " + err.String())
+			t.Error("Dial failed:", err.String())
+			break
 		}
+		ws.Close()
 	}
 }
 
diff --git a/src/pkg/xml/read.go b/src/pkg/xml/read.go
index a3ddb9d..554b2a6 100644
--- a/src/pkg/xml/read.go
+++ b/src/pkg/xml/read.go
@@ -139,7 +139,7 @@ import (
 // to a freshly allocated value and then mapping the element to that value.
 //
 func Unmarshal(r io.Reader, val interface{}) os.Error {
-	v := reflect.NewValue(val)
+	v := reflect.ValueOf(val)
 	if v.Kind() != reflect.Ptr {
 		return os.NewError("non-pointer passed to Unmarshal")
 	}
@@ -176,7 +176,7 @@ func (e *TagPathError) String() string {
 // Passing a nil start element indicates that Unmarshal should
 // read the token stream to find the start element.
 func (p *Parser) Unmarshal(val interface{}, start *StartElement) os.Error {
-	v := reflect.NewValue(val)
+	v := reflect.ValueOf(val)
 	if v.Kind() != reflect.Ptr {
 		return os.NewError("non-pointer passed to Unmarshal")
 	}
@@ -280,7 +280,7 @@ func (p *Parser) unmarshal(val reflect.Value, start *StartElement) os.Error {
 
 	case reflect.Struct:
 		if _, ok := v.Interface().(Name); ok {
-			v.Set(reflect.NewValue(start.Name))
+			v.Set(reflect.ValueOf(start.Name))
 			break
 		}
 
@@ -316,7 +316,7 @@ func (p *Parser) unmarshal(val reflect.Value, start *StartElement) os.Error {
 			if _, ok := v.Interface().(Name); !ok {
 				return UnmarshalError(sv.Type().String() + " field XMLName does not have type xml.Name")
 			}
-			v.Set(reflect.NewValue(start.Name))
+			v.Set(reflect.ValueOf(start.Name))
 		}
 
 		// Assign attributes.
@@ -508,21 +508,21 @@ Loop:
 	case reflect.String:
 		t.SetString(string(data))
 	case reflect.Slice:
-		t.Set(reflect.NewValue(data))
+		t.Set(reflect.ValueOf(data))
 	}
 
 	switch t := saveComment; t.Kind() {
 	case reflect.String:
 		t.SetString(string(comment))
 	case reflect.Slice:
-		t.Set(reflect.NewValue(comment))
+		t.Set(reflect.ValueOf(comment))
 	}
 
 	switch t := saveXML; t.Kind() {
 	case reflect.String:
 		t.SetString(string(saveXMLData))
 	case reflect.Slice:
-		t.Set(reflect.NewValue(saveXMLData))
+		t.Set(reflect.ValueOf(saveXMLData))
 	}
 
 	return nil
diff --git a/src/pkg/xml/read_test.go b/src/pkg/xml/read_test.go
index 0e28e73..d4ae370 100644
--- a/src/pkg/xml/read_test.go
+++ b/src/pkg/xml/read_test.go
@@ -288,9 +288,7 @@ var pathTests = []interface{}{
 
 func TestUnmarshalPaths(t *testing.T) {
 	for _, pt := range pathTests {
-		p := reflect.Zero(reflect.NewValue(pt).Type())
-		p.Set(reflect.Zero(p.Type().Elem()).Addr())
-		v := p.Interface()
+		v := reflect.New(reflect.TypeOf(pt).Elem()).Interface()
 		if err := Unmarshal(StringReader(pathTestString), v); err != nil {
 			t.Fatalf("Unmarshal: %s", err)
 		}
@@ -315,8 +313,8 @@ type BadPathTestB struct {
 var badPathTests = []struct {
 	v, e interface{}
 }{
-	{&BadPathTestA{}, &TagPathError{reflect.Typeof(BadPathTestA{}), "First", "items>item1", "Second", "items>"}},
-	{&BadPathTestB{}, &TagPathError{reflect.Typeof(BadPathTestB{}), "First", "items>item1", "Second", "items>item1>value"}},
+	{&BadPathTestA{}, &TagPathError{reflect.TypeOf(BadPathTestA{}), "First", "items>item1", "Second", "items>"}},
+	{&BadPathTestB{}, &TagPathError{reflect.TypeOf(BadPathTestB{}), "First", "items>item1", "Second", "items>item1>value"}},
 }
 
 func TestUnmarshalBadPaths(t *testing.T) {
diff --git a/src/pkg/xml/xml.go b/src/pkg/xml/xml.go
index f92abe8..42d8b98 100644
--- a/src/pkg/xml/xml.go
+++ b/src/pkg/xml/xml.go
@@ -163,6 +163,13 @@ type Parser struct {
 	//	"quot": `"`,
 	Entity map[string]string
 
+	// CharsetReader, if non-nil, defines a function to generate
+	// charset-conversion readers, converting from the provided
+	// non-UTF-8 charset into UTF-8. If CharsetReader is nil or
+	// returns an error, parsing stops with an error. One of the
+	// the CharsetReader's result values must be non-nil.
+	CharsetReader func(charset string, input io.Reader) (io.Reader, os.Error)
+
 	r         io.ByteReader
 	buf       bytes.Buffer
 	saved     *bytes.Buffer
@@ -186,17 +193,7 @@ func NewParser(r io.Reader) *Parser {
 		line:     1,
 		Strict:   true,
 	}
-
-	// Get efficient byte at a time reader.
-	// Assume that if reader has its own
-	// ReadByte, it's efficient enough.
-	// Otherwise, use bufio.
-	if rb, ok := r.(io.ByteReader); ok {
-		p.r = rb
-	} else {
-		p.r = bufio.NewReader(r)
-	}
-
+	p.switchToReader(r)
 	return p
 }
 
@@ -290,6 +287,18 @@ func (p *Parser) translate(n *Name, isElementName bool) {
 	}
 }
 
+func (p *Parser) switchToReader(r io.Reader) {
+	// Get efficient byte at a time reader.
+	// Assume that if reader has its own
+	// ReadByte, it's efficient enough.
+	// Otherwise, use bufio.
+	if rb, ok := r.(io.ByteReader); ok {
+		p.r = rb
+	} else {
+		p.r = bufio.NewReader(r)
+	}
+}
+
 // Parsing state - stack holds old name space translations
 // and the current set of open elements.  The translations to pop when
 // ending a given tag are *below* it on the stack, which is
@@ -487,6 +496,25 @@ func (p *Parser) RawToken() (Token, os.Error) {
 		}
 		data := p.buf.Bytes()
 		data = data[0 : len(data)-2] // chop ?>
+
+		if target == "xml" {
+			enc := procInstEncoding(string(data))
+			if enc != "" && enc != "utf-8" && enc != "UTF-8" {
+				if p.CharsetReader == nil {
+					p.err = fmt.Errorf("xml: encoding %q declared but Parser.CharsetReader is nil", enc)
+					return nil, p.err
+				}
+				newr, err := p.CharsetReader(enc, p.r.(io.Reader))
+				if err != nil {
+					p.err = fmt.Errorf("xml: opening charset %q: %v", enc, err)
+					return nil, p.err
+				}
+				if newr == nil {
+					panic("CharsetReader returned a nil Reader for charset " + enc)
+				}
+				p.switchToReader(newr)
+			}
+		}
 		return ProcInst{target, data}, nil
 
 	case '!':
@@ -1633,3 +1661,26 @@ func Escape(w io.Writer, s []byte) {
 	}
 	w.Write(s[last:])
 }
+
+// procInstEncoding parses the `encoding="..."` or `encoding='...'`
+// value out of the provided string, returning "" if not found.
+func procInstEncoding(s string) string {
+	// TODO: this parsing is somewhat lame and not exact.
+	// It works for all actual cases, though.
+	idx := strings.Index(s, "encoding=")
+	if idx == -1 {
+		return ""
+	}
+	v := s[idx+len("encoding="):]
+	if v == "" {
+		return ""
+	}
+	if v[0] != '\'' && v[0] != '"' {
+		return ""
+	}
+	idx = strings.IndexRune(v[1:], int(v[0]))
+	if idx == -1 {
+		return ""
+	}
+	return v[1 : idx+1]
+}
diff --git a/src/pkg/xml/xml_test.go b/src/pkg/xml/xml_test.go
index 887bc3d..a99c191 100644
--- a/src/pkg/xml/xml_test.go
+++ b/src/pkg/xml/xml_test.go
@@ -9,6 +9,7 @@ import (
 	"io"
 	"os"
 	"reflect"
+	"strings"
 	"testing"
 )
 
@@ -96,6 +97,19 @@ var cookedTokens = []Token{
 	Comment([]byte(" missing final newline ")),
 }
 
+const testInputAltEncoding = `
+<?xml version="1.0" encoding="x-testing-uppercase"?>
+<TAG>VALUE</TAG>`
+
+var rawTokensAltEncoding = []Token{
+	CharData([]byte("\n")),
+	ProcInst{"xml", []byte(`version="1.0" encoding="x-testing-uppercase"`)},
+	CharData([]byte("\n")),
+	StartElement{Name{"", "tag"}, nil},
+	CharData([]byte("value")),
+	EndElement{Name{"", "tag"}},
+}
+
 var xmlInput = []string{
 	// unexpected EOF cases
 	"<",
@@ -173,7 +187,64 @@ func StringReader(s string) io.Reader { return &stringReader{s, 0} }
 
 func TestRawToken(t *testing.T) {
 	p := NewParser(StringReader(testInput))
+	testRawToken(t, p, rawTokens)
+}
+
+type downCaser struct {
+	t *testing.T
+	r io.ByteReader
+}
+
+func (d *downCaser) ReadByte() (c byte, err os.Error) {
+	c, err = d.r.ReadByte()
+	if c >= 'A' && c <= 'Z' {
+		c += 'a' - 'A'
+	}
+	return
+}
+
+func (d *downCaser) Read(p []byte) (int, os.Error) {
+	d.t.Fatalf("unexpected Read call on downCaser reader")
+	return 0, os.EINVAL
+}
+
+func TestRawTokenAltEncoding(t *testing.T) {
+	sawEncoding := ""
+	p := NewParser(StringReader(testInputAltEncoding))
+	p.CharsetReader = func(charset string, input io.Reader) (io.Reader, os.Error) {
+		sawEncoding = charset
+		if charset != "x-testing-uppercase" {
+			t.Fatalf("unexpected charset %q", charset)
+		}
+		return &downCaser{t, input.(io.ByteReader)}, nil
+	}
+	testRawToken(t, p, rawTokensAltEncoding)
+}
 
+func TestRawTokenAltEncodingNoConverter(t *testing.T) {
+	p := NewParser(StringReader(testInputAltEncoding))
+	token, err := p.RawToken()
+	if token == nil {
+		t.Fatalf("expected a token on first RawToken call")
+	}
+	if err != nil {
+		t.Fatal(err)
+	}
+	token, err = p.RawToken()
+	if token != nil {
+		t.Errorf("expected a nil token; got %#v", token)
+	}
+	if err == nil {
+		t.Fatalf("expected an error on second RawToken call")
+	}
+	const encoding = "x-testing-uppercase"
+	if !strings.Contains(err.String(), encoding) {
+		t.Errorf("expected error to contain %q; got error: %v",
+			encoding, err)
+	}
+}
+
+func testRawToken(t *testing.T, p *Parser, rawTokens []Token) {
 	for i, want := range rawTokens {
 		have, err := p.RawToken()
 		if err != nil {
@@ -483,3 +554,26 @@ func TestDisallowedCharacters(t *testing.T) {
 		}
 	}
 }
+
+type procInstEncodingTest struct {
+	expect, got string
+}
+
+var procInstTests = []struct {
+	input, expect string
+}{
+	{`version="1.0" encoding="utf-8"`, "utf-8"},
+	{`version="1.0" encoding='utf-8'`, "utf-8"},
+	{`version="1.0" encoding='utf-8' `, "utf-8"},
+	{`version="1.0" encoding=utf-8`, ""},
+	{`encoding="FOO" `, "FOO"},
+}
+
+func TestProcInstEncoding(t *testing.T) {
+	for _, test := range procInstTests {
+		got := procInstEncoding(test.input)
+		if got != test.expect {
+			t.Errorf("procInstEncoding(%q) = %q; want %q", test.input, got, test.expect)
+		}
+	}
+}
diff --git a/src/run.bash b/src/run.bash
index ea98403..bb3d06c 100755
--- a/src/run.bash
+++ b/src/run.bash
@@ -33,8 +33,7 @@ xcd() {
 if $rebuild; then
 	(xcd pkg
 		gomake clean
-		time gomake
-		gomake install
+		time gomake install
 	) || exit $i
 fi
 
@@ -43,18 +42,10 @@ gomake testshort
 ) || exit $?
 
 (xcd pkg/sync;
-if $rebuild; then
-	gomake clean;
-	time gomake
-fi
 GOMAXPROCS=10 gomake testshort
 ) || exit $?
 
 (xcd cmd/ebnflint
-if $rebuild; then
-	gomake clean;
-	time gomake
-fi
 time gomake test
 ) || exit $?
 
@@ -83,7 +74,6 @@ gomake clean
 time gomake ogle
 ) || exit $?
 
-[ "$GOHOSTOS" == windows ] ||
 (xcd ../doc/progs
 time ./run
 ) || exit $?
diff --git a/test/bench/timing.log b/test/bench/timing.log
index a967f27..c658fa0 100644
--- a/test/bench/timing.log
+++ b/test/bench/timing.log
@@ -674,3 +674,173 @@ threadring 50000000
 	gcc -O2 threadring.c	30.50u 258.05s 325.72r
 	gccgo -O2 threadring.go	92.87u 748.39s 728.46r
 	gc threadring	38.03u 0.01s 38.04r
+
+# Apr 15, 2011
+# Move to new machine, Intel Xeon E5520 at 2.27GHz.
+# (Was Opteron(tm) Processor 8214 HE)
+
+fasta -n 25000000
+OLD:
+	gcc -O2 fasta.c	3.39u 0.04s 3.42r
+	gccgo -O2 fasta.go	3.52u 0.00s 3.52r
+	gc fasta	3.63u 0.04s 3.67r
+	gc_B fasta	3.66u 0.00s 3.66r
+NEW:
+	gcc -O2 fasta.c	1.45u 0.02s 1.47r
+	gccgo -O2 fasta.go	1.51u 0.01s 1.51r
+	gc fasta	2.04u 0.00s 2.04r
+	gc_B fasta	2.05u 0.00s 2.04r
+
+reverse-complement < output-of-fasta-25000000
+OLD:
+	gcc -O2 reverse-complement.c	1.87u 1.51s 7.02r
+	gccgo -O2 reverse-complement.go	1.56u 0.54s 3.37r
+	gc reverse-complement	1.73u 0.36s 2.08r
+	gc_B reverse-complement	1.75u 0.37s 2.12r
+NEW:
+	gcc -O2 reverse-complement.c	1.20u 0.47s 12.96r
+	gccgo -O2 reverse-complement.go	0.88u 0.14s 1.01r
+	gc reverse-complement	1.13u 0.17s 1.30r
+	gc_B reverse-complement	1.11u 0.09s 1.20r
+
+nbody -n 50000000
+OLD:
+	gcc -O2 -lm nbody.c	21.90u 0.00s 21.92r
+	gccgo -O2 nbody.go	23.12u 0.03s 23.19r
+	gc nbody	29.07u 0.00s 29.07r
+	gc_B nbody	31.84u 0.00s 31.85r
+NEW:
+	gcc -O2 -lm nbody.c	13.01u 0.00s 13.03r
+	gccgo -O2 nbody.go	13.35u 0.00s 13.37r
+	gc nbody	21.78u 0.00s 21.82r
+	gc_B nbody	21.72u 0.00s 21.76r
+
+binary-tree 15 # too slow to use 20
+OLD:
+	gcc -O2 binary-tree.c -lm	0.83u 0.02s 0.84r
+	gccgo -O2 binary-tree.go	2.61u 0.02s 2.62r
+	gccgo -O2 binary-tree-freelist.go	0.32u 0.01s 0.32r
+	gc binary-tree	3.93u 0.04s 3.97r
+	gc binary-tree-freelist	0.47u 0.03s 0.50r
+NEW:
+	gcc -O2 binary-tree.c -lm	0.60u 0.00s 0.59r
+	gccgo -O2 binary-tree.go	1.53u 0.00s 1.52r
+	gccgo -O2 binary-tree-freelist.go	0.01u 0.00s 0.00r
+	gc binary-tree	1.93u 0.02s 1.95r
+	gc binary-tree-freelist	0.32u 0.01s 0.32r
+
+fannkuch 12
+OLD:
+	gcc -O2 fannkuch.c	57.64u 0.00s 57.64r
+	gccgo -O2 fannkuch.go	65.56u 0.01s 65.65r
+	gccgo -O2 fannkuch-parallel.go	179.12u 0.00s 49.82r
+	gc fannkuch	126.39u 0.00s 126.39r
+	gc fannkuch-parallel	172.49u 0.02s 45.44r
+	gc_B fannkuch	89.30u 0.00s 89.28r
+NEW:
+	gcc -O2 fannkuch.c	45.17u 0.00s 45.26r
+	gccgo -O2 fannkuch.go	53.63u 0.00s 53.73r
+	gccgo -O2 fannkuch-parallel.go	216.72u 0.00s 58.42r
+	gc fannkuch	108.21u 0.00s 108.44r
+	gc fannkuch-parallel	227.20u 0.00s 57.27r
+	gc_B fannkuch	56.14u 0.00s 56.26r
+
+regex-dna 100000
+OLD:
+	gcc -O2 regex-dna.c -lpcre	0.77u 0.01s 0.78r
+	gccgo -O2 regex-dna.go	10.15u 0.02s 10.23r
+	gccgo -O2 regex-dna-parallel.go	33.81u 3.22s 11.62r
+	gc regex-dna	6.52u 0.04s 6.56r
+	gc regex-dna-parallel	6.84u 0.03s 2.70r
+	gc_B regex-dna	6.83u 0.01s 6.84r
+NEW:
+	gcc -O2 regex-dna.c -lpcre	0.47u 0.00s 0.47r
+	gccgo -O2 regex-dna.go	6.00u 0.00s 6.00r
+	gccgo -O2 regex-dna-parallel.go	44.54u 1.57s 6.51r
+	gc regex-dna	5.41u 0.01s 5.42r
+	gc regex-dna-parallel	5.62u 0.01s 2.20r
+	gc_B regex-dna	5.50u 0.00s 5.50r
+
+spectral-norm 5500
+OLD:
+	gcc -O2 spectral-norm.c -lm	12.29u 0.00s 12.28r
+	gccgo -O2 spectral-norm.go	11.56u 0.00s 11.55r
+	gc spectral-norm	23.98u 0.00s 24.00r
+	gc_B spectral-norm	24.62u 0.00s 24.65r
+NEW:
+	gcc -O2 spectral-norm.c -lm	15.79u 0.00s 15.82r
+	gccgo -O2 spectral-norm.go	15.32u 0.00s 15.35r
+	gc spectral-norm	19.62u 0.01s 19.67r
+	gc_B spectral-norm	19.62u 0.00s 19.66r
+
+k-nucleotide 1000000
+OLD:
+	gcc -O2 k-nucleotide.c	9.82u 0.06s 9.87r
+	gccgo -O2 k-nucleotide.go	8.30u 0.02s 8.32r
+	gccgo -O2 k-nucleotide-parallel.go	8.84u 0.05s 3.02r
+	gc k-nucleotide	15.38u 0.07s 15.44r
+	gc k-nucleotide-parallel	16.40u 0.03s 5.93r
+	gc_B k-nucleotide	15.19u 0.05s 15.23r
+NEW:
+	gcc -O2 -k-nucleotide.c	4.88u 0.03s 4.92r
+	gccgo -O2 k-nucleotide.go	5.94u 0.01s 5.96r
+	gccgo -O2 k-nucleotide-parallel.go	6.44u 0.03s 1.47r
+	gc k-nucleotide	9.61u 0.01s 9.63r
+	gc k-nucleotide-parallel	9.70u 0.00s 3.39r
+	gc_B k-nucleotide	9.19u 0.03s 9.23r
+
+mandelbrot 16000
+OLD:
+	gcc -O2 mandelbrot.c	54.54u 0.00s 54.56r
+	gccgo -O2 mandelbrot.go	59.63u 0.03s 59.67r
+	gc mandelbrot	64.82u 0.00s 64.83r
+	gc_B mandelbrot	64.84u 0.00s 64.91r
+NEW:
+	gcc -O2 mandelbrot.c	36.07u 0.01s 36.15r
+	gccgo -O2 mandelbrot.go	43.57u 0.00s 43.66r
+	gc mandelbrot	60.66u 0.00s 60.79r
+	gc_B mandelbrot	60.90u 0.00s 61.03r
+
+meteor 2098
+OLD:
+	gcc -O2 meteor-contest.c	0.11u 0.00s 0.10r
+	gccgo -O2 meteor-contest.go	0.10u 0.01s 0.10r
+	gc meteor-contest	0.18u 0.00s 0.17r
+	gc_B meteor-contest	0.17u 0.00s 0.16r
+NEW:
+	gcc -O2 meteor-contest.c	0.10u 0.00s 0.09r
+	gccgo -O2 meteor-contest.go	0.10u 0.00s 0.09r
+	gc meteor-contest	0.14u 0.00s 0.14r
+	gc_B meteor-contest	0.13u 0.00s 0.13r
+
+pidigits 10000
+OLD:
+	gcc -O2 pidigits.c -lgmp	2.22u 0.00s 2.21r
+	gccgo -O2 pidigits.go	13.39u 0.00s 13.40r
+	gc pidigits	6.42u 0.04s 6.45r
+	gc_B pidigits	6.45u 0.02s 6.47r
+NEW:
+	gcc -O2 pidigits.c -lgmp	2.27u 0.00s 2.29r
+	gccgo -O2 pidigits.go	9.21u 0.00s 9.22r
+	gc pidigits	3.60u 0.00s 3.60r
+	gc_B pidigits	3.56u 0.02s 3.58r
+
+threadring 50000000
+OLD:
+	gcc -O2 threadring.c -lpthread	34.51u 267.95s 336.12r
+	gccgo -O2 threadring.go	103.51u 588.57s 627.16r
+	gc threadring	54.68u 0.00s 54.73r
+NEW:
+	gcc -O2 threadring.c 32.00u 259.39s 369.74r
+	gccgo -O2 threadring.go	133.06u 546.02s 595.33r
+	gc threadring	16.75u 0.02s 16.80r
+
+chameneos 6000000
+OLD:
+	gcc -O2 chameneosredux.c -lpthread	12.65u 31.02s 13.33r
+	gccgo -O2 chameneosredux.go	47.04u 302.84s 252.29r
+	gc chameneosredux	14.14u 0.00s 14.14r
+NEW:
+	gcc -O2 chameneosredux.c -lpthread	8.05u 63.43s 11.16r
+	gccgo -O2 chameneosredux.go	82.95u 304.37s 207.64r
+	gc chameneosredux	9.42u 0.00s 9.43r
diff --git a/test/bugs/bug324.dir/main.go b/test/bugs/bug324.dir/main.go
deleted file mode 100644
index 4c1a18d..0000000
--- a/test/bugs/bug324.dir/main.go
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import (
-	"./p"
-)
-
-type Exported interface {
-	private()
-}
-
-type Implementation struct{}
-
-func (p *Implementation) private() { println("main.Implementation.private()") }
-
-
-func main() {
-	// nothing unusual here
-	var x Exported
-	x = new(Implementation)
-	x.private()  //  main.Implementation.private()
-
-	// same here - should be and is legal
-	var px p.Exported
-	px = p.X
-	
-	// this assignment is correctly illegal:
-	//	px.private undefined (cannot refer to unexported field or method private)
-	// px.private()
-
-	// this assignment is correctly illegal:
-	//	*Implementation does not implement p.Exported (missing p.private method)
-	// px = new(Implementation)
-
-	// this assignment is correctly illegal:
-	//	p.Exported does not implement Exported (missing private method)
-	// x = px
-
-	// this assignment unexpectedly compiles and then executes
-	x = px.(Exported)
-
-	// this is a legitimate call, but because of the previous assignment,
-	// it invokes the method private in p!
-	x.private()  // p.Implementation.private()
-}
diff --git a/test/bugs/bug324.go b/test/bugs/bug324.go
deleted file mode 100644
index e188515..0000000
--- a/test/bugs/bug324.go
+++ /dev/null
@@ -1,8 +0,0 @@
-// $G $D/$F.dir/p.go && $G $D/$F.dir/main.go && $L main.$A && ! ./$A.out || echo BUG: should fail
-
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Test case for issue 1550
-ignored
diff --git a/test/convert.go b/test/convert.go
index e7361aa..0a75663 100644
--- a/test/convert.go
+++ b/test/convert.go
@@ -8,7 +8,7 @@ package main
 
 import "reflect"
 
-func typeof(x interface{}) string { return reflect.Typeof(x).String() }
+func typeof(x interface{}) string { return reflect.TypeOf(x).String() }
 
 func f() int { return 0 }
 
diff --git a/test/fixedbugs/bug177.go b/test/fixedbugs/bug177.go
index aec3823..a120ad0 100644
--- a/test/fixedbugs/bug177.go
+++ b/test/fixedbugs/bug177.go
@@ -12,7 +12,7 @@ type S1 struct{ i int }
 type S2 struct{ S1 }
 
 func main() {
-	typ := reflect.Typeof(S2{})
+	typ := reflect.TypeOf(S2{})
 	f := typ.Field(0)
 	if f.Name != "S1" || f.Anonymous != true {
 		println("BUG: ", f.Name, f.Anonymous)
diff --git a/test/fixedbugs/bug248.dir/bug2.go b/test/fixedbugs/bug248.dir/bug2.go
index 4ea187a..b6c816a 100644
--- a/test/fixedbugs/bug248.dir/bug2.go
+++ b/test/fixedbugs/bug248.dir/bug2.go
@@ -38,11 +38,11 @@ func main() {
 	// meaning that reflect data for v0, v1 didn't get confused.
 
 	// path is full (rooted) path name.  check suffix for gc, prefix for gccgo
-	if s := reflect.Typeof(v0).PkgPath(); !strings.HasSuffix(s, "/bug0") && !strings.HasPrefix(s, "bug0") {
+	if s := reflect.TypeOf(v0).PkgPath(); !strings.HasSuffix(s, "/bug0") && !strings.HasPrefix(s, "bug0") {
 		println("bad v0 path", len(s), s)
 		panic("fail")
 	}
-	if s := reflect.Typeof(v1).PkgPath(); !strings.HasSuffix(s, "/bug1") && !strings.HasPrefix(s, "bug1") {
+	if s := reflect.TypeOf(v1).PkgPath(); !strings.HasSuffix(s, "/bug1") && !strings.HasPrefix(s, "bug1") {
 		println("bad v1 path", s)
 		panic("fail")
 	}
diff --git a/test/fixedbugs/bug324.dir/main.go b/test/fixedbugs/bug324.dir/main.go
new file mode 100644
index 0000000..3ab61f3
--- /dev/null
+++ b/test/fixedbugs/bug324.dir/main.go
@@ -0,0 +1,53 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"./p"
+)
+
+type Exported interface {
+	private()
+}
+
+type Implementation struct{}
+
+func (p *Implementation) private() {}
+
+
+func main() {
+	// nothing unusual here
+	var x Exported
+	x = new(Implementation)
+	x.private()  //  main.Implementation.private()
+
+	// same here - should be and is legal
+	var px p.Exported
+	px = p.X
+	
+	// this assignment is correctly illegal:
+	//	px.private undefined (cannot refer to unexported field or method private)
+	// px.private()
+
+	// this assignment is correctly illegal:
+	//	*Implementation does not implement p.Exported (missing p.private method)
+	// px = new(Implementation)
+
+	// this assignment is correctly illegal:
+	//	p.Exported does not implement Exported (missing private method)
+	// x = px
+
+	// this assignment unexpectedly compiles and then executes
+	defer func() {
+		recover()
+	}()
+	x = px.(Exported)
+	
+	println("should not get this far")
+
+	// this is a legitimate call, but because of the previous assignment,
+	// it invokes the method private in p!
+	x.private()  // p.Implementation.private()
+}
diff --git a/test/bugs/bug324.dir/p.go b/test/fixedbugs/bug324.dir/p.go
similarity index 100%
rename from test/bugs/bug324.dir/p.go
rename to test/fixedbugs/bug324.dir/p.go
diff --git a/test/fixedbugs/bug324.go b/test/fixedbugs/bug324.go
new file mode 100644
index 0000000..3da7563
--- /dev/null
+++ b/test/fixedbugs/bug324.go
@@ -0,0 +1,8 @@
+// $G $D/$F.dir/p.go && $G $D/$F.dir/main.go && $L main.$A && ./$A.out
+
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test case for issue 1550
+ignored
diff --git a/test/fixedbugs/bug328.go b/test/fixedbugs/bug328.go
new file mode 100644
index 0000000..64041f4
--- /dev/null
+++ b/test/fixedbugs/bug328.go
@@ -0,0 +1,14 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "unsafe"
+
+func main() {
+	var p unsafe.Pointer
+	println(p)
+}
diff --git a/test/fixedbugs/bug329.go b/test/fixedbugs/bug329.go
new file mode 100644
index 0000000..0b7074d
--- /dev/null
+++ b/test/fixedbugs/bug329.go
@@ -0,0 +1,46 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+type Value struct {
+	X interface{}
+	Y int
+}
+
+type Struct struct {
+	X complex128
+}
+
+const magic = 1 + 2i
+
+func (Value) Complex(x complex128) {
+	if x != magic {
+		println(x)
+		panic("bad complex magic")
+	}
+}
+
+func f(x *byte, y, z int) complex128 {
+	return magic
+}
+
+func (Value) Struct(x Struct) {
+	if x.X != magic {
+		println(x.X)
+		panic("bad struct magic")
+	}
+}
+
+func f1(x *byte, y, z int) Struct {
+	return Struct{magic}
+}
+
+func main() {
+	var v Value
+	v.Struct(f1(nil, 0, 0)) // ok
+	v.Complex(f(nil, 0, 0)) // used to fail
+}
diff --git a/test/fixedbugs/bug330.go b/test/fixedbugs/bug330.go
new file mode 100644
index 0000000..cf1d6cc
--- /dev/null
+++ b/test/fixedbugs/bug330.go
@@ -0,0 +1,13 @@
+// errchk $G -e $D/$F.go
+
+// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main() {
+	x := ""
+	x = +"hello"  // ERROR "invalid operation.*string"
+	x = +x  // ERROR "invalid operation.*string"
+}
diff --git a/test/fixedbugs/bug331.go b/test/fixedbugs/bug331.go
new file mode 100644
index 0000000..28aee1d
--- /dev/null
+++ b/test/fixedbugs/bug331.go
@@ -0,0 +1,36 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out || echo BUG: bug331
+
+// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "os"
+
+func f() (_ string, x float64, err os.Error) {
+	return
+}
+
+func g() (_ string, x float64, err os.Error) {
+	return "hello", 3.14, os.EOF
+}
+
+var _ func() (string, float64, os.Error) = f
+var _ func() (string, float64, os.Error) = g
+
+func main() {
+	x, y, z := g()
+	if x != "hello" || y != 3.14 || z != os.EOF {
+		println("wrong", x, len(x), y, z)
+	}
+}
+
+/*
+issue 1712
+
+bug331.go:12: cannot use "hello" (type string) as type float64 in assignment
+bug331.go:12: cannot use 0 (type float64) as type os.Error in assignment:
+	float64 does not implement os.Error (missing String method)
+bug331.go:12: error in shape across RETURN
+*/
diff --git a/test/fixedbugs/bug332.go b/test/fixedbugs/bug332.go
new file mode 100644
index 0000000..be79286
--- /dev/null
+++ b/test/fixedbugs/bug332.go
@@ -0,0 +1,17 @@
+// errchk $G $D/$F.go
+
+// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+// type T int
+
+func main() {}
+
+// issue 1474
+
+// important: no newline on end of next line.
+// 6g used to print <epoch> instead of bug332.go:111 
+func (t *T) F() {} // ERROR "bug332"
\ No newline at end of file
diff --git a/test/fixedbugs/bug333.go b/test/fixedbugs/bug333.go
new file mode 100644
index 0000000..515c1f3
--- /dev/null
+++ b/test/fixedbugs/bug333.go
@@ -0,0 +1,19 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 1709
+
+package main
+
+func main() {
+       type Ts string
+       var ts Ts
+       _ = []byte(ts)
+}
+
+/*
+bug333.go:14: cannot use ts (type Ts) as type string in function argument
+*/
diff --git a/test/fixedbugs/bug334.go b/test/fixedbugs/bug334.go
new file mode 100644
index 0000000..870c9ae
--- /dev/null
+++ b/test/fixedbugs/bug334.go
@@ -0,0 +1,31 @@
+// $G $D/$F.go || echo BUG: bug334
+
+// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 1716
+
+package main
+
+type (
+	cplx64  complex64
+	cplx128 complex128
+)
+
+func (c cplx64) Foo()  {}
+func (c cplx128) Foo() {}
+
+func main() {
+	var c64 cplx128
+	var c128 cplx64
+	c64.Foo()
+	c128.Foo()
+}
+
+/*
+bug334.go:16: invalid receiver type cplx64
+bug334.go:17: invalid receiver type cplx128
+bug334.go:22: c64.Foo undefined (type cplx128 has no field or method Foo)
+bug334.go:23: c128.Foo undefined (type cplx64 has no field or method Foo)
+*/
diff --git a/test/fixedbugs/bug335.dir/a.go b/test/fixedbugs/bug335.dir/a.go
new file mode 100644
index 0000000..5a8112a
--- /dev/null
+++ b/test/fixedbugs/bug335.dir/a.go
@@ -0,0 +1,9 @@
+// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+import "./b"
+
+var Bar = b.Foo
diff --git a/test/fixedbugs/bug335.dir/b.go b/test/fixedbugs/bug335.dir/b.go
new file mode 100644
index 0000000..7428c2a
--- /dev/null
+++ b/test/fixedbugs/bug335.dir/b.go
@@ -0,0 +1,11 @@
+// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+type T interface{}
+
+func f() T { return nil }
+
+var Foo T = f()
diff --git a/test/fixedbugs/bug335.go b/test/fixedbugs/bug335.go
new file mode 100644
index 0000000..915b746
--- /dev/null
+++ b/test/fixedbugs/bug335.go
@@ -0,0 +1,10 @@
+// $G $D/$F.dir/b.go && $G $D/$F.dir/a.go
+// rm -f a.$A b.$A
+
+// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 1705.
+
+unused (see script at top of file)
diff --git a/test/fixedbugs/bug336.go b/test/fixedbugs/bug336.go
new file mode 100644
index 0000000..8de3689
--- /dev/null
+++ b/test/fixedbugs/bug336.go
@@ -0,0 +1,86 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+type T1 struct {
+	Next *T2
+}
+
+type T2 T1
+
+type T3 struct {
+	Next *T4
+}
+
+type T4 T5
+type T5 T6
+type T6 T7
+type T7 T8
+type T8 T9
+type T9 T3
+
+type T10 struct {
+	x struct {
+		y ***struct {
+			z *struct {
+				Next *T11
+			}
+		}
+	}
+}
+
+type T11 T10
+
+type T12 struct {
+	F1 *T15
+	F2 *T13
+	F3 *T16
+}
+
+type T13 T14
+type T14 T15
+type T15 T16
+type T16 T17
+type T17 T12
+
+// issue 1672
+type T18 *[10]T19
+type T19 T18
+
+func main() {
+	_ = &T1{&T2{}}
+	_ = &T2{&T2{}}
+	_ = &T3{&T4{}}
+	_ = &T4{&T4{}}
+	_ = &T5{&T4{}}
+	_ = &T6{&T4{}}
+	_ = &T7{&T4{}}
+	_ = &T8{&T4{}}
+	_ = &T9{&T4{}}
+	_ = &T12{&T15{}, &T13{}, &T16{}}
+
+	var (
+		tn    struct{ Next *T11 }
+		tz    struct{ z *struct{ Next *T11 } }
+		tpz   *struct{ z *struct{ Next *T11 } }
+		tppz  **struct{ z *struct{ Next *T11 } }
+		tpppz ***struct{ z *struct{ Next *T11 } }
+		ty    struct {
+			y ***struct{ z *struct{ Next *T11 } }
+		}
+	)
+	tn.Next = &T11{}
+	tz.z = &tn
+	tpz = &tz
+	tppz = &tpz
+	tpppz = &tppz
+	ty.y = tpppz
+	_ = &T10{ty}
+
+	t19s := &[10]T19{}
+	_ = T18(t19s)
+}
diff --git a/test/func7.go b/test/func7.go
new file mode 100644
index 0000000..e38b008
--- /dev/null
+++ b/test/func7.go
@@ -0,0 +1,29 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+var calledf = false
+
+func f() int {
+	calledf = true
+	return 1
+}
+
+func g() int {
+	if !calledf {
+		println("BUG: func7 - called g before f")
+	}
+	return 0
+}
+
+func main() {
+	// 6g, 8g, 5g all used to evaluate g() before f().
+	if f() < g() {
+		panic("wrong answer")
+	}
+}
+
diff --git a/test/golden.out b/test/golden.out
index f76db3e..725e8de 100644
--- a/test/golden.out
+++ b/test/golden.out
@@ -157,14 +157,12 @@ panic: interface conversion: interface is int, not int32
 panic: interface conversion: interface is main.T, not main.T
 
 
+=========== fixedbugs/bug328.go
+0x0
+
 == bugs/
 
 =========== bugs/bug322.go
 bugs/bug322.dir/main.go:19: implicit assignment of unexported field 'x' of lib.T in method receiver
 bugs/bug322.dir/main.go:32: implicit assignment of unexported field 'x' of lib.T in method receiver
 BUG: fails incorrectly
-
-=========== bugs/bug324.go
-main.Implementation.private()
-p.Implementation.private()
-BUG: should fail
diff --git a/test/interface/fake.go b/test/interface/fake.go
index de8505d..bdc5b90 100644
--- a/test/interface/fake.go
+++ b/test/interface/fake.go
@@ -52,7 +52,7 @@ func main() {
 	x.z = x.y
 
 	// check mem and string
-	v := reflect.NewValue(x)
+	v := reflect.ValueOf(x)
 	i := v.Field(0)
 	j := v.Field(1)
 	assert(i.Interface() == j.Interface())
diff --git a/test/interface/pointer.go b/test/interface/pointer.go
index e628b55..076469c 100644
--- a/test/interface/pointer.go
+++ b/test/interface/pointer.go
@@ -33,4 +33,5 @@ func main() {
 	print("call addinst\n")
 	var x Inst = AddInst(new(Start)) // ERROR "pointer to interface"
 	print("return from  addinst\n")
+	var x *Inst = new(Start)  // ERROR "pointer to interface"
 }
diff --git a/test/ken/cplx3.go b/test/ken/cplx3.go
index 979e53f..fa6ff1d 100644
--- a/test/ken/cplx3.go
+++ b/test/ken/cplx3.go
@@ -25,7 +25,7 @@ func main() {
 	println(c)
 
 	var a interface{}
-	switch c := reflect.NewValue(a); c.Kind() {
+	switch c := reflect.ValueOf(a); c.Kind() {
 	case reflect.Complex64, reflect.Complex128:
 		v := c.Complex()
 		_, _ = complex128(v), true
diff --git a/test/method2.go b/test/method2.go
index a72536e..2fdc9fc 100644
--- a/test/method2.go
+++ b/test/method2.go
@@ -12,8 +12,14 @@ type T struct {
 type P *T
 type P1 *T
 
-func (p P) val() int   { return 1 } // ERROR "receiver"
-func (p *P1) val() int { return 1 } // ERROR "receiver"
+func (p P) val() int   { return 1 } // ERROR "receiver.* pointer"
+func (p *P1) val() int { return 1 } // ERROR "receiver.* pointer"
+
+type I interface{}
+type I1 interface{}
+
+func (p I) val() int { return 1 } // ERROR "receiver.*interface"
+func (p *I1) val() int { return 1 } // ERROR "receiver.*interface"
 
 type Val interface {
 	val() int

-- 
Packaging for Google Go



More information about the Pkg-google-commits mailing list